From f77236aa3832a5a0f050e097c60189b9b6a19969 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Tue, 26 Oct 2021 22:04:18 +0100 Subject: [PATCH 01/59] Laravel 7.x Shift (#3011) * Apply Laravel coding style * Shift bindings * Shift core files * Shift to Throwable * Add laravel/ui dependency * Shift Eloquent methods * Shift config files * Shift Laravel dependencies * Shift cleanup * Shift test config and references * Applied styleci changes * Applied fixes post shift to laravel 7 Co-authored-by: Shift --- app/Actions/Activity.php | 2 +- app/Api/ApiToken.php | 2 +- app/Api/ApiTokenGuard.php | 4 +- app/Auth/Role.php | 6 +- app/Auth/SocialAccount.php | 2 +- app/Auth/User.php | 6 +- app/Config/mail.php | 2 + app/Entities/Models/Deletion.php | 2 +- app/Entities/Models/Entity.php | 10 +- app/Entities/Models/Page.php | 2 +- app/Entities/Tools/SearchOptions.php | 4 +- app/Entities/Tools/SearchRunner.php | 2 +- app/Exceptions/Handler.php | 9 +- app/Exceptions/NotifyException.php | 2 +- app/Exceptions/PrettyException.php | 2 +- .../StoppedAuthenticationException.php | 2 +- app/Http/Controllers/PageController.php | 2 +- app/Http/Middleware/TrustHosts.php | 20 + app/Uploads/Attachment.php | 2 +- composer.json | 31 +- composer.lock | 2589 ++++++++--------- ..._08_04_115700_create_bookshelves_table.php | 12 +- phpunit.xml | 9 +- resources/lang/ar/auth.php | 4 +- resources/lang/ar/common.php | 2 +- resources/lang/ar/entities.php | 2 +- resources/lang/ar/passwords.php | 2 +- resources/lang/ar/settings.php | 6 +- resources/lang/bg/auth.php | 4 +- resources/lang/bg/common.php | 2 +- resources/lang/bg/entities.php | 2 +- resources/lang/bg/passwords.php | 2 +- resources/lang/bg/settings.php | 6 +- resources/lang/bs/auth.php | 4 +- resources/lang/bs/common.php | 2 +- resources/lang/bs/entities.php | 2 +- resources/lang/bs/passwords.php | 2 +- resources/lang/bs/settings.php | 4 +- resources/lang/ca/auth.php | 4 +- resources/lang/ca/common.php | 2 +- resources/lang/ca/entities.php | 2 +- resources/lang/ca/settings.php | 4 +- resources/lang/cs/auth.php | 4 +- resources/lang/cs/common.php | 2 +- resources/lang/cs/entities.php | 4 +- resources/lang/cs/passwords.php | 2 +- resources/lang/cs/settings.php | 6 +- resources/lang/da/auth.php | 4 +- resources/lang/da/common.php | 2 +- resources/lang/da/entities.php | 2 +- resources/lang/da/passwords.php | 2 +- resources/lang/da/settings.php | 6 +- resources/lang/de/auth.php | 4 +- resources/lang/de/common.php | 2 +- resources/lang/de/entities.php | 2 +- resources/lang/de/passwords.php | 2 +- resources/lang/de/settings.php | 6 +- resources/lang/de_informal/auth.php | 4 +- resources/lang/de_informal/common.php | 2 +- resources/lang/de_informal/entities.php | 2 +- resources/lang/de_informal/passwords.php | 2 +- resources/lang/de_informal/settings.php | 6 +- resources/lang/en/auth.php | 4 +- resources/lang/en/common.php | 2 +- resources/lang/en/entities.php | 2 +- resources/lang/en/settings.php | 4 +- resources/lang/es/auth.php | 4 +- resources/lang/es/common.php | 2 +- resources/lang/es/entities.php | 2 +- resources/lang/es/passwords.php | 2 +- resources/lang/es/settings.php | 6 +- resources/lang/es_AR/auth.php | 4 +- resources/lang/es_AR/common.php | 2 +- resources/lang/es_AR/entities.php | 2 +- resources/lang/es_AR/passwords.php | 2 +- resources/lang/es_AR/settings.php | 6 +- resources/lang/et/auth.php | 4 +- resources/lang/et/common.php | 2 +- resources/lang/et/entities.php | 2 +- resources/lang/et/passwords.php | 2 +- resources/lang/et/settings.php | 6 +- resources/lang/fa/auth.php | 4 +- resources/lang/fa/common.php | 2 +- resources/lang/fa/entities.php | 2 +- resources/lang/fa/passwords.php | 2 +- resources/lang/fa/settings.php | 4 +- resources/lang/fr/auth.php | 4 +- resources/lang/fr/common.php | 2 +- resources/lang/fr/entities.php | 4 +- resources/lang/fr/settings.php | 4 +- resources/lang/he/auth.php | 4 +- resources/lang/he/common.php | 2 +- resources/lang/he/entities.php | 4 +- resources/lang/he/passwords.php | 2 +- resources/lang/he/settings.php | 6 +- resources/lang/hr/auth.php | 4 +- resources/lang/hr/common.php | 2 +- resources/lang/hr/entities.php | 2 +- resources/lang/hr/settings.php | 4 +- resources/lang/hu/auth.php | 4 +- resources/lang/hu/common.php | 2 +- resources/lang/hu/entities.php | 2 +- resources/lang/hu/passwords.php | 2 +- resources/lang/hu/settings.php | 6 +- resources/lang/id/auth.php | 4 +- resources/lang/id/common.php | 2 +- resources/lang/id/entities.php | 2 +- resources/lang/id/passwords.php | 2 +- resources/lang/id/settings.php | 6 +- resources/lang/it/auth.php | 4 +- resources/lang/it/common.php | 2 +- resources/lang/it/entities.php | 2 +- resources/lang/it/passwords.php | 2 +- resources/lang/it/settings.php | 6 +- resources/lang/ja/auth.php | 4 +- resources/lang/ja/common.php | 2 +- resources/lang/ja/entities.php | 4 +- resources/lang/ja/passwords.php | 2 +- resources/lang/ja/settings.php | 6 +- resources/lang/ko/auth.php | 4 +- resources/lang/ko/common.php | 2 +- resources/lang/ko/entities.php | 6 +- resources/lang/ko/errors.php | 2 +- resources/lang/ko/passwords.php | 2 +- resources/lang/ko/settings.php | 6 +- resources/lang/lt/auth.php | 4 +- resources/lang/lt/common.php | 2 +- resources/lang/lt/entities.php | 2 +- resources/lang/lt/settings.php | 4 +- resources/lang/lv/auth.php | 4 +- resources/lang/lv/common.php | 2 +- resources/lang/lv/entities.php | 4 +- resources/lang/lv/passwords.php | 2 +- resources/lang/lv/settings.php | 6 +- resources/lang/nb/auth.php | 4 +- resources/lang/nb/common.php | 2 +- resources/lang/nb/entities.php | 2 +- resources/lang/nb/passwords.php | 2 +- resources/lang/nb/settings.php | 6 +- resources/lang/nl/auth.php | 4 +- resources/lang/nl/common.php | 2 +- resources/lang/nl/entities.php | 2 +- resources/lang/nl/passwords.php | 2 +- resources/lang/nl/settings.php | 6 +- resources/lang/pl/auth.php | 4 +- resources/lang/pl/common.php | 2 +- resources/lang/pl/entities.php | 2 +- resources/lang/pl/passwords.php | 2 +- resources/lang/pl/settings.php | 6 +- resources/lang/pt/auth.php | 4 +- resources/lang/pt/common.php | 2 +- resources/lang/pt/entities.php | 2 +- resources/lang/pt/passwords.php | 2 +- resources/lang/pt/settings.php | 6 +- resources/lang/pt_BR/auth.php | 4 +- resources/lang/pt_BR/common.php | 2 +- resources/lang/pt_BR/entities.php | 2 +- resources/lang/pt_BR/passwords.php | 2 +- resources/lang/pt_BR/settings.php | 6 +- resources/lang/ru/auth.php | 4 +- resources/lang/ru/common.php | 2 +- resources/lang/ru/entities.php | 4 +- resources/lang/ru/errors.php | 2 +- resources/lang/ru/passwords.php | 2 +- resources/lang/ru/settings.php | 6 +- resources/lang/sk/auth.php | 4 +- resources/lang/sk/common.php | 2 +- resources/lang/sk/entities.php | 2 +- resources/lang/sk/passwords.php | 2 +- resources/lang/sk/settings.php | 6 +- resources/lang/sl/auth.php | 4 +- resources/lang/sl/common.php | 2 +- resources/lang/sl/entities.php | 2 +- resources/lang/sl/passwords.php | 2 +- resources/lang/sl/settings.php | 6 +- resources/lang/sv/auth.php | 4 +- resources/lang/sv/common.php | 2 +- resources/lang/sv/entities.php | 2 +- resources/lang/sv/passwords.php | 2 +- resources/lang/sv/settings.php | 6 +- resources/lang/th/auth.php | 6 +- resources/lang/th/common.php | 2 +- resources/lang/th/entities.php | 4 +- resources/lang/th/settings.php | 4 +- resources/lang/tr/auth.php | 4 +- resources/lang/tr/common.php | 2 +- resources/lang/tr/entities.php | 4 +- resources/lang/tr/passwords.php | 2 +- resources/lang/tr/settings.php | 6 +- resources/lang/uk/auth.php | 4 +- resources/lang/uk/common.php | 2 +- resources/lang/uk/entities.php | 2 +- resources/lang/uk/passwords.php | 2 +- resources/lang/uk/settings.php | 6 +- resources/lang/vi/auth.php | 4 +- resources/lang/vi/common.php | 2 +- resources/lang/vi/entities.php | 2 +- resources/lang/vi/passwords.php | 2 +- resources/lang/vi/settings.php | 6 +- resources/lang/zh_CN/auth.php | 4 +- resources/lang/zh_CN/common.php | 2 +- resources/lang/zh_CN/entities.php | 2 +- resources/lang/zh_CN/passwords.php | 2 +- resources/lang/zh_CN/settings.php | 6 +- resources/lang/zh_TW/auth.php | 4 +- resources/lang/zh_TW/common.php | 2 +- resources/lang/zh_TW/entities.php | 4 +- resources/lang/zh_TW/passwords.php | 2 +- resources/lang/zh_TW/settings.php | 6 +- tests/Api/AttachmentsApiTest.php | 2 +- tests/Auth/MfaConfigurationTest.php | 6 +- tests/Auth/Saml2Test.php | 2 +- tests/Entity/BookShelfTest.php | 2 +- tests/Entity/BookTest.php | 2 +- tests/Entity/CommentTest.php | 6 +- tests/Entity/ExportTest.php | 14 +- tests/Entity/PageContentTest.php | 16 +- tests/Permissions/RolesTest.php | 6 +- tests/SecurityHeaderTest.php | 2 +- tests/Settings/CustomHeadContentTest.php | 8 +- tests/Settings/FooterLinksTest.php | 8 +- tests/SharedTestHelpers.php | 4 +- tests/TestResponse.php | 2 +- tests/Uploads/AttachmentTest.php | 4 +- tests/Uploads/DrawioTest.php | 6 +- 225 files changed, 1618 insertions(+), 1804 deletions(-) create mode 100644 app/Http/Middleware/TrustHosts.php diff --git a/app/Actions/Activity.php b/app/Actions/Activity.php index 6a8a9bcd0..3b1408cb9 100644 --- a/app/Actions/Activity.php +++ b/app/Actions/Activity.php @@ -61,7 +61,7 @@ class Activity extends Model /** * Checks if another Activity matches the general information of another. */ - public function isSimilarTo(Activity $activityB): bool + public function isSimilarTo(self $activityB): bool { return [$this->type, $this->entity_type, $this->entity_id] === [$activityB->type, $activityB->entity_type, $activityB->entity_id]; } diff --git a/app/Api/ApiToken.php b/app/Api/ApiToken.php index f44fde19a..70b289ae1 100644 --- a/app/Api/ApiToken.php +++ b/app/Api/ApiToken.php @@ -43,7 +43,7 @@ class ApiToken extends Model implements Loggable } /** - * @inheritdoc + * {@inheritdoc} */ public function logDescriptor(): string { diff --git a/app/Api/ApiTokenGuard.php b/app/Api/ApiTokenGuard.php index 8b9cbc8e1..1bb672556 100644 --- a/app/Api/ApiTokenGuard.php +++ b/app/Api/ApiTokenGuard.php @@ -42,7 +42,7 @@ class ApiTokenGuard implements Guard } /** - * @inheritDoc + * {@inheritdoc} */ public function user() { @@ -152,7 +152,7 @@ class ApiTokenGuard implements Guard } /** - * @inheritDoc + * {@inheritdoc} */ public function validate(array $credentials = []) { diff --git a/app/Auth/Role.php b/app/Auth/Role.php index 46921caeb..fc2e39aa9 100644 --- a/app/Auth/Role.php +++ b/app/Auth/Role.php @@ -83,7 +83,7 @@ class Role extends Model implements Loggable /** * Get the role of the specified display name. */ - public static function getRole(string $displayName): ?Role + public static function getRole(string $displayName): ?self { return static::query()->where('display_name', '=', $displayName)->first(); } @@ -91,7 +91,7 @@ class Role extends Model implements Loggable /** * Get the role object for the specified system role. */ - public static function getSystemRole(string $systemName): ?Role + public static function getSystemRole(string $systemName): ?self { return static::query()->where('system_name', '=', $systemName)->first(); } @@ -116,7 +116,7 @@ class Role extends Model implements Loggable } /** - * @inheritdoc + * {@inheritdoc} */ public function logDescriptor(): string { diff --git a/app/Auth/SocialAccount.php b/app/Auth/SocialAccount.php index f076ecdd4..6cf0224a8 100644 --- a/app/Auth/SocialAccount.php +++ b/app/Auth/SocialAccount.php @@ -21,7 +21,7 @@ class SocialAccount extends Model implements Loggable } /** - * @inheritDoc + * {@inheritdoc} */ public function logDescriptor(): string { diff --git a/app/Auth/User.php b/app/Auth/User.php index 0a6849fe0..aa8b44e9f 100644 --- a/app/Auth/User.php +++ b/app/Auth/User.php @@ -90,7 +90,7 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon /** * Returns the default public user. */ - public static function getDefault(): User + public static function getDefault(): self { if (!is_null(static::$defaultUser)) { return static::$defaultUser; @@ -336,7 +336,7 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon } /** - * @inheritdoc + * {@inheritdoc} */ public function logDescriptor(): string { @@ -344,7 +344,7 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon } /** - * @inheritDoc + * {@inheritdoc} */ public function refreshSlug(): string { diff --git a/app/Config/mail.php b/app/Config/mail.php index 34b28fe2a..b223e382a 100644 --- a/app/Config/mail.php +++ b/app/Config/mail.php @@ -11,6 +11,8 @@ return [ // Mail driver to use. + // From Laravel 7+ this is MAIL_MAILER in laravel. + // Kept as MAIL_DRIVER in BookStack to prevent breaking change. // Options: smtp, sendmail, log, array 'driver' => env('MAIL_DRIVER', 'smtp'), diff --git a/app/Entities/Models/Deletion.php b/app/Entities/Models/Deletion.php index 764c4a1e3..dab89ce37 100644 --- a/app/Entities/Models/Deletion.php +++ b/app/Entities/Models/Deletion.php @@ -32,7 +32,7 @@ class Deletion extends Model implements Loggable /** * Create a new deletion record for the provided entity. */ - public static function createForEntity(Entity $entity): Deletion + public static function createForEntity(Entity $entity): self { $record = (new self())->forceFill([ 'deleted_by' => user()->id, diff --git a/app/Entities/Models/Entity.php b/app/Entities/Models/Entity.php index a02926c4d..f5f9d91f0 100644 --- a/app/Entities/Models/Entity.php +++ b/app/Entities/Models/Entity.php @@ -106,7 +106,7 @@ abstract class Entity extends Model implements Sluggable, Favouritable, Viewable * Compares this entity to another given entity. * Matches by comparing class and id. */ - public function matches(Entity $entity): bool + public function matches(self $entity): bool { return [get_class($this), $this->id] === [get_class($entity), $entity->id]; } @@ -114,7 +114,7 @@ abstract class Entity extends Model implements Sluggable, Favouritable, Viewable /** * Checks if the current entity matches or contains the given. */ - public function matchesOrContains(Entity $entity): bool + public function matchesOrContains(self $entity): bool { if ($this->matches($entity)) { return true; @@ -270,7 +270,7 @@ abstract class Entity extends Model implements Sluggable, Favouritable, Viewable * This is the "static" parent and does not include dynamic * relations such as shelves to books. */ - public function getParent(): ?Entity + public function getParent(): ?self { if ($this instanceof Page) { return $this->chapter_id ? $this->chapter()->withTrashed()->first() : $this->book()->withTrashed()->first(); @@ -300,7 +300,7 @@ abstract class Entity extends Model implements Sluggable, Favouritable, Viewable } /** - * @inheritdoc + * {@inheritdoc} */ public function refreshSlug(): string { @@ -310,7 +310,7 @@ abstract class Entity extends Model implements Sluggable, Favouritable, Viewable } /** - * @inheritdoc + * {@inheritdoc} */ public function favourites(): MorphMany { diff --git a/app/Entities/Models/Page.php b/app/Entities/Models/Page.php index 601e9630d..452965667 100644 --- a/app/Entities/Models/Page.php +++ b/app/Entities/Models/Page.php @@ -129,7 +129,7 @@ class Page extends BookChild /** * Get this page for JSON display. */ - public function forJsonDisplay(): Page + public function forJsonDisplay(): self { $refreshed = $this->refresh()->unsetRelations()->load(['tags', 'createdBy', 'updatedBy', 'ownedBy']); $refreshed->setHidden(array_diff($refreshed->getHidden(), ['html', 'markdown'])); diff --git a/app/Entities/Tools/SearchOptions.php b/app/Entities/Tools/SearchOptions.php index 7913e0969..5ce64cc65 100644 --- a/app/Entities/Tools/SearchOptions.php +++ b/app/Entities/Tools/SearchOptions.php @@ -29,7 +29,7 @@ class SearchOptions /** * Create a new instance from a search string. */ - public static function fromString(string $search): SearchOptions + public static function fromString(string $search): self { $decoded = static::decode($search); $instance = new static(); @@ -45,7 +45,7 @@ class SearchOptions * Will look for a classic string term and use that * Otherwise we'll use the details from an advanced search form. */ - public static function fromRequest(Request $request): SearchOptions + public static function fromRequest(Request $request): self { if (!$request->has('search') && !$request->has('term')) { return static::fromString(''); diff --git a/app/Entities/Tools/SearchRunner.php b/app/Entities/Tools/SearchRunner.php index ca592755b..df566eb0b 100644 --- a/app/Entities/Tools/SearchRunner.php +++ b/app/Entities/Tools/SearchRunner.php @@ -196,7 +196,7 @@ class SearchRunner $escapedOperators[] = preg_quote($operator); } - return join('|', $escapedOperators); + return implode('|', $escapedOperators); } /** diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index 2d40f4476..63b5cfc5a 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -9,6 +9,7 @@ use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Illuminate\Validation\ValidationException; use Symfony\Component\HttpKernel\Exception\HttpException; +use Throwable; class Handler extends ExceptionHandler { @@ -34,13 +35,13 @@ class Handler extends ExceptionHandler /** * Report or log an exception. * - * @param Exception $exception + * @param \Throwable $exception * - * @throws Exception + * @throws \Throwable * * @return void */ - public function report(Exception $exception) + public function report(Throwable $exception) { parent::report($exception); } @@ -53,7 +54,7 @@ class Handler extends ExceptionHandler * * @return \Illuminate\Http\Response */ - public function render($request, Exception $e) + public function render($request, Throwable $e) { if ($this->isApiRequest($request)) { return $this->renderApiException($e); diff --git a/app/Exceptions/NotifyException.php b/app/Exceptions/NotifyException.php index ef9a44101..8e748a21d 100644 --- a/app/Exceptions/NotifyException.php +++ b/app/Exceptions/NotifyException.php @@ -23,7 +23,7 @@ class NotifyException extends Exception implements Responsable /** * Send the response for this type of exception. * - * @inheritdoc + * {@inheritdoc} */ public function toResponse($request) { diff --git a/app/Exceptions/PrettyException.php b/app/Exceptions/PrettyException.php index 33c1471f2..f446442d0 100644 --- a/app/Exceptions/PrettyException.php +++ b/app/Exceptions/PrettyException.php @@ -20,7 +20,7 @@ class PrettyException extends Exception implements Responsable /** * Render a response for when this exception occurs. * - * @inheritdoc + * {@inheritdoc} */ public function toResponse($request) { diff --git a/app/Exceptions/StoppedAuthenticationException.php b/app/Exceptions/StoppedAuthenticationException.php index d10a6da5e..b9aadb03f 100644 --- a/app/Exceptions/StoppedAuthenticationException.php +++ b/app/Exceptions/StoppedAuthenticationException.php @@ -23,7 +23,7 @@ class StoppedAuthenticationException extends \Exception implements Responsable } /** - * @inheritdoc + * {@inheritdoc} */ public function toResponse($request) { diff --git a/app/Http/Controllers/PageController.php b/app/Http/Controllers/PageController.php index a94a61803..ddb15a7aa 100644 --- a/app/Http/Controllers/PageController.php +++ b/app/Http/Controllers/PageController.php @@ -176,7 +176,7 @@ class PageController extends Controller { $page = $this->pageRepo->getById($pageId); $page->setHidden(array_diff($page->getHidden(), ['html', 'markdown'])); - $page->addHidden(['book']); + $page->makeHidden(['book']); return response()->json($page); } diff --git a/app/Http/Middleware/TrustHosts.php b/app/Http/Middleware/TrustHosts.php new file mode 100644 index 000000000..b0550cfc7 --- /dev/null +++ b/app/Http/Middleware/TrustHosts.php @@ -0,0 +1,20 @@ +allSubdomainsOfApplicationUrl(), + ]; + } +} diff --git a/app/Uploads/Attachment.php b/app/Uploads/Attachment.php index a470ec534..5e637246a 100644 --- a/app/Uploads/Attachment.php +++ b/app/Uploads/Attachment.php @@ -93,7 +93,7 @@ class Attachment extends Model return $permissionService->filterRelatedEntity( Page::class, - Attachment::query(), + self::query(), 'attachments', 'uploaded_to' ); diff --git a/composer.json b/composer.json index fa2c0c2b5..b50cee762 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,10 @@ { "name": "bookstackapp/bookstack", "description": "BookStack documentation platform", - "keywords": ["BookStack", "Documentation"], + "keywords": [ + "BookStack", + "Documentation" + ], "license": "MIT", "type": "project", "require": { @@ -16,17 +19,16 @@ "bacon/bacon-qr-code": "^2.0", "barryvdh/laravel-dompdf": "^0.9.0", "barryvdh/laravel-snappy": "^0.4.8", - "doctrine/dbal": "^2.12.1", + "doctrine/dbal": "^3.1", "fideloper/proxy": "^4.4.1", "filp/whoops": "^2.14", - "intervention/image": "^2.5.1", - "laravel/framework": "^6.20.33", - "laravel/socialite": "^5.1", + "intervention/image": "^2.7", + "laravel/framework": "^7.29", + "laravel/socialite": "^5.2", "league/commonmark": "^1.5", "league/flysystem-aws-s3-v3": "^1.0.29", "league/html-to-markdown": "^5.0.0", "league/oauth2-client": "^2.6", - "nunomaduro/collision": "^3.1", "onelogin/php-saml": "^4.0", "phpseclib/phpseclib": "~3.0", "pragmarx/google2fa": "^8.0", @@ -37,15 +39,18 @@ "socialiteproviders/okta": "^4.1", "socialiteproviders/slack": "^4.1", "socialiteproviders/twitch": "^5.3", - "ssddanbrown/htmldiff": "^v1.0.1" + "ssddanbrown/htmldiff": "^1.0.1", + "laravel/ui": "^2.5", + "guzzlehttp/guzzle": "^7.4.0", + "laravel/tinker": "^2.5" }, "require-dev": { - "barryvdh/laravel-debugbar": "^3.5.1", - "barryvdh/laravel-ide-helper": "^2.8.2", + "barryvdh/laravel-debugbar": "^3.6", "fakerphp/faker": "^1.13.0", "mockery/mockery": "^1.3.3", "phpunit/phpunit": "^9.5.3", - "symfony/dom-crawler": "^5.3" + "symfony/dom-crawler": "^5.3", + "nunomaduro/collision": "^4.3" }, "autoload": { "classmap": [ @@ -55,9 +60,9 @@ "psr-4": { "BookStack\\": "app/" }, - "files": [ - "app/helpers.php" - ] + "files": [ + "app/helpers.php" + ] }, "autoload-dev": { "psr-4": { diff --git a/composer.lock b/composer.lock index 318544c5a..f07d61062 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "fc6d8f731e3975127a9101802cc4bb3a", + "content-hash": "491a3de7d49182613d0c81032a7001e1", "packages": [ { "name": "aws/aws-crt-php", @@ -58,16 +58,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.199.3", + "version": "3.199.4", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "132a1148ebb63d04023837bcf9a36f49b308a0bd" + "reference": "047f6ce04b1de9320ca00bf393d6f03b9d036fa5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/132a1148ebb63d04023837bcf9a36f49b308a0bd", - "reference": "132a1148ebb63d04023837bcf9a36f49b308a0bd", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/047f6ce04b1de9320ca00bf393d6f03b9d036fa5", + "reference": "047f6ce04b1de9320ca00bf393d6f03b9d036fa5", "shasum": "" }, "require": { @@ -143,9 +143,9 @@ "support": { "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.199.3" + "source": "https://github.com/aws/aws-sdk-php/tree/3.199.4" }, - "time": "2021-10-25T18:17:28+00:00" + "time": "2021-10-26T18:14:35+00:00" }, { "name": "bacon/bacon-qr-code", @@ -331,6 +331,139 @@ }, "time": "2020-09-07T12:33:10+00:00" }, + { + "name": "brick/math", + "version": "0.9.3", + "source": { + "type": "git", + "url": "https://github.com/brick/math.git", + "reference": "ca57d18f028f84f777b2168cd1911b0dee2343ae" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/brick/math/zipball/ca57d18f028f84f777b2168cd1911b0dee2343ae", + "reference": "ca57d18f028f84f777b2168cd1911b0dee2343ae", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.2", + "phpunit/phpunit": "^7.5.15 || ^8.5 || ^9.0", + "vimeo/psalm": "4.9.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Brick\\Math\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Arbitrary-precision arithmetic library", + "keywords": [ + "Arbitrary-precision", + "BigInteger", + "BigRational", + "arithmetic", + "bigdecimal", + "bignum", + "brick", + "math" + ], + "support": { + "issues": "https://github.com/brick/math/issues", + "source": "https://github.com/brick/math/tree/0.9.3" + }, + "funding": [ + { + "url": "https://github.com/BenMorel", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/brick/math", + "type": "tidelift" + } + ], + "time": "2021-08-15T20:50:18+00:00" + }, + { + "name": "composer/package-versions-deprecated", + "version": "1.11.99.4", + "source": { + "type": "git", + "url": "https://github.com/composer/package-versions-deprecated.git", + "reference": "b174585d1fe49ceed21928a945138948cb394600" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/package-versions-deprecated/zipball/b174585d1fe49ceed21928a945138948cb394600", + "reference": "b174585d1fe49ceed21928a945138948cb394600", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.1.0 || ^2.0", + "php": "^7 || ^8" + }, + "replace": { + "ocramius/package-versions": "1.11.99" + }, + "require-dev": { + "composer/composer": "^1.9.3 || ^2.0@dev", + "ext-zip": "^1.13", + "phpunit/phpunit": "^6.5 || ^7" + }, + "type": "composer-plugin", + "extra": { + "class": "PackageVersions\\Installer", + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "PackageVersions\\": "src/PackageVersions" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be" + } + ], + "description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)", + "support": { + "issues": "https://github.com/composer/package-versions-deprecated/issues", + "source": "https://github.com/composer/package-versions-deprecated/tree/1.11.99.4" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2021-09-13T08:41:34+00:00" + }, { "name": "dasprid/enum", "version": "1.0.3", @@ -479,34 +612,35 @@ }, { "name": "doctrine/dbal", - "version": "2.13.4", + "version": "3.1.3", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "2411a55a2a628e6d8dd598388ab13474802c7b6e" + "reference": "96b0053775a544b4a6ab47654dac0621be8b4cf8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/2411a55a2a628e6d8dd598388ab13474802c7b6e", - "reference": "2411a55a2a628e6d8dd598388ab13474802c7b6e", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/96b0053775a544b4a6ab47654dac0621be8b4cf8", + "reference": "96b0053775a544b4a6ab47654dac0621be8b4cf8", "shasum": "" }, "require": { + "composer/package-versions-deprecated": "^1.11.99", "doctrine/cache": "^1.0|^2.0", "doctrine/deprecations": "^0.5.3", "doctrine/event-manager": "^1.0", - "ext-pdo": "*", - "php": "^7.1 || ^8" + "php": "^7.3 || ^8.0" }, "require-dev": { "doctrine/coding-standard": "9.0.0", "jetbrains/phpstorm-stubs": "2021.1", "phpstan/phpstan": "0.12.99", - "phpunit/phpunit": "^7.5.20|^8.5|9.5.10", + "phpstan/phpstan-strict-rules": "^0.12.11", + "phpunit/phpunit": "9.5.10", "psalm/plugin-phpunit": "0.16.1", "squizlabs/php_codesniffer": "3.6.0", - "symfony/cache": "^4.4", - "symfony/console": "^2.0.5|^3.0|^4.0|^5.0", + "symfony/cache": "^5.2|^6.0", + "symfony/console": "^2.0.5|^3.0|^4.0|^5.0|^6.0", "vimeo/psalm": "4.10.0" }, "suggest": { @@ -518,7 +652,7 @@ "type": "library", "autoload": { "psr-4": { - "Doctrine\\DBAL\\": "lib/Doctrine/DBAL" + "Doctrine\\DBAL\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -561,14 +695,13 @@ "queryobject", "sasql", "sql", - "sqlanywhere", "sqlite", "sqlserver", "sqlsrv" ], "support": { "issues": "https://github.com/doctrine/dbal/issues", - "source": "https://github.com/doctrine/dbal/tree/2.13.4" + "source": "https://github.com/doctrine/dbal/tree/3.1.3" }, "funding": [ { @@ -584,7 +717,7 @@ "type": "tidelift" } ], - "time": "2021-10-02T15:59:26+00:00" + "time": "2021-10-02T16:15:05+00:00" }, { "name": "doctrine/deprecations", @@ -1710,16 +1843,16 @@ }, { "name": "laravel/framework", - "version": "v6.20.36", + "version": "v7.30.4", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "10f6bfaec9efb68aa88d7196b8b1b162d83040ae" + "reference": "9dd38140dc2924daa1a020a3d7a45f9ceff03df3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/10f6bfaec9efb68aa88d7196b8b1b162d83040ae", - "reference": "10f6bfaec9efb68aa88d7196b8b1b162d83040ae", + "url": "https://api.github.com/repos/laravel/framework/zipball/9dd38140dc2924daa1a020a3d7a45f9ceff03df3", + "reference": "9dd38140dc2924daa1a020a3d7a45f9ceff03df3", "shasum": "" }, "require": { @@ -1731,29 +1864,34 @@ "ext-openssl": "*", "league/commonmark": "^1.3", "league/flysystem": "^1.1", - "monolog/monolog": "^1.12|^2.0", + "monolog/monolog": "^2.0", "nesbot/carbon": "^2.31", "opis/closure": "^3.6", "php": "^7.2.5|^8.0", "psr/container": "^1.0", "psr/simple-cache": "^1.0", - "ramsey/uuid": "^3.7", + "ramsey/uuid": "^3.7|^4.0", "swiftmailer/swiftmailer": "^6.0", - "symfony/console": "^4.3.4", - "symfony/debug": "^4.3.4", - "symfony/finder": "^4.3.4", - "symfony/http-foundation": "^4.3.4", - "symfony/http-kernel": "^4.3.4", + "symfony/console": "^5.0", + "symfony/error-handler": "^5.0", + "symfony/finder": "^5.0", + "symfony/http-foundation": "^5.0", + "symfony/http-kernel": "^5.0", + "symfony/mime": "^5.0", "symfony/polyfill-php73": "^1.17", - "symfony/process": "^4.3.4", - "symfony/routing": "^4.3.4", - "symfony/var-dumper": "^4.3.4", - "tijsverkoyen/css-to-inline-styles": "^2.2.1", - "vlucas/phpdotenv": "^3.3" + "symfony/process": "^5.0", + "symfony/routing": "^5.0", + "symfony/var-dumper": "^5.0", + "tijsverkoyen/css-to-inline-styles": "^2.2.2", + "vlucas/phpdotenv": "^4.0", + "voku/portable-ascii": "^1.4.8" }, "conflict": { "tightenco/collect": "<5.5.33" }, + "provide": { + "psr/container-implementation": "1.0" + }, "replace": { "illuminate/auth": "self.version", "illuminate/broadcasting": "self.version", @@ -1780,6 +1918,7 @@ "illuminate/routing": "self.version", "illuminate/session": "self.version", "illuminate/support": "self.version", + "illuminate/testing": "self.version", "illuminate/translation": "self.version", "illuminate/validation": "self.version", "illuminate/view": "self.version" @@ -1792,11 +1931,11 @@ "league/flysystem-cached-adapter": "^1.0", "mockery/mockery": "~1.3.3|^1.4.2", "moontoast/math": "^1.1", - "orchestra/testbench-core": "^4.8", + "orchestra/testbench-core": "^5.8", "pda/pheanstalk": "^4.0", - "phpunit/phpunit": "^7.5.15|^8.4|^9.3.3", + "phpunit/phpunit": "^8.4|^9.3.3", "predis/predis": "^1.1.1", - "symfony/cache": "^4.3.4" + "symfony/cache": "^5.0" }, "suggest": { "aws/aws-sdk-php": "Required to use the SQS queue driver, DynamoDb failed job storage and SES mail driver (^3.155).", @@ -1809,25 +1948,28 @@ "ext-redis": "Required to use the Redis cache and queue drivers (^4.0|^5.0).", "fakerphp/faker": "Required to use the eloquent factory builder (^1.9.1).", "filp/whoops": "Required for friendly error pages in development (^2.8).", - "guzzlehttp/guzzle": "Required to use the Mailgun mail driver and the ping methods on schedules (^6.3.1|^7.0.1).", + "guzzlehttp/guzzle": "Required to use the HTTP Client, Mailgun mail driver and the ping methods on schedules (^6.3.1|^7.0.1).", "laravel/tinker": "Required to use the tinker console command (^2.0).", "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^1.0).", "league/flysystem-cached-adapter": "Required to use the Flysystem cache (^1.0).", "league/flysystem-sftp": "Required to use the Flysystem SFTP driver (^1.0).", + "mockery/mockery": "Required to use mocking (~1.3.3|^1.4.2).", "moontoast/math": "Required to use ordered UUIDs (^1.1).", "nyholm/psr7": "Required to use PSR-7 bridging features (^1.2).", "pda/pheanstalk": "Required to use the beanstalk queue driver (^4.0).", + "phpunit/phpunit": "Required to use assertions and run tests (^8.4|^9.3.3).", "predis/predis": "Required to use the predis connector (^1.1.2).", "psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).", "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^4.0).", - "symfony/cache": "Required to PSR-6 cache bridge (^4.3.4).", - "symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^1.2).", + "symfony/cache": "Required to PSR-6 cache bridge (^5.0).", + "symfony/filesystem": "Required to create relative storage directory symbolic links (^5.0).", + "symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^2.0).", "wildbit/swiftmailer-postmark": "Required to use Postmark mail driver (^3.0)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "6.x-dev" + "dev-master": "7.x-dev" } }, "autoload": { @@ -1859,7 +2001,7 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2021-10-19T13:59:55+00:00" + "time": "2021-01-21T14:10:48+00:00" }, { "name": "laravel/socialite", @@ -1930,6 +2072,129 @@ }, "time": "2021-08-31T15:16:26+00:00" }, + { + "name": "laravel/tinker", + "version": "v2.6.2", + "source": { + "type": "git", + "url": "https://github.com/laravel/tinker.git", + "reference": "c808a7227f97ecfd9219fbf913bad842ea854ddc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/tinker/zipball/c808a7227f97ecfd9219fbf913bad842ea854ddc", + "reference": "c808a7227f97ecfd9219fbf913bad842ea854ddc", + "shasum": "" + }, + "require": { + "illuminate/console": "^6.0|^7.0|^8.0", + "illuminate/contracts": "^6.0|^7.0|^8.0", + "illuminate/support": "^6.0|^7.0|^8.0", + "php": "^7.2.5|^8.0", + "psy/psysh": "^0.10.4", + "symfony/var-dumper": "^4.3.4|^5.0" + }, + "require-dev": { + "mockery/mockery": "~1.3.3|^1.4.2", + "phpunit/phpunit": "^8.5.8|^9.3.3" + }, + "suggest": { + "illuminate/database": "The Illuminate Database package (^6.0|^7.0|^8.0)." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + }, + "laravel": { + "providers": [ + "Laravel\\Tinker\\TinkerServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Tinker\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Powerful REPL for the Laravel framework.", + "keywords": [ + "REPL", + "Tinker", + "laravel", + "psysh" + ], + "support": { + "issues": "https://github.com/laravel/tinker/issues", + "source": "https://github.com/laravel/tinker/tree/v2.6.2" + }, + "time": "2021-09-28T15:47:34+00:00" + }, + { + "name": "laravel/ui", + "version": "v2.5.0", + "source": { + "type": "git", + "url": "https://github.com/laravel/ui.git", + "reference": "d01a705763c243b07be795e9d1bb47f89260f73d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/ui/zipball/d01a705763c243b07be795e9d1bb47f89260f73d", + "reference": "d01a705763c243b07be795e9d1bb47f89260f73d", + "shasum": "" + }, + "require": { + "illuminate/console": "^7.0", + "illuminate/filesystem": "^7.0", + "illuminate/support": "^7.0", + "php": "^7.2.5|^8.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Laravel\\Ui\\UiServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Ui\\": "src/", + "Illuminate\\Foundation\\Auth\\": "auth-backend/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Laravel UI utilities and presets.", + "keywords": [ + "laravel", + "ui" + ], + "support": { + "issues": "https://github.com/laravel/ui/issues", + "source": "https://github.com/laravel/ui/tree/v2.5.0" + }, + "time": "2020-11-03T19:45:19+00:00" + }, { "name": "league/commonmark", "version": "1.6.6", @@ -2722,84 +2987,60 @@ "time": "2021-09-06T09:29:23+00:00" }, { - "name": "nunomaduro/collision", - "version": "v3.2.0", + "name": "nikic/php-parser", + "version": "v4.13.0", "source": { "type": "git", - "url": "https://github.com/nunomaduro/collision.git", - "reference": "f7c45764dfe4ba5f2618d265a6f1f9c72732e01d" + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "50953a2691a922aa1769461637869a0a2faa3f53" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/collision/zipball/f7c45764dfe4ba5f2618d265a6f1f9c72732e01d", - "reference": "f7c45764dfe4ba5f2618d265a6f1f9c72732e01d", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/50953a2691a922aa1769461637869a0a2faa3f53", + "reference": "50953a2691a922aa1769461637869a0a2faa3f53", "shasum": "" }, "require": { - "filp/whoops": "^2.1.4", - "php": "^7.2.5 || ^8.0", - "php-parallel-lint/php-console-highlighter": "0.5.*", - "symfony/console": "~2.8|~3.3|~4.0" + "ext-tokenizer": "*", + "php": ">=7.0" }, "require-dev": { - "laravel/framework": "^6.0", - "phpunit/phpunit": "^8.0 || ^9.0" + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" }, + "bin": [ + "bin/php-parse" + ], "type": "library", "extra": { - "laravel": { - "providers": [ - "NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider" - ] + "branch-alias": { + "dev-master": "4.9-dev" } }, "autoload": { "psr-4": { - "NunoMaduro\\Collision\\": "src/" + "PhpParser\\": "lib/PhpParser" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Nuno Maduro", - "email": "enunomaduro@gmail.com" + "name": "Nikita Popov" } ], - "description": "Cli error handling for console/command-line PHP applications.", + "description": "A PHP parser written in PHP", "keywords": [ - "artisan", - "cli", - "command-line", - "console", - "error", - "handling", - "laravel", - "laravel-zero", - "php", - "symfony" + "parser", + "php" ], "support": { - "issues": "https://github.com/nunomaduro/collision/issues", - "source": "https://github.com/nunomaduro/collision" + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v4.13.0" }, - "funding": [ - { - "url": "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=66BYDWAT92N6L", - "type": "custom" - }, - { - "url": "https://github.com/nunomaduro", - "type": "github" - }, - { - "url": "https://www.patreon.com/nunomaduro", - "type": "patreon" - } - ], - "time": "2021-02-11T09:01:42+00:00" + "time": "2021-09-20T12:20:58+00:00" }, { "name": "onelogin/php-saml", @@ -3124,108 +3365,6 @@ }, "time": "2019-09-11T20:02:13+00:00" }, - { - "name": "php-parallel-lint/php-console-color", - "version": "v0.3", - "source": { - "type": "git", - "url": "https://github.com/php-parallel-lint/PHP-Console-Color.git", - "reference": "b6af326b2088f1ad3b264696c9fd590ec395b49e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-parallel-lint/PHP-Console-Color/zipball/b6af326b2088f1ad3b264696c9fd590ec395b49e", - "reference": "b6af326b2088f1ad3b264696c9fd590ec395b49e", - "shasum": "" - }, - "require": { - "php": ">=5.4.0" - }, - "replace": { - "jakub-onderka/php-console-color": "*" - }, - "require-dev": { - "php-parallel-lint/php-code-style": "1.0", - "php-parallel-lint/php-parallel-lint": "1.0", - "php-parallel-lint/php-var-dump-check": "0.*", - "phpunit/phpunit": "~4.3", - "squizlabs/php_codesniffer": "1.*" - }, - "type": "library", - "autoload": { - "psr-4": { - "JakubOnderka\\PhpConsoleColor\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-2-Clause" - ], - "authors": [ - { - "name": "Jakub Onderka", - "email": "jakub.onderka@gmail.com" - } - ], - "support": { - "issues": "https://github.com/php-parallel-lint/PHP-Console-Color/issues", - "source": "https://github.com/php-parallel-lint/PHP-Console-Color/tree/master" - }, - "time": "2020-05-14T05:47:14+00:00" - }, - { - "name": "php-parallel-lint/php-console-highlighter", - "version": "v0.5", - "source": { - "type": "git", - "url": "https://github.com/php-parallel-lint/PHP-Console-Highlighter.git", - "reference": "21bf002f077b177f056d8cb455c5ed573adfdbb8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-parallel-lint/PHP-Console-Highlighter/zipball/21bf002f077b177f056d8cb455c5ed573adfdbb8", - "reference": "21bf002f077b177f056d8cb455c5ed573adfdbb8", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": ">=5.4.0", - "php-parallel-lint/php-console-color": "~0.2" - }, - "replace": { - "jakub-onderka/php-console-highlighter": "*" - }, - "require-dev": { - "php-parallel-lint/php-code-style": "~1.0", - "php-parallel-lint/php-parallel-lint": "~1.0", - "php-parallel-lint/php-var-dump-check": "~0.1", - "phpunit/phpunit": "~4.0", - "squizlabs/php_codesniffer": "~1.5" - }, - "type": "library", - "autoload": { - "psr-4": { - "JakubOnderka\\PhpConsoleHighlighter\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jakub Onderka", - "email": "acci@acci.cz", - "homepage": "http://www.acci.cz/" - } - ], - "description": "Highlight PHP code in terminal", - "support": { - "issues": "https://github.com/php-parallel-lint/PHP-Console-Highlighter/issues", - "source": "https://github.com/php-parallel-lint/PHP-Console-Highlighter/tree/master" - }, - "time": "2020-05-13T07:37:49+00:00" - }, { "name": "phpoption/phpoption", "version": "1.8.0", @@ -3572,6 +3711,56 @@ }, "time": "2021-03-05T17:36:06+00:00" }, + { + "name": "psr/event-dispatcher", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\EventDispatcher\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Standard interfaces for event handling.", + "keywords": [ + "events", + "psr", + "psr-14" + ], + "support": { + "issues": "https://github.com/php-fig/event-dispatcher/issues", + "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + }, + "time": "2019-01-08T18:20:26+00:00" + }, { "name": "psr/http-client", "version": "1.0.1", @@ -3833,6 +4022,81 @@ }, "time": "2017-10-23T01:57:42+00:00" }, + { + "name": "psy/psysh", + "version": "v0.10.9", + "source": { + "type": "git", + "url": "https://github.com/bobthecow/psysh.git", + "reference": "01281336c4ae557fe4a994544f30d3a1bc204375" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/01281336c4ae557fe4a994544f30d3a1bc204375", + "reference": "01281336c4ae557fe4a994544f30d3a1bc204375", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-tokenizer": "*", + "nikic/php-parser": "~4.0|~3.0|~2.0|~1.3", + "php": "^8.0 || ^7.0 || ^5.5.9", + "symfony/console": "~5.0|~4.0|~3.0|^2.4.2|~2.3.10", + "symfony/var-dumper": "~5.0|~4.0|~3.0|~2.7" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.2", + "hoa/console": "3.17.*" + }, + "suggest": { + "ext-pcntl": "Enabling the PCNTL extension makes PsySH a lot happier :)", + "ext-pdo-sqlite": "The doc command requires SQLite to work.", + "ext-posix": "If you have PCNTL, you'll want the POSIX extension as well.", + "ext-readline": "Enables support for arrow-key history navigation, and showing and manipulating command history.", + "hoa/console": "A pure PHP readline implementation. You'll want this if your PHP install doesn't already support readline or libedit." + }, + "bin": [ + "bin/psysh" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "0.10.x-dev" + } + }, + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Psy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Justin Hileman", + "email": "justin@justinhileman.info", + "homepage": "http://justinhileman.com" + } + ], + "description": "An interactive shell for modern PHP.", + "homepage": "http://psysh.org", + "keywords": [ + "REPL", + "console", + "interactive", + "shell" + ], + "support": { + "issues": "https://github.com/bobthecow/psysh/issues", + "source": "https://github.com/bobthecow/psysh/tree/v0.10.9" + }, + "time": "2021-10-10T13:37:39+00:00" + }, { "name": "ralouphie/getallheaders", "version": "3.0.3", @@ -3878,56 +4142,146 @@ "time": "2019-03-08T08:55:37+00:00" }, { - "name": "ramsey/uuid", - "version": "3.9.6", + "name": "ramsey/collection", + "version": "1.2.2", "source": { "type": "git", - "url": "https://github.com/ramsey/uuid.git", - "reference": "ffa80ab953edd85d5b6c004f96181a538aad35a3" + "url": "https://github.com/ramsey/collection.git", + "reference": "cccc74ee5e328031b15640b51056ee8d3bb66c0a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/uuid/zipball/ffa80ab953edd85d5b6c004f96181a538aad35a3", - "reference": "ffa80ab953edd85d5b6c004f96181a538aad35a3", + "url": "https://api.github.com/repos/ramsey/collection/zipball/cccc74ee5e328031b15640b51056ee8d3bb66c0a", + "reference": "cccc74ee5e328031b15640b51056ee8d3bb66c0a", "shasum": "" }, "require": { + "php": "^7.3 || ^8", + "symfony/polyfill-php81": "^1.23" + }, + "require-dev": { + "captainhook/captainhook": "^5.3", + "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", + "ergebnis/composer-normalize": "^2.6", + "fakerphp/faker": "^1.5", + "hamcrest/hamcrest-php": "^2", + "jangregor/phpstan-prophecy": "^0.8", + "mockery/mockery": "^1.3", + "phpspec/prophecy-phpunit": "^2.0", + "phpstan/extension-installer": "^1", + "phpstan/phpstan": "^0.12.32", + "phpstan/phpstan-mockery": "^0.12.5", + "phpstan/phpstan-phpunit": "^0.12.11", + "phpunit/phpunit": "^8.5 || ^9", + "psy/psysh": "^0.10.4", + "slevomat/coding-standard": "^6.3", + "squizlabs/php_codesniffer": "^3.5", + "vimeo/psalm": "^4.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Ramsey\\Collection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ben Ramsey", + "email": "ben@benramsey.com", + "homepage": "https://benramsey.com" + } + ], + "description": "A PHP library for representing and manipulating collections.", + "keywords": [ + "array", + "collection", + "hash", + "map", + "queue", + "set" + ], + "support": { + "issues": "https://github.com/ramsey/collection/issues", + "source": "https://github.com/ramsey/collection/tree/1.2.2" + }, + "funding": [ + { + "url": "https://github.com/ramsey", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/ramsey/collection", + "type": "tidelift" + } + ], + "time": "2021-10-10T03:01:02+00:00" + }, + { + "name": "ramsey/uuid", + "version": "4.2.3", + "source": { + "type": "git", + "url": "https://github.com/ramsey/uuid.git", + "reference": "fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df", + "reference": "fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df", + "shasum": "" + }, + "require": { + "brick/math": "^0.8 || ^0.9", "ext-json": "*", - "paragonie/random_compat": "^1 | ^2 | ^9.99.99", - "php": "^5.4 | ^7.0 | ^8.0", - "symfony/polyfill-ctype": "^1.8" + "php": "^7.2 || ^8.0", + "ramsey/collection": "^1.0", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-php80": "^1.14" }, "replace": { "rhumsaa/uuid": "self.version" }, "require-dev": { - "codeception/aspect-mock": "^1 | ^2", - "doctrine/annotations": "^1.2", - "goaop/framework": "1.0.0-alpha.2 | ^1 | >=2.1.0 <=2.3.2", - "mockery/mockery": "^0.9.11 | ^1", + "captainhook/captainhook": "^5.10", + "captainhook/plugin-composer": "^5.3", + "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", + "doctrine/annotations": "^1.8", + "ergebnis/composer-normalize": "^2.15", + "mockery/mockery": "^1.3", "moontoast/math": "^1.1", - "nikic/php-parser": "<=4.5.0", "paragonie/random-lib": "^2", - "php-mock/php-mock-phpunit": "^0.3 | ^1.1 | ^2.6", - "php-parallel-lint/php-parallel-lint": "^1.3", - "phpunit/phpunit": ">=4.8.36 <9.0.0 | >=9.3.0", + "php-mock/php-mock": "^2.2", + "php-mock/php-mock-mockery": "^1.3", + "php-parallel-lint/php-parallel-lint": "^1.1", + "phpbench/phpbench": "^1.0", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^0.12", + "phpstan/phpstan-mockery": "^0.12", + "phpstan/phpstan-phpunit": "^0.12", + "phpunit/phpunit": "^8.5 || ^9", + "slevomat/coding-standard": "^7.0", "squizlabs/php_codesniffer": "^3.5", - "yoast/phpunit-polyfills": "^1.0" + "vimeo/psalm": "^4.9" }, "suggest": { - "ext-ctype": "Provides support for PHP Ctype functions", - "ext-libsodium": "Provides the PECL libsodium extension for use with the SodiumRandomGenerator", - "ext-openssl": "Provides the OpenSSL extension for use with the OpenSslGenerator", - "ext-uuid": "Provides the PECL UUID extension for use with the PeclUuidTimeGenerator and PeclUuidRandomGenerator", - "moontoast/math": "Provides support for converting UUID to 128-bit integer (in string form).", + "ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.", + "ext-ctype": "Enables faster processing of character classification using ctype functions.", + "ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.", + "ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.", "paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter", - "ramsey/uuid-console": "A console application for generating UUIDs with ramsey/uuid", "ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.x-dev" + "dev-main": "4.x-dev" + }, + "captainhook": { + "force-install": true } }, "autoload": { @@ -3942,23 +4296,7 @@ "license": [ "MIT" ], - "authors": [ - { - "name": "Ben Ramsey", - "email": "ben@benramsey.com", - "homepage": "https://benramsey.com" - }, - { - "name": "Marijn Huizendveld", - "email": "marijn.huizendveld@gmail.com" - }, - { - "name": "Thibaud Fabre", - "email": "thibaud@aztech.io" - } - ], - "description": "Formerly rhumsaa/uuid. A PHP 5.4+ library for generating RFC 4122 version 1, 3, 4, and 5 universally unique identifiers (UUID).", - "homepage": "https://github.com/ramsey/uuid", + "description": "A PHP library for generating and working with universally unique identifiers (UUIDs).", "keywords": [ "guid", "identifier", @@ -3966,9 +4304,7 @@ ], "support": { "issues": "https://github.com/ramsey/uuid/issues", - "rss": "https://github.com/ramsey/uuid/releases.atom", - "source": "https://github.com/ramsey/uuid", - "wiki": "https://github.com/ramsey/uuid/wiki" + "source": "https://github.com/ramsey/uuid/tree/4.2.3" }, "funding": [ { @@ -3980,7 +4316,7 @@ "type": "tidelift" } ], - "time": "2021-09-25T23:07:42+00:00" + "time": "2021-09-25T23:10:38+00:00" }, { "name": "robrichards/xmlseclibs", @@ -4515,43 +4851,46 @@ }, { "name": "symfony/console", - "version": "v4.4.30", + "version": "v5.3.7", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "a3f7189a0665ee33b50e9e228c46f50f5acbed22" + "reference": "8b1008344647462ae6ec57559da166c2bfa5e16a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/a3f7189a0665ee33b50e9e228c46f50f5acbed22", - "reference": "a3f7189a0665ee33b50e9e228c46f50f5acbed22", + "url": "https://api.github.com/repos/symfony/console/zipball/8b1008344647462ae6ec57559da166c2bfa5e16a", + "reference": "8b1008344647462ae6ec57559da166c2bfa5e16a", "shasum": "" }, "require": { - "php": ">=7.1.3", + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1", "symfony/polyfill-mbstring": "~1.0", "symfony/polyfill-php73": "^1.8", "symfony/polyfill-php80": "^1.16", - "symfony/service-contracts": "^1.1|^2" + "symfony/service-contracts": "^1.1|^2", + "symfony/string": "^5.1" }, "conflict": { "psr/log": ">=3", - "symfony/dependency-injection": "<3.4", - "symfony/event-dispatcher": "<4.3|>=5", + "symfony/dependency-injection": "<4.4", + "symfony/dotenv": "<5.1", + "symfony/event-dispatcher": "<4.4", "symfony/lock": "<4.4", - "symfony/process": "<3.3" + "symfony/process": "<4.4" }, "provide": { "psr/log-implementation": "1.0|2.0" }, "require-dev": { "psr/log": "^1|^2", - "symfony/config": "^3.4|^4.0|^5.0", - "symfony/dependency-injection": "^3.4|^4.0|^5.0", - "symfony/event-dispatcher": "^4.3", + "symfony/config": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/event-dispatcher": "^4.4|^5.0", "symfony/lock": "^4.4|^5.0", - "symfony/process": "^3.4|^4.0|^5.0", - "symfony/var-dumper": "^4.3|^5.0" + "symfony/process": "^4.4|^5.0", + "symfony/var-dumper": "^4.4|^5.0" }, "suggest": { "psr/log": "For using the console logger", @@ -4584,8 +4923,14 @@ ], "description": "Eases the creation of beautiful and testable command line interfaces", "homepage": "https://symfony.com", + "keywords": [ + "cli", + "command line", + "console", + "terminal" + ], "support": { - "source": "https://github.com/symfony/console/tree/v4.4.30" + "source": "https://github.com/symfony/console/tree/v5.3.7" }, "funding": [ { @@ -4601,7 +4946,7 @@ "type": "tidelift" } ], - "time": "2021-08-25T19:27:26+00:00" + "time": "2021-08-25T20:02:16+00:00" }, { "name": "symfony/css-selector", @@ -4669,74 +5014,6 @@ ], "time": "2021-07-21T12:38:00+00:00" }, - { - "name": "symfony/debug", - "version": "v4.4.31", - "source": { - "type": "git", - "url": "https://github.com/symfony/debug.git", - "reference": "43ede438d4cb52cd589ae5dc070e9323866ba8e0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/43ede438d4cb52cd589ae5dc070e9323866ba8e0", - "reference": "43ede438d4cb52cd589ae5dc070e9323866ba8e0", - "shasum": "" - }, - "require": { - "php": ">=7.1.3", - "psr/log": "^1|^2|^3" - }, - "conflict": { - "symfony/http-kernel": "<3.4" - }, - "require-dev": { - "symfony/http-kernel": "^3.4|^4.0|^5.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Debug\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides tools to ease debugging PHP code", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/debug/tree/v4.4.31" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2021-09-24T13:30:14+00:00" - }, { "name": "symfony/deprecation-contracts", "version": "v2.4.0", @@ -4806,25 +5083,25 @@ }, { "name": "symfony/error-handler", - "version": "v4.4.30", + "version": "v5.3.7", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "51f98f7aa99f00f3b1da6bafe934e67ae6ba6dc5" + "reference": "3bc60d0fba00ae8d1eaa9eb5ab11a2bbdd1fc321" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/51f98f7aa99f00f3b1da6bafe934e67ae6ba6dc5", - "reference": "51f98f7aa99f00f3b1da6bafe934e67ae6ba6dc5", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/3bc60d0fba00ae8d1eaa9eb5ab11a2bbdd1fc321", + "reference": "3bc60d0fba00ae8d1eaa9eb5ab11a2bbdd1fc321", "shasum": "" }, "require": { - "php": ">=7.1.3", + "php": ">=7.2.5", "psr/log": "^1|^2|^3", - "symfony/debug": "^4.4.5", "symfony/var-dumper": "^4.4|^5.0" }, "require-dev": { + "symfony/deprecation-contracts": "^2.1", "symfony/http-kernel": "^4.4|^5.0", "symfony/serializer": "^4.4|^5.0" }, @@ -4854,7 +5131,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v4.4.30" + "source": "https://github.com/symfony/error-handler/tree/v5.3.7" }, "funding": [ { @@ -4870,43 +5147,44 @@ "type": "tidelift" } ], - "time": "2021-08-27T17:42:48+00:00" + "time": "2021-08-28T15:07:08+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v4.4.30", + "version": "v5.3.7", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "2fe81680070043c4c80e7cedceb797e34f377bac" + "reference": "ce7b20d69c66a20939d8952b617506a44d102130" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/2fe81680070043c4c80e7cedceb797e34f377bac", - "reference": "2fe81680070043c4c80e7cedceb797e34f377bac", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/ce7b20d69c66a20939d8952b617506a44d102130", + "reference": "ce7b20d69c66a20939d8952b617506a44d102130", "shasum": "" }, "require": { - "php": ">=7.1.3", - "symfony/event-dispatcher-contracts": "^1.1", + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1", + "symfony/event-dispatcher-contracts": "^2", "symfony/polyfill-php80": "^1.16" }, "conflict": { - "symfony/dependency-injection": "<3.4" + "symfony/dependency-injection": "<4.4" }, "provide": { "psr/event-dispatcher-implementation": "1.0", - "symfony/event-dispatcher-implementation": "1.1" + "symfony/event-dispatcher-implementation": "2.0" }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^3.4|^4.0|^5.0", - "symfony/dependency-injection": "^3.4|^4.0|^5.0", - "symfony/error-handler": "~3.4|~4.4", - "symfony/expression-language": "^3.4|^4.0|^5.0", - "symfony/http-foundation": "^3.4|^4.0|^5.0", + "symfony/config": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/error-handler": "^4.4|^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/http-foundation": "^4.4|^5.0", "symfony/service-contracts": "^1.1|^2", - "symfony/stopwatch": "^3.4|^4.0|^5.0" + "symfony/stopwatch": "^4.4|^5.0" }, "suggest": { "symfony/dependency-injection": "", @@ -4938,7 +5216,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v4.4.30" + "source": "https://github.com/symfony/event-dispatcher/tree/v5.3.7" }, "funding": [ { @@ -4954,33 +5232,33 @@ "type": "tidelift" } ], - "time": "2021-08-04T20:31:23+00:00" + "time": "2021-08-04T21:20:46+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v1.1.9", + "version": "v2.4.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "84e23fdcd2517bf37aecbd16967e83f0caee25a7" + "reference": "69fee1ad2332a7cbab3aca13591953da9cdb7a11" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/84e23fdcd2517bf37aecbd16967e83f0caee25a7", - "reference": "84e23fdcd2517bf37aecbd16967e83f0caee25a7", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/69fee1ad2332a7cbab3aca13591953da9cdb7a11", + "reference": "69fee1ad2332a7cbab3aca13591953da9cdb7a11", "shasum": "" }, "require": { - "php": ">=7.1.3" + "php": ">=7.2.5", + "psr/event-dispatcher": "^1" }, "suggest": { - "psr/event-dispatcher": "", "symfony/event-dispatcher-implementation": "" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-main": "2.4-dev" }, "thanks": { "name": "symfony/contracts", @@ -5017,7 +5295,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v1.1.9" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v2.4.0" }, "funding": [ { @@ -5033,24 +5311,24 @@ "type": "tidelift" } ], - "time": "2020-07-06T13:19:58+00:00" + "time": "2021-03-23T23:28:01+00:00" }, { "name": "symfony/finder", - "version": "v4.4.30", + "version": "v5.3.7", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "70362f1e112280d75b30087c7598b837c1b468b6" + "reference": "a10000ada1e600d109a6c7632e9ac42e8bf2fb93" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/70362f1e112280d75b30087c7598b837c1b468b6", - "reference": "70362f1e112280d75b30087c7598b837c1b468b6", + "url": "https://api.github.com/repos/symfony/finder/zipball/a10000ada1e600d109a6c7632e9ac42e8bf2fb93", + "reference": "a10000ada1e600d109a6c7632e9ac42e8bf2fb93", "shasum": "" }, "require": { - "php": ">=7.1.3", + "php": ">=7.2.5", "symfony/polyfill-php80": "^1.16" }, "type": "library", @@ -5079,7 +5357,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v4.4.30" + "source": "https://github.com/symfony/finder/tree/v5.3.7" }, "funding": [ { @@ -5095,7 +5373,7 @@ "type": "tidelift" } ], - "time": "2021-08-04T20:31:23+00:00" + "time": "2021-08-04T21:20:46+00:00" }, { "name": "symfony/http-client-contracts", @@ -5177,27 +5455,32 @@ }, { "name": "symfony/http-foundation", - "version": "v4.4.30", + "version": "v5.3.7", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "09b3202651ab23ac8dcf455284a48a3500e56731" + "reference": "e36c8e5502b4f3f0190c675f1c1f1248a64f04e5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/09b3202651ab23ac8dcf455284a48a3500e56731", - "reference": "09b3202651ab23ac8dcf455284a48a3500e56731", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/e36c8e5502b4f3f0190c675f1c1f1248a64f04e5", + "reference": "e36c8e5502b4f3f0190c675f1c1f1248a64f04e5", "shasum": "" }, "require": { - "php": ">=7.1.3", - "symfony/mime": "^4.3|^5.0", + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1", "symfony/polyfill-mbstring": "~1.1", "symfony/polyfill-php80": "^1.16" }, "require-dev": { "predis/predis": "~1.0", - "symfony/expression-language": "^3.4|^4.0|^5.0" + "symfony/cache": "^4.4|^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/mime": "^4.4|^5.0" + }, + "suggest": { + "symfony/mime": "To use the file extension guesser" }, "type": "library", "autoload": { @@ -5225,7 +5508,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v4.4.30" + "source": "https://github.com/symfony/http-foundation/tree/v5.3.7" }, "funding": [ { @@ -5241,61 +5524,69 @@ "type": "tidelift" } ], - "time": "2021-08-26T15:51:23+00:00" + "time": "2021-08-27T11:20:35+00:00" }, { "name": "symfony/http-kernel", - "version": "v4.4.32", + "version": "v5.3.9", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "f7bda3ea8f05ae90627400e58af5179b25ce0f38" + "reference": "ceaf46a992f60e90645e7279825a830f733a17c5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/f7bda3ea8f05ae90627400e58af5179b25ce0f38", - "reference": "f7bda3ea8f05ae90627400e58af5179b25ce0f38", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/ceaf46a992f60e90645e7279825a830f733a17c5", + "reference": "ceaf46a992f60e90645e7279825a830f733a17c5", "shasum": "" }, "require": { - "php": ">=7.1.3", + "php": ">=7.2.5", "psr/log": "^1|^2", - "symfony/error-handler": "^4.4", - "symfony/event-dispatcher": "^4.4", + "symfony/deprecation-contracts": "^2.1", + "symfony/error-handler": "^4.4|^5.0", + "symfony/event-dispatcher": "^5.0", "symfony/http-client-contracts": "^1.1|^2", - "symfony/http-foundation": "^4.4.30|^5.3.7", + "symfony/http-foundation": "^5.3.7", "symfony/polyfill-ctype": "^1.8", "symfony/polyfill-php73": "^1.9", "symfony/polyfill-php80": "^1.16" }, "conflict": { - "symfony/browser-kit": "<4.3", - "symfony/config": "<3.4", - "symfony/console": ">=5", - "symfony/dependency-injection": "<4.3", - "symfony/translation": "<4.2", - "twig/twig": "<1.43|<2.13,>=2" + "symfony/browser-kit": "<4.4", + "symfony/cache": "<5.0", + "symfony/config": "<5.0", + "symfony/console": "<4.4", + "symfony/dependency-injection": "<5.3", + "symfony/doctrine-bridge": "<5.0", + "symfony/form": "<5.0", + "symfony/http-client": "<5.0", + "symfony/mailer": "<5.0", + "symfony/messenger": "<5.0", + "symfony/translation": "<5.0", + "symfony/twig-bridge": "<5.0", + "symfony/validator": "<5.0", + "twig/twig": "<2.13" }, "provide": { "psr/log-implementation": "1.0|2.0" }, "require-dev": { "psr/cache": "^1.0|^2.0|^3.0", - "symfony/browser-kit": "^4.3|^5.0", - "symfony/config": "^3.4|^4.0|^5.0", - "symfony/console": "^3.4|^4.0", - "symfony/css-selector": "^3.4|^4.0|^5.0", - "symfony/dependency-injection": "^4.3|^5.0", - "symfony/dom-crawler": "^3.4|^4.0|^5.0", - "symfony/expression-language": "^3.4|^4.0|^5.0", - "symfony/finder": "^3.4|^4.0|^5.0", - "symfony/process": "^3.4|^4.0|^5.0", - "symfony/routing": "^3.4|^4.0|^5.0", - "symfony/stopwatch": "^3.4|^4.0|^5.0", - "symfony/templating": "^3.4|^4.0|^5.0", - "symfony/translation": "^4.2|^5.0", + "symfony/browser-kit": "^4.4|^5.0", + "symfony/config": "^5.0", + "symfony/console": "^4.4|^5.0", + "symfony/css-selector": "^4.4|^5.0", + "symfony/dependency-injection": "^5.3", + "symfony/dom-crawler": "^4.4|^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/finder": "^4.4|^5.0", + "symfony/process": "^4.4|^5.0", + "symfony/routing": "^4.4|^5.0", + "symfony/stopwatch": "^4.4|^5.0", + "symfony/translation": "^4.4|^5.0", "symfony/translation-contracts": "^1.1|^2", - "twig/twig": "^1.43|^2.13|^3.0.4" + "twig/twig": "^2.13|^3.0.4" }, "suggest": { "symfony/browser-kit": "", @@ -5329,7 +5620,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v4.4.32" + "source": "https://github.com/symfony/http-kernel/tree/v5.3.9" }, "funding": [ { @@ -5345,7 +5636,7 @@ "type": "tidelift" } ], - "time": "2021-09-28T10:20:04+00:00" + "time": "2021-09-28T10:25:11+00:00" }, { "name": "symfony/mime", @@ -5589,6 +5880,87 @@ ], "time": "2021-05-27T09:27:20+00:00" }, + { + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.23.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "16880ba9c5ebe3642d1995ab866db29270b36535" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/16880ba9c5ebe3642d1995ab866db29270b36535", + "reference": "16880ba9c5ebe3642d1995ab866db29270b36535", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's grapheme_* functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.23.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-05-27T12:26:48+00:00" + }, { "name": "symfony/polyfill-intl-idn", "version": "v1.23.0", @@ -6079,21 +6451,100 @@ "time": "2021-07-28T13:41:28+00:00" }, { - "name": "symfony/process", - "version": "v4.4.30", + "name": "symfony/polyfill-php81", + "version": "v1.23.0", "source": { "type": "git", - "url": "https://github.com/symfony/process.git", - "reference": "13d3161ef63a8ec21eeccaaf9a4d7f784a87a97d" + "url": "https://github.com/symfony/polyfill-php81.git", + "reference": "e66119f3de95efc359483f810c4c3e6436279436" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/13d3161ef63a8ec21eeccaaf9a4d7f784a87a97d", - "reference": "13d3161ef63a8ec21eeccaaf9a4d7f784a87a97d", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/e66119f3de95efc359483f810c4c3e6436279436", + "reference": "e66119f3de95efc359483f810c4c3e6436279436", "shasum": "" }, "require": { - "php": ">=7.1.3", + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php81\\": "" + }, + "files": [ + "bootstrap.php" + ], + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php81/tree/v1.23.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-05-21T13:25:03+00:00" + }, + { + "name": "symfony/process", + "version": "v5.3.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "38f26c7d6ed535217ea393e05634cb0b244a1967" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/38f26c7d6ed535217ea393e05634cb0b244a1967", + "reference": "38f26c7d6ed535217ea393e05634cb0b244a1967", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", "symfony/polyfill-php80": "^1.16" }, "type": "library", @@ -6122,7 +6573,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v4.4.30" + "source": "https://github.com/symfony/process/tree/v5.3.7" }, "funding": [ { @@ -6138,42 +6589,43 @@ "type": "tidelift" } ], - "time": "2021-08-04T20:31:23+00:00" + "time": "2021-08-04T21:20:46+00:00" }, { "name": "symfony/routing", - "version": "v4.4.30", + "version": "v5.3.7", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "9ddf033927ad9f30ba2bfd167a7b342cafa13e8e" + "reference": "be865017746fe869007d94220ad3f5297951811b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/9ddf033927ad9f30ba2bfd167a7b342cafa13e8e", - "reference": "9ddf033927ad9f30ba2bfd167a7b342cafa13e8e", + "url": "https://api.github.com/repos/symfony/routing/zipball/be865017746fe869007d94220ad3f5297951811b", + "reference": "be865017746fe869007d94220ad3f5297951811b", "shasum": "" }, "require": { - "php": ">=7.1.3", + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1", "symfony/polyfill-php80": "^1.16" }, "conflict": { - "symfony/config": "<4.2", - "symfony/dependency-injection": "<3.4", - "symfony/yaml": "<3.4" + "doctrine/annotations": "<1.12", + "symfony/config": "<5.3", + "symfony/dependency-injection": "<4.4", + "symfony/yaml": "<4.4" }, "require-dev": { - "doctrine/annotations": "^1.10.4", + "doctrine/annotations": "^1.12", "psr/log": "^1|^2|^3", - "symfony/config": "^4.2|^5.0", - "symfony/dependency-injection": "^3.4|^4.0|^5.0", - "symfony/expression-language": "^3.4|^4.0|^5.0", - "symfony/http-foundation": "^3.4|^4.0|^5.0", - "symfony/yaml": "^3.4|^4.0|^5.0" + "symfony/config": "^5.3", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/http-foundation": "^4.4|^5.0", + "symfony/yaml": "^4.4|^5.0" }, "suggest": { - "doctrine/annotations": "For using the annotation loader", "symfony/config": "For using the all-in-one router or any loader", "symfony/expression-language": "For using expression matching", "symfony/http-foundation": "For using a Symfony Request object", @@ -6211,7 +6663,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v4.4.30" + "source": "https://github.com/symfony/routing/tree/v5.3.7" }, "funding": [ { @@ -6227,7 +6679,7 @@ "type": "tidelift" } ], - "time": "2021-08-04T21:41:01+00:00" + "time": "2021-08-04T21:42:42+00:00" }, { "name": "symfony/service-contracts", @@ -6309,44 +6761,130 @@ "time": "2021-04-01T10:43:52+00:00" }, { - "name": "symfony/translation", - "version": "v4.4.32", + "name": "symfony/string", + "version": "v5.3.7", "source": { "type": "git", - "url": "https://github.com/symfony/translation.git", - "reference": "db0ba1e85280d8ff11e38d53c70f8814d4d740f5" + "url": "https://github.com/symfony/string.git", + "reference": "8d224396e28d30f81969f083a58763b8b9ceb0a5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/db0ba1e85280d8ff11e38d53c70f8814d4d740f5", - "reference": "db0ba1e85280d8ff11e38d53c70f8814d4d740f5", + "url": "https://api.github.com/repos/symfony/string/zipball/8d224396e28d30f81969f083a58763b8b9ceb0a5", + "reference": "8d224396e28d30f81969f083a58763b8b9ceb0a5", "shasum": "" }, "require": { - "php": ">=7.1.3", + "php": ">=7.2.5", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php80": "~1.15" + }, + "require-dev": { + "symfony/error-handler": "^4.4|^5.0", + "symfony/http-client": "^4.4|^5.0", + "symfony/translation-contracts": "^1.1|^2", + "symfony/var-exporter": "^4.4|^5.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\String\\": "" + }, + "files": [ + "Resources/functions.php" + ], + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "homepage": "https://symfony.com", + "keywords": [ + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], + "support": { + "source": "https://github.com/symfony/string/tree/v5.3.7" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-08-26T08:00:08+00:00" + }, + { + "name": "symfony/translation", + "version": "v5.3.9", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation.git", + "reference": "6e69f3551c1a3356cf6ea8d019bf039a0f8b6886" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation/zipball/6e69f3551c1a3356cf6ea8d019bf039a0f8b6886", + "reference": "6e69f3551c1a3356cf6ea8d019bf039a0f8b6886", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1", "symfony/polyfill-mbstring": "~1.0", "symfony/polyfill-php80": "^1.16", - "symfony/translation-contracts": "^1.1.6|^2" + "symfony/translation-contracts": "^2.3" }, "conflict": { - "symfony/config": "<3.4", - "symfony/dependency-injection": "<3.4", - "symfony/http-kernel": "<4.4", - "symfony/yaml": "<3.4" + "symfony/config": "<4.4", + "symfony/dependency-injection": "<5.0", + "symfony/http-kernel": "<5.0", + "symfony/twig-bundle": "<5.0", + "symfony/yaml": "<4.4" }, "provide": { - "symfony/translation-implementation": "1.0|2.0" + "symfony/translation-implementation": "2.3" }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^3.4|^4.0|^5.0", - "symfony/console": "^3.4|^4.0|^5.0", - "symfony/dependency-injection": "^3.4|^4.0|^5.0", - "symfony/finder": "~2.8|~3.0|~4.0|^5.0", - "symfony/http-kernel": "^4.4", - "symfony/intl": "^3.4|^4.0|^5.0", + "symfony/config": "^4.4|^5.0", + "symfony/console": "^4.4|^5.0", + "symfony/dependency-injection": "^5.0", + "symfony/finder": "^4.4|^5.0", + "symfony/http-kernel": "^5.0", + "symfony/intl": "^4.4|^5.0", + "symfony/polyfill-intl-icu": "^1.21", "symfony/service-contracts": "^1.1.2|^2", - "symfony/yaml": "^3.4|^4.0|^5.0" + "symfony/yaml": "^4.4|^5.0" }, "suggest": { "psr/log-implementation": "To use logging capability in translator", @@ -6355,6 +6893,9 @@ }, "type": "library", "autoload": { + "files": [ + "Resources/functions.php" + ], "psr-4": { "Symfony\\Component\\Translation\\": "" }, @@ -6379,7 +6920,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v4.4.32" + "source": "https://github.com/symfony/translation/tree/v5.3.9" }, "funding": [ { @@ -6395,7 +6936,7 @@ "type": "tidelift" } ], - "time": "2021-08-26T05:57:13+00:00" + "time": "2021-08-26T08:22:53+00:00" }, { "name": "symfony/translation-contracts", @@ -6477,33 +7018,32 @@ }, { "name": "symfony/var-dumper", - "version": "v4.4.31", + "version": "v5.3.8", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "1f12cc0c2e880a5f39575c19af81438464717839" + "reference": "eaaea4098be1c90c8285543e1356a09c8aa5c8da" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/1f12cc0c2e880a5f39575c19af81438464717839", - "reference": "1f12cc0c2e880a5f39575c19af81438464717839", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/eaaea4098be1c90c8285543e1356a09c8aa5c8da", + "reference": "eaaea4098be1c90c8285543e1356a09c8aa5c8da", "shasum": "" }, "require": { - "php": ">=7.1.3", + "php": ">=7.2.5", "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php72": "~1.5", "symfony/polyfill-php80": "^1.16" }, "conflict": { - "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0", - "symfony/console": "<3.4" + "phpunit/phpunit": "<5.4.3", + "symfony/console": "<4.4" }, "require-dev": { "ext-iconv": "*", - "symfony/console": "^3.4|^4.0|^5.0", + "symfony/console": "^4.4|^5.0", "symfony/process": "^4.4|^5.0", - "twig/twig": "^1.43|^2.13|^3.0.4" + "twig/twig": "^2.13|^3.0.4" }, "suggest": { "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", @@ -6546,7 +7086,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v4.4.31" + "source": "https://github.com/symfony/var-dumper/tree/v5.3.8" }, "funding": [ { @@ -6562,7 +7102,7 @@ "type": "tidelift" } ], - "time": "2021-09-24T15:30:11+00:00" + "time": "2021-09-24T15:59:58+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", @@ -6619,24 +7159,25 @@ }, { "name": "vlucas/phpdotenv", - "version": "v3.6.9", + "version": "v4.2.1", "source": { "type": "git", "url": "https://github.com/vlucas/phpdotenv.git", - "reference": "a1bf4c9853d90ade427b4efe35355fc41b3d6988" + "reference": "d38f4d1edcbe32515a0ad593cbd4c858e337263c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/a1bf4c9853d90ade427b4efe35355fc41b3d6988", - "reference": "a1bf4c9853d90ade427b4efe35355fc41b3d6988", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/d38f4d1edcbe32515a0ad593cbd4c858e337263c", + "reference": "d38f4d1edcbe32515a0ad593cbd4c858e337263c", "shasum": "" }, "require": { - "php": "^5.4 || ^7.0 || ^8.0", - "phpoption/phpoption": "^1.5.2", + "php": "^5.5.9 || ^7.0 || ^8.0", + "phpoption/phpoption": "^1.7.3", "symfony/polyfill-ctype": "^1.17" }, "require-dev": { + "bamarni/composer-bin-plugin": "^1.4.1", "ext-filter": "*", "ext-pcre": "*", "phpunit/phpunit": "^4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.21" @@ -6648,7 +7189,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.6-dev" + "dev-master": "4.2-dev" } }, "autoload": { @@ -6678,7 +7219,7 @@ ], "support": { "issues": "https://github.com/vlucas/phpdotenv/issues", - "source": "https://github.com/vlucas/phpdotenv/tree/v3.6.9" + "source": "https://github.com/vlucas/phpdotenv/tree/v4.2.1" }, "funding": [ { @@ -6690,7 +7231,81 @@ "type": "tidelift" } ], - "time": "2021-10-02T19:07:56+00:00" + "time": "2021-10-02T19:17:08+00:00" + }, + { + "name": "voku/portable-ascii", + "version": "1.5.6", + "source": { + "type": "git", + "url": "https://github.com/voku/portable-ascii.git", + "reference": "80953678b19901e5165c56752d087fc11526017c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/voku/portable-ascii/zipball/80953678b19901e5165c56752d087fc11526017c", + "reference": "80953678b19901e5165c56752d087fc11526017c", + "shasum": "" + }, + "require": { + "php": ">=7.0.0" + }, + "require-dev": { + "phpunit/phpunit": "~6.0 || ~7.0 || ~9.0" + }, + "suggest": { + "ext-intl": "Use Intl for transliterator_transliterate() support" + }, + "type": "library", + "autoload": { + "psr-4": { + "voku\\": "src/voku/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Lars Moelleken", + "homepage": "http://www.moelleken.org/" + } + ], + "description": "Portable ASCII library - performance optimized (ascii) string functions for php.", + "homepage": "https://github.com/voku/portable-ascii", + "keywords": [ + "ascii", + "clean", + "php" + ], + "support": { + "issues": "https://github.com/voku/portable-ascii/issues", + "source": "https://github.com/voku/portable-ascii/tree/1.5.6" + }, + "funding": [ + { + "url": "https://www.paypal.me/moelleken", + "type": "custom" + }, + { + "url": "https://github.com/voku", + "type": "github" + }, + { + "url": "https://opencollective.com/portable-ascii", + "type": "open_collective" + }, + { + "url": "https://www.patreon.com/voku", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/voku/portable-ascii", + "type": "tidelift" + } + ], + "time": "2020-11-12T00:07:28+00:00" } ], "packages-dev": [ @@ -6779,611 +7394,6 @@ ], "time": "2021-10-21T10:57:31+00:00" }, - { - "name": "barryvdh/laravel-ide-helper", - "version": "v2.8.2", - "source": { - "type": "git", - "url": "https://github.com/barryvdh/laravel-ide-helper.git", - "reference": "5515cabea39b9cf55f98980d0f269dc9d85cfcca" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/5515cabea39b9cf55f98980d0f269dc9d85cfcca", - "reference": "5515cabea39b9cf55f98980d0f269dc9d85cfcca", - "shasum": "" - }, - "require": { - "barryvdh/reflection-docblock": "^2.0.6", - "composer/composer": "^1.6 || ^2", - "doctrine/dbal": "~2.3", - "ext-json": "*", - "illuminate/console": "^6 || ^7 || ^8", - "illuminate/filesystem": "^6 || ^7 || ^8", - "illuminate/support": "^6 || ^7 || ^8", - "php": ">=7.2", - "phpdocumentor/type-resolver": "^1.1.0" - }, - "require-dev": { - "ext-pdo_sqlite": "*", - "friendsofphp/php-cs-fixer": "^2", - "illuminate/config": "^6 || ^7 || ^8", - "illuminate/view": "^6 || ^7 || ^8", - "mockery/mockery": "^1.3.3", - "orchestra/testbench": "^4 || ^5 || ^6", - "phpunit/phpunit": "^8.5 || ^9", - "spatie/phpunit-snapshot-assertions": "^1.4 || ^2.2 || ^3 || ^4", - "vimeo/psalm": "^3.12" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.8-dev" - }, - "laravel": { - "providers": [ - "Barryvdh\\LaravelIdeHelper\\IdeHelperServiceProvider" - ] - } - }, - "autoload": { - "psr-4": { - "Barryvdh\\LaravelIdeHelper\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Barry vd. Heuvel", - "email": "barryvdh@gmail.com" - } - ], - "description": "Laravel IDE Helper, generates correct PHPDocs for all Facade classes, to improve auto-completion.", - "keywords": [ - "autocomplete", - "codeintel", - "helper", - "ide", - "laravel", - "netbeans", - "phpdoc", - "phpstorm", - "sublime" - ], - "support": { - "issues": "https://github.com/barryvdh/laravel-ide-helper/issues", - "source": "https://github.com/barryvdh/laravel-ide-helper/tree/v2.8.2" - }, - "funding": [ - { - "url": "https://github.com/barryvdh", - "type": "github" - } - ], - "time": "2020-12-06T08:55:05+00:00" - }, - { - "name": "barryvdh/reflection-docblock", - "version": "v2.0.6", - "source": { - "type": "git", - "url": "https://github.com/barryvdh/ReflectionDocBlock.git", - "reference": "6b69015d83d3daf9004a71a89f26e27d27ef6a16" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/barryvdh/ReflectionDocBlock/zipball/6b69015d83d3daf9004a71a89f26e27d27ef6a16", - "reference": "6b69015d83d3daf9004a71a89f26e27d27ef6a16", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.0,<4.5" - }, - "suggest": { - "dflydev/markdown": "~1.0", - "erusev/parsedown": "~1.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "psr-0": { - "Barryvdh": [ - "src/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "mike.vanriel@naenius.com" - } - ], - "support": { - "source": "https://github.com/barryvdh/ReflectionDocBlock/tree/v2.0.6" - }, - "time": "2018-12-13T10:34:14+00:00" - }, - { - "name": "composer/ca-bundle", - "version": "1.2.11", - "source": { - "type": "git", - "url": "https://github.com/composer/ca-bundle.git", - "reference": "0b072d51c5a9c6f3412f7ea3ab043d6603cb2582" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/ca-bundle/zipball/0b072d51c5a9c6f3412f7ea3ab043d6603cb2582", - "reference": "0b072d51c5a9c6f3412f7ea3ab043d6603cb2582", - "shasum": "" - }, - "require": { - "ext-openssl": "*", - "ext-pcre": "*", - "php": "^5.3.2 || ^7.0 || ^8.0" - }, - "require-dev": { - "phpstan/phpstan": "^0.12.55", - "psr/log": "^1.0", - "symfony/phpunit-bridge": "^4.2 || ^5", - "symfony/process": "^2.5 || ^3.0 || ^4.0 || ^5.0 || ^6.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Composer\\CaBundle\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - } - ], - "description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.", - "keywords": [ - "cabundle", - "cacert", - "certificate", - "ssl", - "tls" - ], - "support": { - "irc": "irc://irc.freenode.org/composer", - "issues": "https://github.com/composer/ca-bundle/issues", - "source": "https://github.com/composer/ca-bundle/tree/1.2.11" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2021-09-25T20:32:43+00:00" - }, - { - "name": "composer/composer", - "version": "2.1.9", - "source": { - "type": "git", - "url": "https://github.com/composer/composer.git", - "reference": "e558c88f28d102d497adec4852802c0dc14c7077" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/composer/zipball/e558c88f28d102d497adec4852802c0dc14c7077", - "reference": "e558c88f28d102d497adec4852802c0dc14c7077", - "shasum": "" - }, - "require": { - "composer/ca-bundle": "^1.0", - "composer/metadata-minifier": "^1.0", - "composer/semver": "^3.0", - "composer/spdx-licenses": "^1.2", - "composer/xdebug-handler": "^2.0", - "justinrainbow/json-schema": "^5.2.11", - "php": "^5.3.2 || ^7.0 || ^8.0", - "psr/log": "^1.0", - "react/promise": "^1.2 || ^2.7", - "seld/jsonlint": "^1.4", - "seld/phar-utils": "^1.0", - "symfony/console": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0", - "symfony/filesystem": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0", - "symfony/finder": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0", - "symfony/process": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0" - }, - "require-dev": { - "phpspec/prophecy": "^1.10", - "symfony/phpunit-bridge": "^4.2 || ^5.0 || ^6.0" - }, - "suggest": { - "ext-openssl": "Enabling the openssl extension allows you to access https URLs for repositories and packages", - "ext-zip": "Enabling the zip extension allows you to unzip archives", - "ext-zlib": "Allow gzip compression of HTTP requests" - }, - "bin": [ - "bin/composer" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.1-dev" - } - }, - "autoload": { - "psr-4": { - "Composer\\": "src/Composer" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nils Adermann", - "email": "naderman@naderman.de", - "homepage": "https://www.naderman.de" - }, - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "https://seld.be" - } - ], - "description": "Composer helps you declare, manage and install dependencies of PHP projects. It ensures you have the right stack everywhere.", - "homepage": "https://getcomposer.org/", - "keywords": [ - "autoload", - "dependency", - "package" - ], - "support": { - "irc": "ircs://irc.libera.chat:6697/composer", - "issues": "https://github.com/composer/composer/issues", - "source": "https://github.com/composer/composer/tree/2.1.9" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2021-10-05T07:47:38+00:00" - }, - { - "name": "composer/metadata-minifier", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/composer/metadata-minifier.git", - "reference": "c549d23829536f0d0e984aaabbf02af91f443207" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/metadata-minifier/zipball/c549d23829536f0d0e984aaabbf02af91f443207", - "reference": "c549d23829536f0d0e984aaabbf02af91f443207", - "shasum": "" - }, - "require": { - "php": "^5.3.2 || ^7.0 || ^8.0" - }, - "require-dev": { - "composer/composer": "^2", - "phpstan/phpstan": "^0.12.55", - "symfony/phpunit-bridge": "^4.2 || ^5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Composer\\MetadataMinifier\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - } - ], - "description": "Small utility library that handles metadata minification and expansion.", - "keywords": [ - "composer", - "compression" - ], - "support": { - "issues": "https://github.com/composer/metadata-minifier/issues", - "source": "https://github.com/composer/metadata-minifier/tree/1.0.0" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2021-04-07T13:37:33+00:00" - }, - { - "name": "composer/semver", - "version": "3.2.6", - "source": { - "type": "git", - "url": "https://github.com/composer/semver.git", - "reference": "83e511e247de329283478496f7a1e114c9517506" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/83e511e247de329283478496f7a1e114c9517506", - "reference": "83e511e247de329283478496f7a1e114c9517506", - "shasum": "" - }, - "require": { - "php": "^5.3.2 || ^7.0 || ^8.0" - }, - "require-dev": { - "phpstan/phpstan": "^0.12.54", - "symfony/phpunit-bridge": "^4.2 || ^5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Composer\\Semver\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nils Adermann", - "email": "naderman@naderman.de", - "homepage": "http://www.naderman.de" - }, - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - }, - { - "name": "Rob Bast", - "email": "rob.bast@gmail.com", - "homepage": "http://robbast.nl" - } - ], - "description": "Semver library that offers utilities, version constraint parsing and validation.", - "keywords": [ - "semantic", - "semver", - "validation", - "versioning" - ], - "support": { - "irc": "irc://irc.freenode.org/composer", - "issues": "https://github.com/composer/semver/issues", - "source": "https://github.com/composer/semver/tree/3.2.6" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2021-10-25T11:34:17+00:00" - }, - { - "name": "composer/spdx-licenses", - "version": "1.5.5", - "source": { - "type": "git", - "url": "https://github.com/composer/spdx-licenses.git", - "reference": "de30328a7af8680efdc03e396aad24befd513200" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/spdx-licenses/zipball/de30328a7af8680efdc03e396aad24befd513200", - "reference": "de30328a7af8680efdc03e396aad24befd513200", - "shasum": "" - }, - "require": { - "php": "^5.3.2 || ^7.0 || ^8.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || 6.5 - 7" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Composer\\Spdx\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nils Adermann", - "email": "naderman@naderman.de", - "homepage": "http://www.naderman.de" - }, - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - }, - { - "name": "Rob Bast", - "email": "rob.bast@gmail.com", - "homepage": "http://robbast.nl" - } - ], - "description": "SPDX licenses list and validation library.", - "keywords": [ - "license", - "spdx", - "validator" - ], - "support": { - "irc": "irc://irc.freenode.org/composer", - "issues": "https://github.com/composer/spdx-licenses/issues", - "source": "https://github.com/composer/spdx-licenses/tree/1.5.5" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2020-12-03T16:04:16+00:00" - }, - { - "name": "composer/xdebug-handler", - "version": "2.0.2", - "source": { - "type": "git", - "url": "https://github.com/composer/xdebug-handler.git", - "reference": "84674dd3a7575ba617f5a76d7e9e29a7d3891339" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/84674dd3a7575ba617f5a76d7e9e29a7d3891339", - "reference": "84674dd3a7575ba617f5a76d7e9e29a7d3891339", - "shasum": "" - }, - "require": { - "php": "^5.3.2 || ^7.0 || ^8.0", - "psr/log": "^1 || ^2 || ^3" - }, - "require-dev": { - "phpstan/phpstan": "^0.12.55", - "symfony/phpunit-bridge": "^4.2 || ^5" - }, - "type": "library", - "autoload": { - "psr-4": { - "Composer\\XdebugHandler\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "John Stevenson", - "email": "john-stevenson@blueyonder.co.uk" - } - ], - "description": "Restarts a process without Xdebug.", - "keywords": [ - "Xdebug", - "performance" - ], - "support": { - "irc": "irc://irc.freenode.org/composer", - "issues": "https://github.com/composer/xdebug-handler/issues", - "source": "https://github.com/composer/xdebug-handler/tree/2.0.2" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2021-07-31T17:03:58+00:00" - }, { "name": "doctrine/instantiator", "version": "1.4.0", @@ -7453,6 +7463,59 @@ ], "time": "2020-11-10T18:47:58+00:00" }, + { + "name": "facade/ignition-contracts", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/facade/ignition-contracts.git", + "reference": "3c921a1cdba35b68a7f0ccffc6dffc1995b18267" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/facade/ignition-contracts/zipball/3c921a1cdba35b68a7f0ccffc6dffc1995b18267", + "reference": "3c921a1cdba35b68a7f0ccffc6dffc1995b18267", + "shasum": "" + }, + "require": { + "php": "^7.3|^8.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^v2.15.8", + "phpunit/phpunit": "^9.3.11", + "vimeo/psalm": "^3.17.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Facade\\IgnitionContracts\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "homepage": "https://flareapp.io", + "role": "Developer" + } + ], + "description": "Solution contracts for Ignition", + "homepage": "https://github.com/facade/ignition-contracts", + "keywords": [ + "contracts", + "flare", + "ignition" + ], + "support": { + "issues": "https://github.com/facade/ignition-contracts/issues", + "source": "https://github.com/facade/ignition-contracts/tree/1.0.2" + }, + "time": "2020-10-16T08:27:54+00:00" + }, { "name": "fakerphp/faker", "version": "v1.16.0", @@ -7569,76 +7632,6 @@ }, "time": "2020-07-09T08:09:16+00:00" }, - { - "name": "justinrainbow/json-schema", - "version": "5.2.11", - "source": { - "type": "git", - "url": "https://github.com/justinrainbow/json-schema.git", - "reference": "2ab6744b7296ded80f8cc4f9509abbff393399aa" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/2ab6744b7296ded80f8cc4f9509abbff393399aa", - "reference": "2ab6744b7296ded80f8cc4f9509abbff393399aa", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "~2.2.20||~2.15.1", - "json-schema/json-schema-test-suite": "1.2.0", - "phpunit/phpunit": "^4.8.35" - }, - "bin": [ - "bin/validate-json" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "JsonSchema\\": "src/JsonSchema/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bruno Prieto Reis", - "email": "bruno.p.reis@gmail.com" - }, - { - "name": "Justin Rainbow", - "email": "justin.rainbow@gmail.com" - }, - { - "name": "Igor Wiedler", - "email": "igor@wiedler.ch" - }, - { - "name": "Robert Schönthal", - "email": "seroscho@googlemail.com" - } - ], - "description": "A library to validate a json schema.", - "homepage": "https://github.com/justinrainbow/json-schema", - "keywords": [ - "json", - "schema" - ], - "support": { - "issues": "https://github.com/justinrainbow/json-schema/issues", - "source": "https://github.com/justinrainbow/json-schema/tree/5.2.11" - }, - "time": "2021-07-22T09:24:00+00:00" - }, { "name": "maximebf/debugbar", "version": "v1.17.2", @@ -7835,60 +7828,92 @@ "time": "2020-11-13T09:40:50+00:00" }, { - "name": "nikic/php-parser", - "version": "v4.13.0", + "name": "nunomaduro/collision", + "version": "v4.3.0", "source": { "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "50953a2691a922aa1769461637869a0a2faa3f53" + "url": "https://github.com/nunomaduro/collision.git", + "reference": "7c125dc2463f3e144ddc7e05e63077109508c94e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/50953a2691a922aa1769461637869a0a2faa3f53", - "reference": "50953a2691a922aa1769461637869a0a2faa3f53", + "url": "https://api.github.com/repos/nunomaduro/collision/zipball/7c125dc2463f3e144ddc7e05e63077109508c94e", + "reference": "7c125dc2463f3e144ddc7e05e63077109508c94e", "shasum": "" }, "require": { - "ext-tokenizer": "*", - "php": ">=7.0" + "facade/ignition-contracts": "^1.0", + "filp/whoops": "^2.4", + "php": "^7.2.5 || ^8.0", + "symfony/console": "^5.0" }, "require-dev": { - "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" + "facade/ignition": "^2.0", + "fideloper/proxy": "^4.2", + "friendsofphp/php-cs-fixer": "^2.16", + "fruitcake/laravel-cors": "^1.0", + "laravel/framework": "^7.0", + "laravel/tinker": "^2.0", + "nunomaduro/larastan": "^0.6", + "orchestra/testbench": "^5.0", + "phpstan/phpstan": "^0.12.3", + "phpunit/phpunit": "^8.5.1 || ^9.0" }, - "bin": [ - "bin/php-parse" - ], "type": "library", "extra": { - "branch-alias": { - "dev-master": "4.9-dev" + "laravel": { + "providers": [ + "NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider" + ] } }, "autoload": { "psr-4": { - "PhpParser\\": "lib/PhpParser" + "NunoMaduro\\Collision\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Nikita Popov" + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" } ], - "description": "A PHP parser written in PHP", + "description": "Cli error handling for console/command-line PHP applications.", "keywords": [ - "parser", - "php" + "artisan", + "cli", + "command-line", + "console", + "error", + "handling", + "laravel", + "laravel-zero", + "php", + "symfony" ], "support": { - "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.13.0" + "issues": "https://github.com/nunomaduro/collision/issues", + "source": "https://github.com/nunomaduro/collision" }, - "time": "2021-09-20T12:20:58+00:00" + "funding": [ + { + "url": "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=66BYDWAT92N6L", + "type": "custom" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + }, + { + "url": "https://www.patreon.com/nunomaduro", + "type": "patreon" + } + ], + "time": "2020-10-29T15:12:23+00:00" }, { "name": "phar-io/manifest", @@ -8649,56 +8674,6 @@ ], "time": "2021-09-25T07:38:51+00:00" }, - { - "name": "react/promise", - "version": "v2.8.0", - "source": { - "type": "git", - "url": "https://github.com/reactphp/promise.git", - "reference": "f3cff96a19736714524ca0dd1d4130de73dbbbc4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/reactphp/promise/zipball/f3cff96a19736714524ca0dd1d4130de73dbbbc4", - "reference": "f3cff96a19736714524ca0dd1d4130de73dbbbc4", - "shasum": "" - }, - "require": { - "php": ">=5.4.0" - }, - "require-dev": { - "phpunit/phpunit": "^7.0 || ^6.5 || ^5.7 || ^4.8.36" - }, - "type": "library", - "autoload": { - "psr-4": { - "React\\Promise\\": "src/" - }, - "files": [ - "src/functions_include.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jan Sorgalla", - "email": "jsorgalla@gmail.com" - } - ], - "description": "A lightweight implementation of CommonJS Promises/A for PHP", - "keywords": [ - "promise", - "promises" - ], - "support": { - "issues": "https://github.com/reactphp/promise/issues", - "source": "https://github.com/reactphp/promise/tree/v2.8.0" - }, - "time": "2020-05-12T15:16:56+00:00" - }, { "name": "sebastian/cli-parser", "version": "1.0.1", @@ -9664,33 +9639,37 @@ "time": "2020-09-28T06:39:44+00:00" }, { - "name": "seld/jsonlint", - "version": "1.8.3", + "name": "symfony/debug", + "version": "v4.4.31", "source": { "type": "git", - "url": "https://github.com/Seldaek/jsonlint.git", - "reference": "9ad6ce79c342fbd44df10ea95511a1b24dee5b57" + "url": "https://github.com/symfony/debug.git", + "reference": "43ede438d4cb52cd589ae5dc070e9323866ba8e0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/9ad6ce79c342fbd44df10ea95511a1b24dee5b57", - "reference": "9ad6ce79c342fbd44df10ea95511a1b24dee5b57", + "url": "https://api.github.com/repos/symfony/debug/zipball/43ede438d4cb52cd589ae5dc070e9323866ba8e0", + "reference": "43ede438d4cb52cd589ae5dc070e9323866ba8e0", "shasum": "" }, "require": { - "php": "^5.3 || ^7.0 || ^8.0" + "php": ">=7.1.3", + "psr/log": "^1|^2|^3" + }, + "conflict": { + "symfony/http-kernel": "<3.4" }, "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" + "symfony/http-kernel": "^3.4|^4.0|^5.0" }, - "bin": [ - "bin/jsonlint" - ], "type": "library", "autoload": { "psr-4": { - "Seld\\JsonLint\\": "src/Seld/JsonLint/" - } + "Symfony\\Component\\Debug\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -9698,81 +9677,34 @@ ], "authors": [ { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "JSON Linter", - "keywords": [ - "json", - "linter", - "parser", - "validator" - ], + "description": "Provides tools to ease debugging PHP code", + "homepage": "https://symfony.com", "support": { - "issues": "https://github.com/Seldaek/jsonlint/issues", - "source": "https://github.com/Seldaek/jsonlint/tree/1.8.3" + "source": "https://github.com/symfony/debug/tree/v4.4.31" }, "funding": [ { - "url": "https://github.com/Seldaek", + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", "type": "github" }, { - "url": "https://tidelift.com/funding/github/packagist/seld/jsonlint", + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2020-11-11T09:19:24+00:00" - }, - { - "name": "seld/phar-utils", - "version": "1.1.2", - "source": { - "type": "git", - "url": "https://github.com/Seldaek/phar-utils.git", - "reference": "749042a2315705d2dfbbc59234dd9ceb22bf3ff0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Seldaek/phar-utils/zipball/749042a2315705d2dfbbc59234dd9ceb22bf3ff0", - "reference": "749042a2315705d2dfbbc59234dd9ceb22bf3ff0", - "shasum": "" - }, - "require": { - "php": ">=5.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Seld\\PharUtils\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be" - } - ], - "description": "PHAR file format utilities, for when PHP phars you up", - "keywords": [ - "phar" - ], - "support": { - "issues": "https://github.com/Seldaek/phar-utils/issues", - "source": "https://github.com/Seldaek/phar-utils/tree/1.1.2" - }, - "time": "2021-08-19T21:01:38+00:00" + "time": "2021-09-24T13:30:14+00:00" }, { "name": "symfony/dom-crawler", @@ -9849,69 +9781,6 @@ ], "time": "2021-08-29T19:32:13+00:00" }, - { - "name": "symfony/filesystem", - "version": "v5.3.4", - "source": { - "type": "git", - "url": "https://github.com/symfony/filesystem.git", - "reference": "343f4fe324383ca46792cae728a3b6e2f708fb32" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/343f4fe324383ca46792cae728a3b6e2f708fb32", - "reference": "343f4fe324383ca46792cae728a3b6e2f708fb32", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-php80": "^1.16" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Filesystem\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides basic utilities for the filesystem", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/filesystem/tree/v5.3.4" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2021-07-21T12:40:44+00:00" - }, { "name": "theseer/tokenizer", "version": "1.2.1", diff --git a/database/migrations/2018_08_04_115700_create_bookshelves_table.php b/database/migrations/2018_08_04_115700_create_bookshelves_table.php index 04f46ce50..8dc2a72e9 100644 --- a/database/migrations/2018_08_04_115700_create_bookshelves_table.php +++ b/database/migrations/2018_08_04_115700_create_bookshelves_table.php @@ -120,11 +120,11 @@ class CreateBookshelvesTable extends Migration Schema::dropIfExists('bookshelves'); // Drop related polymorphic items - DB::table('activities')->where('entity_type', '=', 'BookStack\Entities\Models\Bookshelf')->delete(); - DB::table('views')->where('viewable_type', '=', 'BookStack\Entities\Models\Bookshelf')->delete(); - DB::table('entity_permissions')->where('restrictable_type', '=', 'BookStack\Entities\Models\Bookshelf')->delete(); - DB::table('tags')->where('entity_type', '=', 'BookStack\Entities\Models\Bookshelf')->delete(); - DB::table('search_terms')->where('entity_type', '=', 'BookStack\Entities\Models\Bookshelf')->delete(); - DB::table('comments')->where('entity_type', '=', 'BookStack\Entities\Models\Bookshelf')->delete(); + DB::table('activities')->where('entity_type', '=', \BookStack\Entities\Models\Bookshelf::class)->delete(); + DB::table('views')->where('viewable_type', '=', \BookStack\Entities\Models\Bookshelf::class)->delete(); + DB::table('entity_permissions')->where('restrictable_type', '=', \BookStack\Entities\Models\Bookshelf::class)->delete(); + DB::table('tags')->where('entity_type', '=', \BookStack\Entities\Models\Bookshelf::class)->delete(); + DB::table('search_terms')->where('entity_type', '=', \BookStack\Entities\Models\Bookshelf::class)->delete(); + DB::table('comments')->where('entity_type', '=', \BookStack\Entities\Models\Bookshelf::class)->delete(); } } diff --git a/phpunit.xml b/phpunit.xml index 7e0da05d4..960f4c4c3 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -1,15 +1,8 @@ + colors="true"> app/ diff --git a/resources/lang/ar/auth.php b/resources/lang/ar/auth.php index c0cc8bbc0..fa48d65e7 100644 --- a/resources/lang/ar/auth.php +++ b/resources/lang/ar/auth.php @@ -38,7 +38,6 @@ return [ 'registration_email_domain_invalid' => 'المجال الخاص بالبريد الإلكتروني لا يملك حق الوصول لهذا التطبيق', 'register_success' => 'شكراً لإنشاء حسابكم! تم تسجيلكم ودخولكم للحساب الخاص بكم.', - // Password Reset 'reset_password' => 'استعادة كلمة المرور', 'reset_password_send_instructions' => 'أدخل بريدك الإلكتروني بالأسفل وسيتم إرسال رسالة برابط لاستعادة كلمة المرور.', @@ -49,7 +48,6 @@ return [ 'email_reset_text' => 'تم إرسال هذه الرسالة بسبب تلقينا لطلب استعادة كلمة المرور الخاصة بحسابكم.', 'email_reset_not_requested' => 'إذا لم يتم طلب استعادة كلمة المرور من قبلكم، فلا حاجة لاتخاذ أية خطوات.', - // Email Confirmation 'email_confirm_subject' => 'تأكيد بريدكم الإلكتروني لتطبيق :appName', 'email_confirm_greeting' => 'شكرا لانضمامكم إلى :appName!', @@ -109,4 +107,4 @@ return [ 'mfa_verify_backup_code_enter_here' => 'Enter backup code here', 'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:', 'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.', -]; \ No newline at end of file +]; diff --git a/resources/lang/ar/common.php b/resources/lang/ar/common.php index de40e583e..53e18964d 100644 --- a/resources/lang/ar/common.php +++ b/resources/lang/ar/common.php @@ -20,7 +20,7 @@ return [ 'role' => 'الدور', 'cover_image' => 'صورة الغلاف', 'cover_image_description' => 'الصورة يجب أن تكون مقاربة لحجم 440×250 بكسل.', - + // Actions 'actions' => 'إجراءات', 'view' => 'عرض', diff --git a/resources/lang/ar/entities.php b/resources/lang/ar/entities.php index c9e3f322c..e4888d0b2 100644 --- a/resources/lang/ar/entities.php +++ b/resources/lang/ar/entities.php @@ -321,5 +321,5 @@ return [ 'revision_delete_confirm' => 'هل أنت متأكد من أنك تريد حذف هذه المراجعة؟', 'revision_restore_confirm' => 'هل أنت متأكد من أنك تريد استعادة هذه المراجعة؟ سيتم استبدال محتوى الصفحة الحالية.', 'revision_delete_success' => 'تم حذف المراجعة', - 'revision_cannot_delete_latest' => 'لايمكن حذف آخر مراجعة.' + 'revision_cannot_delete_latest' => 'لايمكن حذف آخر مراجعة.', ]; diff --git a/resources/lang/ar/passwords.php b/resources/lang/ar/passwords.php index 4ab447d5d..33b8e9c3e 100644 --- a/resources/lang/ar/passwords.php +++ b/resources/lang/ar/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'يجب أن تتكون كلمة المرور من ستة أحرف على الأقل وأن تطابق التأكيد.', - 'user' => "لم يتم العثور على مستخدم بعنوان البريد الإلكتروني المعطى.", + 'user' => 'لم يتم العثور على مستخدم بعنوان البريد الإلكتروني المعطى.', 'token' => 'رمز إعادة تعيين كلمة المرور غير صالح لعنوان هذا البريد الإلكتروني.', 'sent' => 'تم إرسال رابط تجديد كلمة المرور إلى بريدكم الإلكتروني!', 'reset' => 'تم تجديد كلمة المرور الخاصة بكم!', diff --git a/resources/lang/ar/settings.php b/resources/lang/ar/settings.php index b4ccd9482..f3ebc3039 100755 --- a/resources/lang/ar/settings.php +++ b/resources/lang/ar/settings.php @@ -72,7 +72,7 @@ return [ // Maintenance settings 'maint' => 'الصيانة', 'maint_image_cleanup' => 'تنظيف الصور', - 'maint_image_cleanup_desc' => "مسح الصفحة ومراجعة المحتوى للتحقق من أي الصور والرسوم المستخدمة حاليًا وأي الصور زائدة عن الحاجة. تأكد من إنشاء قاعدة بيانات كاملة و نسخة احتياطية للصور قبل تشغيل هذا.", + 'maint_image_cleanup_desc' => 'مسح الصفحة ومراجعة المحتوى للتحقق من أي الصور والرسوم المستخدمة حاليًا وأي الصور زائدة عن الحاجة. تأكد من إنشاء قاعدة بيانات كاملة و نسخة احتياطية للصور قبل تشغيل هذا.', 'maint_delete_images_only_in_revisions' => 'Also delete images that only exist in old page revisions', 'maint_image_cleanup_run' => 'بدء التنظيف', 'maint_image_cleanup_warning' => 'يوجد عدد :count من الصور المحتمل عدم استخدامها. تأكيد حذف الصور؟', @@ -132,7 +132,7 @@ return [ 'role_delete' => 'حذف الدور', 'role_delete_confirm' => 'سيتم حذف الدور المسمى \':roleName\'.', 'role_delete_users_assigned' => 'هذا الدور له: عدد المستخدمين المعينين له. إذا كنت ترغب في ترحيل المستخدمين من هذا الدور ، فحدد دورًا جديدًا أدناه.', - 'role_delete_no_migration' => "لا تقم بترجيل المستخدمين", + 'role_delete_no_migration' => 'لا تقم بترجيل المستخدمين', 'role_delete_sure' => 'تأكيد حذف الدور؟', 'role_delete_success' => 'تم حذف الدور بنجاح', 'role_edit' => 'تعديل الدور', @@ -273,6 +273,6 @@ return [ 'vi' => 'Tiếng Việt', 'zh_CN' => '简体中文', 'zh_TW' => '繁體中文', - ] + ], //!//////////////////////////////// ]; diff --git a/resources/lang/bg/auth.php b/resources/lang/bg/auth.php index d04796cfe..50499fc78 100644 --- a/resources/lang/bg/auth.php +++ b/resources/lang/bg/auth.php @@ -38,7 +38,6 @@ return [ 'registration_email_domain_invalid' => 'Този емейл домейн към момента няма достъп до приложението', 'register_success' => 'Благодарим Ви за регистрацията! В момента сте регистриран и сте вписани в приложението.', - // Password Reset 'reset_password' => 'Нулиране на паролата', 'reset_password_send_instructions' => 'Въведете емейла си и ще ви бъде изпратен емейл с линк за нулиране на паролата.', @@ -49,7 +48,6 @@ return [ 'email_reset_text' => 'Вие получихте този емейл, защото поискахте вашата парола да бъде занулена.', 'email_reset_not_requested' => 'Ако Вие не сте поискали зануляването на паролата, няма нужда от други действия.', - // Email Confirmation 'email_confirm_subject' => 'Потвърди емейла си за :appName', 'email_confirm_greeting' => 'Благодарим Ви, че се присъединихте към :appName!', @@ -109,4 +107,4 @@ return [ 'mfa_verify_backup_code_enter_here' => 'Enter backup code here', 'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:', 'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.', -]; \ No newline at end of file +]; diff --git a/resources/lang/bg/common.php b/resources/lang/bg/common.php index 4b0f72a60..110487a41 100644 --- a/resources/lang/bg/common.php +++ b/resources/lang/bg/common.php @@ -20,7 +20,7 @@ return [ 'role' => 'Роля', 'cover_image' => 'Основно изображение', 'cover_image_description' => 'Картината трябва да е приблизително 440х250 пиксела.', - + // Actions 'actions' => 'Действия', 'view' => 'Преглед', diff --git a/resources/lang/bg/entities.php b/resources/lang/bg/entities.php index bfcfb2758..1db29c5e3 100644 --- a/resources/lang/bg/entities.php +++ b/resources/lang/bg/entities.php @@ -321,5 +321,5 @@ return [ 'revision_delete_confirm' => 'Наистина ли искате да изтриете тази версия?', 'revision_restore_confirm' => 'Сигурни ли сте, че искате да изтриете тази версия? Настоящата страница ще бъде заместена.', 'revision_delete_success' => 'Версията беше изтрита', - 'revision_cannot_delete_latest' => 'Не може да изтриете последната версия.' + 'revision_cannot_delete_latest' => 'Не може да изтриете последната версия.', ]; diff --git a/resources/lang/bg/passwords.php b/resources/lang/bg/passwords.php index 871fdeea8..5fb192a44 100644 --- a/resources/lang/bg/passwords.php +++ b/resources/lang/bg/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'Паролите трябва да имат поне 8 символа и да съвпадат с потвърждението.', - 'user' => "Не можем да намерим потребител с този имейл адрес.", + 'user' => 'Не можем да намерим потребител с този имейл адрес.', 'token' => 'Кодът за зануляване на паролата е невалиден за този емейл адрес.', 'sent' => 'Пратихме връзка за нулиране на паролата до имейла ви!', 'reset' => 'Вашата парола е нулирана!', diff --git a/resources/lang/bg/settings.php b/resources/lang/bg/settings.php index e6afe7101..2151e2e20 100644 --- a/resources/lang/bg/settings.php +++ b/resources/lang/bg/settings.php @@ -72,7 +72,7 @@ return [ // Maintenance settings 'maint' => 'Maintenance', 'maint_image_cleanup' => 'Cleanup Images', - 'maint_image_cleanup_desc' => "Scans page & revision content to check which images and drawings are currently in use and which images are redundant. Ensure you create a full database and image backup before running this.", + 'maint_image_cleanup_desc' => 'Scans page & revision content to check which images and drawings are currently in use and which images are redundant. Ensure you create a full database and image backup before running this.', 'maint_delete_images_only_in_revisions' => 'Also delete images that only exist in old page revisions', 'maint_image_cleanup_run' => 'Run Cleanup', 'maint_image_cleanup_warning' => ':count potentially unused images were found. Are you sure you want to delete these images?', @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Изтрий роля', 'role_delete_confirm' => 'Това ще изтрие ролята \':roleName\'.', 'role_delete_users_assigned' => 'В тази роля се намират :userCount потребители. Ако искате да преместите тези потребители в друга роля, моля изберете нова роля отдолу.', - 'role_delete_no_migration' => "Не премествай потребителите в нова роля", + 'role_delete_no_migration' => 'Не премествай потребителите в нова роля', 'role_delete_sure' => 'Сигурни ли сте, че искате да изтриете тази роля?', 'role_delete_success' => 'Ролята беше успешно изтрита', 'role_edit' => 'Редактиране на роля', @@ -273,6 +273,6 @@ return [ 'vi' => 'Tiếng Việt', 'zh_CN' => '简体中文', 'zh_TW' => '繁體中文', - ] + ], //!//////////////////////////////// ]; diff --git a/resources/lang/bs/auth.php b/resources/lang/bs/auth.php index a5926fa2b..3a5517331 100644 --- a/resources/lang/bs/auth.php +++ b/resources/lang/bs/auth.php @@ -38,7 +38,6 @@ return [ 'registration_email_domain_invalid' => 'Ta e-mail domena nema pristup ovoj aplikaciji', 'register_success' => 'Hvala na registraciji! Sada ste registrovani i prijavljeni.', - // Password Reset 'reset_password' => 'Resetuj Lozinku', 'reset_password_send_instructions' => 'Unesite vašu e-mail adresu ispod i na nju ćemo vam poslati e-mail sa linkom za promjenu lozinke.', @@ -49,7 +48,6 @@ return [ 'email_reset_text' => 'Primate ovaj e-mail jer smo dobili zahtjev za promjenu lozinke za vaš račun.', 'email_reset_not_requested' => 'Ako niste zahtijevali promjenu lozinke ne trebate ništa više uraditi.', - // Email Confirmation 'email_confirm_subject' => 'Potvrdite vaš e-mail na :appName', 'email_confirm_greeting' => 'Hvala na pristupanju :appName!', @@ -109,4 +107,4 @@ return [ 'mfa_verify_backup_code_enter_here' => 'Enter backup code here', 'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:', 'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.', -]; \ No newline at end of file +]; diff --git a/resources/lang/bs/common.php b/resources/lang/bs/common.php index 17ec0b765..a511a10be 100644 --- a/resources/lang/bs/common.php +++ b/resources/lang/bs/common.php @@ -20,7 +20,7 @@ return [ 'role' => 'Uloga', 'cover_image' => 'Naslovna slika', 'cover_image_description' => 'Ova slika treba biti približno 440x250px.', - + // Actions 'actions' => 'Akcije', 'view' => 'Prikaz', diff --git a/resources/lang/bs/entities.php b/resources/lang/bs/entities.php index 102019d2a..680053bc9 100644 --- a/resources/lang/bs/entities.php +++ b/resources/lang/bs/entities.php @@ -321,5 +321,5 @@ return [ 'revision_delete_confirm' => 'Are you sure you want to delete this revision?', 'revision_restore_confirm' => 'Are you sure you want to restore this revision? The current page contents will be replaced.', 'revision_delete_success' => 'Revision deleted', - 'revision_cannot_delete_latest' => 'Cannot delete the latest revision.' + 'revision_cannot_delete_latest' => 'Cannot delete the latest revision.', ]; diff --git a/resources/lang/bs/passwords.php b/resources/lang/bs/passwords.php index 0383e8af0..54880f4b5 100644 --- a/resources/lang/bs/passwords.php +++ b/resources/lang/bs/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'Lozinke moraju sadržavati najmanje osam karaktera i podudarati se sa potvrdom lozinke.', - 'user' => "Ne možemo naći korisnika sa tom e-mail adresom.", + 'user' => 'Ne možemo naći korisnika sa tom e-mail adresom.', 'token' => 'Token za poništavanje lozinke nije validan za ovu e-mail adresu.', 'sent' => 'Poslali smo link za poništavanje vaše lozinke na e-mail!', 'reset' => 'Vaša lozinka je resetovana!', diff --git a/resources/lang/bs/settings.php b/resources/lang/bs/settings.php index 46df0d07d..335a1b436 100644 --- a/resources/lang/bs/settings.php +++ b/resources/lang/bs/settings.php @@ -72,7 +72,7 @@ return [ // Maintenance settings 'maint' => 'Maintenance', 'maint_image_cleanup' => 'Cleanup Images', - 'maint_image_cleanup_desc' => "Scans page & revision content to check which images and drawings are currently in use and which images are redundant. Ensure you create a full database and image backup before running this.", + 'maint_image_cleanup_desc' => 'Scans page & revision content to check which images and drawings are currently in use and which images are redundant. Ensure you create a full database and image backup before running this.', 'maint_delete_images_only_in_revisions' => 'Also delete images that only exist in old page revisions', 'maint_image_cleanup_run' => 'Run Cleanup', 'maint_image_cleanup_warning' => ':count potentially unused images were found. Are you sure you want to delete these images?', @@ -273,6 +273,6 @@ return [ 'vi' => 'Tiếng Việt', 'zh_CN' => '简体中文', 'zh_TW' => '繁體中文', - ] + ], //!//////////////////////////////// ]; diff --git a/resources/lang/ca/auth.php b/resources/lang/ca/auth.php index 9febe36b7..e22ca74bf 100644 --- a/resources/lang/ca/auth.php +++ b/resources/lang/ca/auth.php @@ -38,7 +38,6 @@ return [ 'registration_email_domain_invalid' => 'Aquest domini de correu electrònic no té accés a aquesta aplicació', 'register_success' => 'Gràcies per registrar-vos! Ja us hi heu registrat i heu iniciat la sessió.', - // Password Reset 'reset_password' => 'Restableix la contrasenya', 'reset_password_send_instructions' => 'Introduïu la vostra adreça electrònica a continuació i us enviarem un correu electrònic amb un enllaç per a restablir la contrasenya.', @@ -49,7 +48,6 @@ return [ 'email_reset_text' => 'Rebeu aquest correu electrònic perquè heu rebut una petició de restabliment de contrasenya per al vostre compte.', 'email_reset_not_requested' => 'Si no heu demanat restablir la contrasenya, no cal que prengueu cap acció.', - // Email Confirmation 'email_confirm_subject' => 'Confirmeu la vostra adreça electrònica a :appName', 'email_confirm_greeting' => 'Gràcies per unir-vos a :appName!', @@ -109,4 +107,4 @@ return [ 'mfa_verify_backup_code_enter_here' => 'Enter backup code here', 'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:', 'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.', -]; \ No newline at end of file +]; diff --git a/resources/lang/ca/common.php b/resources/lang/ca/common.php index 497395060..0f18099e7 100644 --- a/resources/lang/ca/common.php +++ b/resources/lang/ca/common.php @@ -20,7 +20,7 @@ return [ 'role' => 'Rol', 'cover_image' => 'Imatge de portada', 'cover_image_description' => 'Aquesta imatge hauria de fer aproximadament 440x250 px.', - + // Actions 'actions' => 'Accions', 'view' => 'Visualitza', diff --git a/resources/lang/ca/entities.php b/resources/lang/ca/entities.php index 36466e920..d486fe512 100644 --- a/resources/lang/ca/entities.php +++ b/resources/lang/ca/entities.php @@ -321,5 +321,5 @@ return [ 'revision_delete_confirm' => 'Segur que voleu suprimir aquesta revisió?', 'revision_restore_confirm' => 'Segur que voleu restaurar aquesta revisió? Se substituirà el contingut de la pàgina actual.', 'revision_delete_success' => 'S\'ha suprimit la revisió', - 'revision_cannot_delete_latest' => 'No es pot suprimir la darrera revisió.' + 'revision_cannot_delete_latest' => 'No es pot suprimir la darrera revisió.', ]; diff --git a/resources/lang/ca/settings.php b/resources/lang/ca/settings.php index 74e692798..4a1e66855 100755 --- a/resources/lang/ca/settings.php +++ b/resources/lang/ca/settings.php @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Suprimeix el rol', 'role_delete_confirm' => 'Se suprimirà el rol amb el nom \':roleName\'.', 'role_delete_users_assigned' => 'Aquest rol té :userCount usuaris assignats. Si voleu migrar els usuaris d\'aquest rol, seleccioneu un rol nou a continuació.', - 'role_delete_no_migration' => "No migris els usuaris", + 'role_delete_no_migration' => 'No migris els usuaris', 'role_delete_sure' => 'Segur que voleu suprimir aquest rol?', 'role_delete_success' => 'Rol suprimit correctament', 'role_edit' => 'Edita el rol', @@ -273,6 +273,6 @@ return [ 'vi' => 'Tiếng Việt', 'zh_CN' => '简体中文', 'zh_TW' => '繁體中文', - ] + ], //!//////////////////////////////// ]; diff --git a/resources/lang/cs/auth.php b/resources/lang/cs/auth.php index ad83a6926..f95242009 100644 --- a/resources/lang/cs/auth.php +++ b/resources/lang/cs/auth.php @@ -38,7 +38,6 @@ return [ 'registration_email_domain_invalid' => 'Registrace z této e-mailové domény nejsou povoleny', 'register_success' => 'Děkujeme za registraci! Nyní jste zaregistrováni a přihlášeni.', - // Password Reset 'reset_password' => 'Obnovit heslo', 'reset_password_send_instructions' => 'Níže zadejte svou e-mailovou adresu a bude vám zaslán e-mail s odkazem na obnovení hesla.', @@ -49,7 +48,6 @@ return [ 'email_reset_text' => 'Tento e-mail jste obdrželi, protože jsme obdrželi žádost o obnovení hesla k vašemu účtu.', 'email_reset_not_requested' => 'Pokud jste o obnovení hesla nežádali, není vyžadována žádná další akce.', - // Email Confirmation 'email_confirm_subject' => 'Potvrďte svůj e-mail pro :appName', 'email_confirm_greeting' => 'Díky že jste se přidali do :appName!', @@ -109,4 +107,4 @@ return [ 'mfa_verify_backup_code_enter_here' => 'Enter backup code here', 'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:', 'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.', -]; \ No newline at end of file +]; diff --git a/resources/lang/cs/common.php b/resources/lang/cs/common.php index 14555a912..d837116ee 100644 --- a/resources/lang/cs/common.php +++ b/resources/lang/cs/common.php @@ -20,7 +20,7 @@ return [ 'role' => 'Role', 'cover_image' => 'Obrázek obálky', 'cover_image_description' => 'Obrázek by měl být přibližně 440×250px.', - + // Actions 'actions' => 'Akce', 'view' => 'Zobrazit', diff --git a/resources/lang/cs/entities.php b/resources/lang/cs/entities.php index d82d4c2ea..548c01a84 100644 --- a/resources/lang/cs/entities.php +++ b/resources/lang/cs/entities.php @@ -94,7 +94,7 @@ return [ 'shelves_edit' => 'Upravit knihovnu', 'shelves_delete' => 'Odstranit knihovnu', 'shelves_delete_named' => 'Odstranit knihovnu :name', - 'shelves_delete_explain' => "Toto odstraní knihovnu ‚:name‘. Vložené knihy nebudou odstraněny.", + 'shelves_delete_explain' => 'Toto odstraní knihovnu ‚:name‘. Vložené knihy nebudou odstraněny.', 'shelves_delete_confirmation' => 'Opravdu chcete odstranit tuto knihovnu?', 'shelves_permissions' => 'Oprávnění knihovny', 'shelves_permissions_updated' => 'Oprávnění knihovny byla aktualizována', @@ -321,5 +321,5 @@ return [ 'revision_delete_confirm' => 'Opravdu chcete odstranit tuto revizi?', 'revision_restore_confirm' => 'Jste si jisti, že chcete obnovit tuto revizi? Aktuální obsah stránky bude nahrazen.', 'revision_delete_success' => 'Revize odstraněna', - 'revision_cannot_delete_latest' => 'Nelze odstranit poslední revizi.' + 'revision_cannot_delete_latest' => 'Nelze odstranit poslední revizi.', ]; diff --git a/resources/lang/cs/passwords.php b/resources/lang/cs/passwords.php index 40b12b607..b25e24f3c 100644 --- a/resources/lang/cs/passwords.php +++ b/resources/lang/cs/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'Heslo musí mít alespoň osm znaků a musí odpovídat potvrzení hesla.', - 'user' => "Nemůžeme nalézt uživatele s touto e-mailovou adresou.", + 'user' => 'Nemůžeme nalézt uživatele s touto e-mailovou adresou.', 'token' => 'Token pro obnovení hesla není platný pro tuto e-mailovou adresu.', 'sent' => 'Poslali jsme Vám e-mail s odkazem pro obnovení hesla!', 'reset' => 'Vaše heslo bylo obnoveno!', diff --git a/resources/lang/cs/settings.php b/resources/lang/cs/settings.php index b2e840044..b4a726830 100644 --- a/resources/lang/cs/settings.php +++ b/resources/lang/cs/settings.php @@ -72,7 +72,7 @@ return [ // Maintenance settings 'maint' => 'Údržba', 'maint_image_cleanup' => 'Pročistění obrázků', - 'maint_image_cleanup_desc' => "Prohledá stránky a jejich revize, aby zjistil, které obrázky a kresby jsou momentálně používány a které jsou zbytečné. Zajistěte plnou zálohu databáze a obrázků než se do toho pustíte.", + 'maint_image_cleanup_desc' => 'Prohledá stránky a jejich revize, aby zjistil, které obrázky a kresby jsou momentálně používány a které jsou zbytečné. Zajistěte plnou zálohu databáze a obrázků než se do toho pustíte.', 'maint_delete_images_only_in_revisions' => 'Odstranit i obrázky, které se vyskytují pouze ve starých revizích stránky', 'maint_image_cleanup_run' => 'Spustit pročištění', 'maint_image_cleanup_warning' => 'Nalezeno :count potenciálně nepoužitých obrázků. Jste si jisti, že je chcete odstranit?', @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Odstranit roli', 'role_delete_confirm' => 'Role \':roleName\' bude odstraněna.', 'role_delete_users_assigned' => 'Role je přiřazena :userCount uživatelům. Pokud jim chcete náhradou přidělit jinou roli, zvolte jednu z následujících.', - 'role_delete_no_migration' => "Nepřiřazovat uživatelům náhradní roli", + 'role_delete_no_migration' => 'Nepřiřazovat uživatelům náhradní roli', 'role_delete_sure' => 'Opravdu chcete tuto roli odstranit?', 'role_delete_success' => 'Role byla odstraněna', 'role_edit' => 'Upravit roli', @@ -273,6 +273,6 @@ return [ 'vi' => 'Tiếng Việt', 'zh_CN' => '简体中文', 'zh_TW' => '繁體中文', - ] + ], //!//////////////////////////////// ]; diff --git a/resources/lang/da/auth.php b/resources/lang/da/auth.php index 8c9d86ea6..6b627c027 100644 --- a/resources/lang/da/auth.php +++ b/resources/lang/da/auth.php @@ -38,7 +38,6 @@ return [ 'registration_email_domain_invalid' => 'E-Mail domænet har ikke adgang til denne applikation', 'register_success' => 'Tak for din registrering. Du er nu registeret og logget ind.', - // Password Reset 'reset_password' => 'Nulstil adgangskode', 'reset_password_send_instructions' => 'Indtast din E-Mail herunder og du vil blive sendt en E-Mail med et link til at nulstille din adgangskode.', @@ -49,7 +48,6 @@ return [ 'email_reset_text' => 'Du modtager denne E-Mail fordi vi har modtaget en anmodning om at nulstille din adgangskode.', 'email_reset_not_requested' => 'Hvis du ikke har anmodet om at få din adgangskode nulstillet, behøver du ikke at foretage dig noget.', - // Email Confirmation 'email_confirm_subject' => 'Bekræft din E-Mail på :appName', 'email_confirm_greeting' => 'Tak for at oprette dig på :appName!', @@ -109,4 +107,4 @@ return [ 'mfa_verify_backup_code_enter_here' => 'Enter backup code here', 'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:', 'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.', -]; \ No newline at end of file +]; diff --git a/resources/lang/da/common.php b/resources/lang/da/common.php index 0e4269734..563aff97b 100644 --- a/resources/lang/da/common.php +++ b/resources/lang/da/common.php @@ -20,7 +20,7 @@ return [ 'role' => 'Rolle', 'cover_image' => 'Coverbillede', 'cover_image_description' => 'Dette billede skal være omtrent 440x250px.', - + // Actions 'actions' => 'Handlinger', 'view' => 'Vis', diff --git a/resources/lang/da/entities.php b/resources/lang/da/entities.php index 0d9d67cb4..3c2f56474 100644 --- a/resources/lang/da/entities.php +++ b/resources/lang/da/entities.php @@ -321,5 +321,5 @@ return [ 'revision_delete_confirm' => 'Er du sikker på at du vil slette denne revision?', 'revision_restore_confirm' => 'Er du sikker på at du ønsker at gendanne denne revision? Nuværende sideindhold vil blive erstattet.', 'revision_delete_success' => 'Revision slettet', - 'revision_cannot_delete_latest' => 'Kan ikke slette seneste revision.' + 'revision_cannot_delete_latest' => 'Kan ikke slette seneste revision.', ]; diff --git a/resources/lang/da/passwords.php b/resources/lang/da/passwords.php index 343fa2b85..39ed9418f 100644 --- a/resources/lang/da/passwords.php +++ b/resources/lang/da/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'Adgangskoder skal være mindst otte tegn og svare til bekræftelsen.', - 'user' => "Vi kan ikke finde en bruger med den e-mail adresse.", + 'user' => 'Vi kan ikke finde en bruger med den e-mail adresse.', 'token' => 'Linket til nulstilling af adgangskode er ugyldigt for denne e-mail-adresse.', 'sent' => 'Vi har sendt dig en e-mail med et link til at nulstille adgangskoden!', 'reset' => 'Dit kodeord er blevet nulstillet!', diff --git a/resources/lang/da/settings.php b/resources/lang/da/settings.php index 804a67bba..83b27aaab 100644 --- a/resources/lang/da/settings.php +++ b/resources/lang/da/settings.php @@ -72,7 +72,7 @@ return [ // Maintenance settings 'maint' => 'Vedligeholdelse', 'maint_image_cleanup' => 'Ryd op i billeder', - 'maint_image_cleanup_desc' => "Scanner side & revisionsindhold for at kontrollere, hvilke billeder og tegninger, der i øjeblikket er i brug, og hvilke billeder, der er overflødige. Sørg for, at du opretter en komplet database og billedbackup, før du kører dette.", + 'maint_image_cleanup_desc' => 'Scanner side & revisionsindhold for at kontrollere, hvilke billeder og tegninger, der i øjeblikket er i brug, og hvilke billeder, der er overflødige. Sørg for, at du opretter en komplet database og billedbackup, før du kører dette.', 'maint_delete_images_only_in_revisions' => 'Slet også billeder, der kun findes i gamle siderevisioner', 'maint_image_cleanup_run' => 'Kør Oprydning', 'maint_image_cleanup_warning' => 'der blev fundet :count potentielt ubrugte billeder. Er du sikker på, at du vil slette disse billeder?', @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Slet rolle', 'role_delete_confirm' => 'Dette vil slette rollen med navnet \':roleName\'.', 'role_delete_users_assigned' => 'Denne rolle er tildelt :userCount brugere. Hvis du vil rykke disse brugere fra denne rolle, kan du vælge en ny nedenunder.', - 'role_delete_no_migration' => "Ryk ikke brugere", + 'role_delete_no_migration' => 'Ryk ikke brugere', 'role_delete_sure' => 'Er du sikker på, at du vil slette denne rolle?', 'role_delete_success' => 'Rollen blev slettet', 'role_edit' => 'Rediger rolle', @@ -273,6 +273,6 @@ return [ 'vi' => 'Tiếng Việt', 'zh_CN' => '简体中文', 'zh_TW' => '繁體中文', - ] + ], //!//////////////////////////////// ]; diff --git a/resources/lang/de/auth.php b/resources/lang/de/auth.php index efe82680d..2c0989272 100644 --- a/resources/lang/de/auth.php +++ b/resources/lang/de/auth.php @@ -38,7 +38,6 @@ return [ 'registration_email_domain_invalid' => 'Sie können sich mit dieser E-Mail nicht registrieren.', 'register_success' => 'Vielen Dank für Ihre Registrierung! Die Daten sind gespeichert und Sie sind angemeldet.', - // Password Reset 'reset_password' => 'Passwort vergessen', 'reset_password_send_instructions' => 'Bitte geben Sie Ihre E-Mail-Adresse ein. Danach erhalten Sie eine E-Mail mit einem Link zum Zurücksetzen Ihres Passwortes.', @@ -49,7 +48,6 @@ return [ 'email_reset_text' => 'Sie erhalten diese E-Mail, weil jemand versucht hat, Ihr Passwort zurückzusetzen.', 'email_reset_not_requested' => 'Wenn Sie das nicht waren, brauchen Sie nichts weiter zu tun.', - // Email Confirmation 'email_confirm_subject' => 'Bestätigen Sie Ihre E-Mail-Adresse für :appName', 'email_confirm_greeting' => 'Danke, dass Sie sich für :appName registriert haben!', @@ -109,4 +107,4 @@ return [ 'mfa_verify_backup_code_enter_here' => 'Backup-Code hier eingeben', 'mfa_verify_totp_desc' => 'Geben Sie den Code ein, der mit Ihrer mobilen App generiert wurde:', 'mfa_setup_login_notification' => 'Multi-Faktor-Methode konfiguriert. Bitte melden Sie sich jetzt erneut mit der konfigurierten Methode an.', -]; \ No newline at end of file +]; diff --git a/resources/lang/de/common.php b/resources/lang/de/common.php index bd75e1737..fddd735f4 100644 --- a/resources/lang/de/common.php +++ b/resources/lang/de/common.php @@ -20,7 +20,7 @@ return [ 'role' => 'Rolle', 'cover_image' => 'Titelbild', 'cover_image_description' => 'Das Bild sollte eine Auflösung von 440x250px haben.', - + // Actions 'actions' => 'Aktionen', 'view' => 'Anzeigen', diff --git a/resources/lang/de/entities.php b/resources/lang/de/entities.php index 200961c97..d23eb679f 100644 --- a/resources/lang/de/entities.php +++ b/resources/lang/de/entities.php @@ -321,5 +321,5 @@ return [ 'revision_delete_confirm' => 'Sind Sie sicher, dass Sie diese Revision löschen wollen?', 'revision_restore_confirm' => 'Sind Sie sicher, dass Sie diese Revision wiederherstellen wollen? Der aktuelle Seiteninhalt wird ersetzt.', 'revision_delete_success' => 'Revision gelöscht', - 'revision_cannot_delete_latest' => 'Die letzte Version kann nicht gelöscht werden.' + 'revision_cannot_delete_latest' => 'Die letzte Version kann nicht gelöscht werden.', ]; diff --git a/resources/lang/de/passwords.php b/resources/lang/de/passwords.php index 3da092cb8..5f3762e16 100644 --- a/resources/lang/de/passwords.php +++ b/resources/lang/de/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'Passwörter müssen aus mindestens sechs Zeichen bestehen und mit der eingegebenen Wiederholung übereinstimmen.', - 'user' => "Es wurde kein Benutzer mit dieser E-Mail-Adresse gefunden.", + 'user' => 'Es wurde kein Benutzer mit dieser E-Mail-Adresse gefunden.', 'token' => 'Der Link zum Zurücksetzen Ihres Passworts ist entweder ungültig oder abgelaufen.', 'sent' => 'Der Link zum Zurücksetzen Ihres Passwortes wurde Ihnen per E-Mail zugesendet.', 'reset' => 'Ihr Passwort wurde zurückgesetzt!', diff --git a/resources/lang/de/settings.php b/resources/lang/de/settings.php index 5d6c19d10..1d1c47060 100644 --- a/resources/lang/de/settings.php +++ b/resources/lang/de/settings.php @@ -75,7 +75,7 @@ Hinweis: Benutzer können ihre E-Mail Adresse nach erfolgreicher Registrierung // Maintenance settings 'maint' => 'Wartung', 'maint_image_cleanup' => 'Bilder bereinigen', - 'maint_image_cleanup_desc' => "Überprüft Seiten- und Versionsinhalte auf ungenutzte und mehrfach vorhandene Bilder. Erstellen Sie vor dem Start ein Backup Ihrer Datenbank und Bilder.", + 'maint_image_cleanup_desc' => 'Überprüft Seiten- und Versionsinhalte auf ungenutzte und mehrfach vorhandene Bilder. Erstellen Sie vor dem Start ein Backup Ihrer Datenbank und Bilder.', 'maint_delete_images_only_in_revisions' => 'Lösche auch Bilder, die nur in alten Seitenüberarbeitungen vorhanden sind', 'maint_image_cleanup_run' => 'Reinigung starten', 'maint_image_cleanup_warning' => ':count eventuell unbenutze Bilder wurden gefunden. Möchten Sie diese Bilder löschen?', @@ -135,7 +135,7 @@ Hinweis: Benutzer können ihre E-Mail Adresse nach erfolgreicher Registrierung 'role_delete' => 'Rolle löschen', 'role_delete_confirm' => 'Sie möchten die Rolle ":roleName" löschen.', 'role_delete_users_assigned' => 'Diese Rolle ist :userCount Benutzern zugeordnet. Sie können unten eine neue Rolle auswählen, die Sie diesen Benutzern zuordnen möchten.', - 'role_delete_no_migration' => "Den Benutzern keine andere Rolle zuordnen", + 'role_delete_no_migration' => 'Den Benutzern keine andere Rolle zuordnen', 'role_delete_sure' => 'Sind Sie sicher, dass Sie diese Rolle löschen möchten?', 'role_delete_success' => 'Rolle erfolgreich gelöscht', 'role_edit' => 'Rolle bearbeiten', @@ -276,6 +276,6 @@ Hinweis: Benutzer können ihre E-Mail Adresse nach erfolgreicher Registrierung 'vi' => 'Tiếng Việt', 'zh_CN' => '简体中文', 'zh_TW' => '繁體中文', - ] + ], //!//////////////////////////////// ]; diff --git a/resources/lang/de_informal/auth.php b/resources/lang/de_informal/auth.php index 70da5bae2..de845ba7d 100644 --- a/resources/lang/de_informal/auth.php +++ b/resources/lang/de_informal/auth.php @@ -38,7 +38,6 @@ return [ 'registration_email_domain_invalid' => 'Du kannst dich mit dieser E-Mail nicht registrieren.', 'register_success' => 'Vielen Dank für deine Registrierung! Du bist jetzt registriert und eingeloggt.', - // Password Reset 'reset_password' => 'Passwort vergessen', 'reset_password_send_instructions' => 'Bitte gib Deine E-Mail-Adresse ein. Danach erhältst Du eine E-Mail mit einem Link zum Zurücksetzen Deines Passwortes.', @@ -49,7 +48,6 @@ return [ 'email_reset_text' => 'Du erhältsts diese E-Mail, weil jemand versucht hat, Dein Passwort zurückzusetzen.', 'email_reset_not_requested' => 'Wenn du das zurücksetzen des Passworts nicht angefordert hast, ist keine weitere Aktion erforderlich.', - // Email Confirmation 'email_confirm_subject' => 'Bestätige Deine E-Mail-Adresse für :appName', 'email_confirm_greeting' => 'Danke, dass Du dich für :appName registrierst hast!', @@ -109,4 +107,4 @@ return [ 'mfa_verify_backup_code_enter_here' => 'Backup-Code hier eingeben', 'mfa_verify_totp_desc' => 'Geben Sie den Code ein, der mit Ihrer mobilen App generiert wurde:', 'mfa_setup_login_notification' => 'Multi-Faktor-Methode konfiguriert. Bitte melden Sie sich jetzt erneut mit der konfigurierten Methode an.', -]; \ No newline at end of file +]; diff --git a/resources/lang/de_informal/common.php b/resources/lang/de_informal/common.php index 898df928e..a3663396e 100644 --- a/resources/lang/de_informal/common.php +++ b/resources/lang/de_informal/common.php @@ -20,7 +20,7 @@ return [ 'role' => 'Rolle', 'cover_image' => 'Titelbild', 'cover_image_description' => 'Das Bild sollte eine Auflösung von 440x250px haben.', - + // Actions 'actions' => 'Aktionen', 'view' => 'Anzeigen', diff --git a/resources/lang/de_informal/entities.php b/resources/lang/de_informal/entities.php index 712421b1f..c29a7db2c 100644 --- a/resources/lang/de_informal/entities.php +++ b/resources/lang/de_informal/entities.php @@ -321,5 +321,5 @@ return [ 'revision_delete_confirm' => 'Bist Du sicher, dass Du diese Revision löschen möchtest?', 'revision_restore_confirm' => 'Sind Sie sicher, dass Sie diese Revision wiederherstellen wollen? Der aktuelle Seiteninhalt wird ersetzt.', 'revision_delete_success' => 'Revision gelöscht', - 'revision_cannot_delete_latest' => 'Die letzte Version kann nicht gelöscht werden.' + 'revision_cannot_delete_latest' => 'Die letzte Version kann nicht gelöscht werden.', ]; diff --git a/resources/lang/de_informal/passwords.php b/resources/lang/de_informal/passwords.php index 0dd28c019..b5b38d7fd 100644 --- a/resources/lang/de_informal/passwords.php +++ b/resources/lang/de_informal/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'Passwörter müssen aus mindestens sechs Zeichen bestehen und mit der eingegebenen Wiederholung übereinstimmen.', - 'user' => "Es wurde kein Benutzer mit dieser E-Mail-Adresse gefunden.", + 'user' => 'Es wurde kein Benutzer mit dieser E-Mail-Adresse gefunden.', 'token' => 'Der Token zum Zurücksetzen des Passworts für diese E-Mail-Adresse ist ungültig.', 'sent' => 'Wir haben dir einen Link zum Zurücksetzen des Passwortes per E-Mail geschickt!', 'reset' => 'Dein Passwort wurde zurückgesetzt!', diff --git a/resources/lang/de_informal/settings.php b/resources/lang/de_informal/settings.php index 8fdae9863..d22f73e89 100644 --- a/resources/lang/de_informal/settings.php +++ b/resources/lang/de_informal/settings.php @@ -75,7 +75,7 @@ Hinweis: Benutzer können ihre E-Mail Adresse nach erfolgreicher Registrierung // Maintenance settings 'maint' => 'Wartung', 'maint_image_cleanup' => 'Bilder bereinigen', - 'maint_image_cleanup_desc' => "Überprüft Seiten- und Versionsinhalte auf ungenutzte und mehrfach vorhandene Bilder. Erstelle vor dem Start ein Backup Deiner Datenbank und Bilder.", + 'maint_image_cleanup_desc' => 'Überprüft Seiten- und Versionsinhalte auf ungenutzte und mehrfach vorhandene Bilder. Erstelle vor dem Start ein Backup Deiner Datenbank und Bilder.', 'maint_delete_images_only_in_revisions' => 'Lösche auch Bilder, die nur in alten Seitenüberarbeitungen vorhanden sind', 'maint_image_cleanup_run' => 'Reinigung starten', 'maint_image_cleanup_warning' => ':count eventuell unbenutze Bilder wurden gefunden. Möchtest Du diese Bilder löschen?', @@ -135,7 +135,7 @@ Hinweis: Benutzer können ihre E-Mail Adresse nach erfolgreicher Registrierung 'role_delete' => 'Rolle löschen', 'role_delete_confirm' => 'Du möchtest die Rolle ":roleName" löschen.', 'role_delete_users_assigned' => 'Diese Rolle ist :userCount Benutzern zugeordnet. Du kannst unten eine neue Rolle auswählen, die Du diesen Benutzern zuordnen möchtest.', - 'role_delete_no_migration' => "Den Benutzern keine andere Rolle zuordnen", + 'role_delete_no_migration' => 'Den Benutzern keine andere Rolle zuordnen', 'role_delete_sure' => 'Bist Du sicher, dass Du diese Rolle löschen möchtest?', 'role_delete_success' => 'Rolle erfolgreich gelöscht', 'role_edit' => 'Rolle bearbeiten', @@ -276,6 +276,6 @@ Hinweis: Benutzer können ihre E-Mail Adresse nach erfolgreicher Registrierung 'vi' => 'Tiếng Việt', 'zh_CN' => '简体中文', 'zh_TW' => '繁體中文', - ] + ], //!//////////////////////////////// ]; diff --git a/resources/lang/en/auth.php b/resources/lang/en/auth.php index e4d4c425b..ee0ba2d21 100644 --- a/resources/lang/en/auth.php +++ b/resources/lang/en/auth.php @@ -38,7 +38,6 @@ return [ 'registration_email_domain_invalid' => 'That email domain does not have access to this application', 'register_success' => 'Thanks for signing up! You are now registered and signed in.', - // Password Reset 'reset_password' => 'Reset Password', 'reset_password_send_instructions' => 'Enter your email below and you will be sent an email with a password reset link.', @@ -49,7 +48,6 @@ return [ 'email_reset_text' => 'You are receiving this email because we received a password reset request for your account.', 'email_reset_not_requested' => 'If you did not request a password reset, no further action is required.', - // Email Confirmation 'email_confirm_subject' => 'Confirm your email on :appName', 'email_confirm_greeting' => 'Thanks for joining :appName!', @@ -109,4 +107,4 @@ return [ 'mfa_verify_backup_code_enter_here' => 'Enter backup code here', 'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:', 'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.', -]; \ No newline at end of file +]; diff --git a/resources/lang/en/common.php b/resources/lang/en/common.php index f93fb034b..161891bf4 100644 --- a/resources/lang/en/common.php +++ b/resources/lang/en/common.php @@ -20,7 +20,7 @@ return [ 'role' => 'Role', 'cover_image' => 'Cover image', 'cover_image_description' => 'This image should be approx 440x250px.', - + // Actions 'actions' => 'Actions', 'view' => 'View', diff --git a/resources/lang/en/entities.php b/resources/lang/en/entities.php index 0a4068eea..4871b6225 100644 --- a/resources/lang/en/entities.php +++ b/resources/lang/en/entities.php @@ -321,5 +321,5 @@ return [ 'revision_delete_confirm' => 'Are you sure you want to delete this revision?', 'revision_restore_confirm' => 'Are you sure you want to restore this revision? The current page contents will be replaced.', 'revision_delete_success' => 'Revision deleted', - 'revision_cannot_delete_latest' => 'Cannot delete the latest revision.' + 'revision_cannot_delete_latest' => 'Cannot delete the latest revision.', ]; diff --git a/resources/lang/en/settings.php b/resources/lang/en/settings.php index 8c35d6849..688b0aad8 100755 --- a/resources/lang/en/settings.php +++ b/resources/lang/en/settings.php @@ -72,7 +72,7 @@ return [ // Maintenance settings 'maint' => 'Maintenance', 'maint_image_cleanup' => 'Cleanup Images', - 'maint_image_cleanup_desc' => "Scans page & revision content to check which images and drawings are currently in use and which images are redundant. Ensure you create a full database and image backup before running this.", + 'maint_image_cleanup_desc' => 'Scans page & revision content to check which images and drawings are currently in use and which images are redundant. Ensure you create a full database and image backup before running this.', 'maint_delete_images_only_in_revisions' => 'Also delete images that only exist in old page revisions', 'maint_image_cleanup_run' => 'Run Cleanup', 'maint_image_cleanup_warning' => ':count potentially unused images were found. Are you sure you want to delete these images?', @@ -273,6 +273,6 @@ return [ 'vi' => 'Tiếng Việt', 'zh_CN' => '简体中文', 'zh_TW' => '繁體中文', - ] + ], //!//////////////////////////////// ]; diff --git a/resources/lang/es/auth.php b/resources/lang/es/auth.php index 70f069a12..8a7710afe 100644 --- a/resources/lang/es/auth.php +++ b/resources/lang/es/auth.php @@ -38,7 +38,6 @@ return [ 'registration_email_domain_invalid' => 'Este dominio de correo electrónico no tiene acceso a esta aplicación', 'register_success' => '¡Gracias por registrarse! Ahora se encuentra registrado y logueado.', - // Password Reset 'reset_password' => 'Resetear Contraseña', 'reset_password_send_instructions' => 'Introduzca su correo electrónico a continuación y le será enviado un correo con un link para la restauración', @@ -49,7 +48,6 @@ return [ 'email_reset_text' => 'Está recibiendo este correo electrónico debido a que recibimos una solicitud de reseteo de contraseña de su cuenta.', 'email_reset_not_requested' => 'Si no ha solicitado un reseteo de la contraseña, no es requerida ninguna acción por su parte.', - // Email Confirmation 'email_confirm_subject' => 'Confirme su correo electrónico en :appName', 'email_confirm_greeting' => '¡Gracias por unirse a :appName!', @@ -109,4 +107,4 @@ return [ 'mfa_verify_backup_code_enter_here' => 'Introduce el código de respaldo aquí', 'mfa_verify_totp_desc' => 'Introduzca el código, generado con tu aplicación móvil, a continuación:', 'mfa_setup_login_notification' => 'Método de dos factores configurado. Por favor, inicia sesión de nuevo utilizando el método configurado.', -]; \ No newline at end of file +]; diff --git a/resources/lang/es/common.php b/resources/lang/es/common.php index b8514a876..f36cd5eb0 100644 --- a/resources/lang/es/common.php +++ b/resources/lang/es/common.php @@ -20,7 +20,7 @@ return [ 'role' => 'Rol', 'cover_image' => 'Imagen de portada', 'cover_image_description' => 'Esta imagen debe ser aproximadamente de 440x250px.', - + // Actions 'actions' => 'Acciones', 'view' => 'Ver', diff --git a/resources/lang/es/entities.php b/resources/lang/es/entities.php index 1a7b6df4f..a0bac5851 100644 --- a/resources/lang/es/entities.php +++ b/resources/lang/es/entities.php @@ -321,5 +321,5 @@ return [ 'revision_delete_confirm' => '¿Está seguro de que desea eliminar esta revisión?', 'revision_restore_confirm' => '¿Está seguro de que desea restaurar esta revisión? El contenido actual de la página será reemplazado.', 'revision_delete_success' => 'Revisión eliminada', - 'revision_cannot_delete_latest' => 'No se puede eliminar la última revisión.' + 'revision_cannot_delete_latest' => 'No se puede eliminar la última revisión.', ]; diff --git a/resources/lang/es/passwords.php b/resources/lang/es/passwords.php index 15e42d1ec..4a46134c4 100644 --- a/resources/lang/es/passwords.php +++ b/resources/lang/es/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'La contraseña debe ser como mínimo de seis caracteres y coincidir con la confirmación.', - 'user' => "No podemos encontrar un usuario con esta dirección de correo electrónico.", + 'user' => 'No podemos encontrar un usuario con esta dirección de correo electrónico.', 'token' => 'El token de modificación de contraseña no es válido para esta dirección de correo electrónico.', 'sent' => '¡Hemos enviado a su cuenta de e-mail un enlace para restaurar su contraseña!', 'reset' => '¡Su contraseña ha sido restaurada!', diff --git a/resources/lang/es/settings.php b/resources/lang/es/settings.php index 81416e70e..8c3370c81 100644 --- a/resources/lang/es/settings.php +++ b/resources/lang/es/settings.php @@ -72,7 +72,7 @@ return [ // Maintenance settings 'maint' => 'Mantenimiento', 'maint_image_cleanup' => 'Limpiar imágenes', - 'maint_image_cleanup_desc' => "Analiza las páginas y sus revisiones para comprobar qué imágenes y dibujos están siendo utilizadas y cuales no son necesarias. Asegúrate de crear una copia completa de la base de datos y de las imágenes antes de lanzar esta opción.", + 'maint_image_cleanup_desc' => 'Analiza las páginas y sus revisiones para comprobar qué imágenes y dibujos están siendo utilizadas y cuales no son necesarias. Asegúrate de crear una copia completa de la base de datos y de las imágenes antes de lanzar esta opción.', 'maint_delete_images_only_in_revisions' => 'Elimina también imágenes que sólo existen en antiguas revisiones de páginas', 'maint_image_cleanup_run' => 'Lanzar limpieza', 'maint_image_cleanup_warning' => 'Se han encontrado :count imágenes posiblemente no utilizadas . ¿Estás seguro de querer borrar estas imágenes?', @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Borrar rol', 'role_delete_confirm' => 'Se borrará el rol con nombre \':roleName\'.', 'role_delete_users_assigned' => 'Este rol tiene :userCount usuarios asignados. Si quisiera migrar los usuarios de este rol, seleccione un nuevo rol a continuación.', - 'role_delete_no_migration' => "No migrar usuarios", + 'role_delete_no_migration' => 'No migrar usuarios', 'role_delete_sure' => 'Está seguro que desea borrar este rol?', 'role_delete_success' => 'Rol borrado satisfactoriamente', 'role_edit' => 'Editar rol', @@ -273,6 +273,6 @@ return [ 'vi' => 'Tiếng Việt', 'zh_CN' => '简体中文', 'zh_TW' => '繁體中文', - ] + ], //!//////////////////////////////// ]; diff --git a/resources/lang/es_AR/auth.php b/resources/lang/es_AR/auth.php index cb18a9405..b419720a7 100644 --- a/resources/lang/es_AR/auth.php +++ b/resources/lang/es_AR/auth.php @@ -38,7 +38,6 @@ return [ 'registration_email_domain_invalid' => 'Este dominio de correo electrónico no tiene acceso a esta aplicación', 'register_success' => '¡Gracias por registrarse! Ahora se encuentra registrado y ha accedido a la aplicación.', - // Password Reset 'reset_password' => 'Restablecer la contraseña', 'reset_password_send_instructions' => 'Introduzca su correo electrónico a continuación y se le enviará un correo electrónico con un enlace para la restauración', @@ -49,7 +48,6 @@ return [ 'email_reset_text' => 'Ud. esta recibiendo este correo electrónico debido a que recibimos una solicitud de restauración de la contraseña de su cuenta.', 'email_reset_not_requested' => 'Si ud. no solicitó un cambio de contraseña, no se requiere ninguna acción.', - // Email Confirmation 'email_confirm_subject' => 'Confirme su correo electrónico en :appName', 'email_confirm_greeting' => '¡Gracias por unirse a :appName!', @@ -109,4 +107,4 @@ return [ 'mfa_verify_backup_code_enter_here' => 'Introduzca el código de respaldo aquí', 'mfa_verify_totp_desc' => 'A continuación, introduzca el código generado con su aplicación móvil:', 'mfa_setup_login_notification' => 'Método de dos factores configurado. Por favor, inicie sesión nuevamente utilizando el método configurado.', -]; \ No newline at end of file +]; diff --git a/resources/lang/es_AR/common.php b/resources/lang/es_AR/common.php index 05c76cb11..c4e8c62f3 100644 --- a/resources/lang/es_AR/common.php +++ b/resources/lang/es_AR/common.php @@ -20,7 +20,7 @@ return [ 'role' => 'Rol', 'cover_image' => 'Imagen de cubierta', 'cover_image_description' => 'Esta imagen debe ser de 440x250px aproximadamente.', - + // Actions 'actions' => 'Acciones', 'view' => 'Ver', diff --git a/resources/lang/es_AR/entities.php b/resources/lang/es_AR/entities.php index bf08bdb51..a931e784c 100644 --- a/resources/lang/es_AR/entities.php +++ b/resources/lang/es_AR/entities.php @@ -321,5 +321,5 @@ return [ 'revision_delete_confirm' => '¿Está seguro de que quiere eliminar esta revisión?', 'revision_restore_confirm' => '¿Está seguro de que quiere restaurar esta revisión? Se reemplazará el contenido de la página actual.', 'revision_delete_success' => 'Revisión eliminada', - 'revision_cannot_delete_latest' => 'No se puede eliminar la última revisión.' + 'revision_cannot_delete_latest' => 'No se puede eliminar la última revisión.', ]; diff --git a/resources/lang/es_AR/passwords.php b/resources/lang/es_AR/passwords.php index f9e24939b..92e92a2b7 100644 --- a/resources/lang/es_AR/passwords.php +++ b/resources/lang/es_AR/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'La contraseña debe ser como mínimo de seis caracteres y coincidir con la confirmación.', - 'user' => "No podemos encontrar un usuario con esta dirección de correo electrónico.", + 'user' => 'No podemos encontrar un usuario con esta dirección de correo electrónico.', 'token' => 'El token para restablecer la contraseña no es válido para esta dirección de correo electrónico.', 'sent' => '¡Hemos enviado a su cuenta de correo electrónico un enlace para restaurar su contraseña!', 'reset' => '¡Su contraseña fue restaurada!', diff --git a/resources/lang/es_AR/settings.php b/resources/lang/es_AR/settings.php index 46f72fa6b..922944674 100644 --- a/resources/lang/es_AR/settings.php +++ b/resources/lang/es_AR/settings.php @@ -72,7 +72,7 @@ return [ // Maintenance settings 'maint' => 'Mantenimiento', 'maint_image_cleanup' => 'Limpiar imágenes', - 'maint_image_cleanup_desc' => "Analizar contenido de páginas y revisiones para detectar cuáles imágenes y dibujos están en uso y cuáles son redundantes. Asegúrese de crear un respaldo completo de imágenes y base de datos antes de ejecutar esta tarea.", + 'maint_image_cleanup_desc' => 'Analizar contenido de páginas y revisiones para detectar cuáles imágenes y dibujos están en uso y cuáles son redundantes. Asegúrese de crear un respaldo completo de imágenes y base de datos antes de ejecutar esta tarea.', 'maint_delete_images_only_in_revisions' => 'También elimina imágenes que sólo existen en antiguas revisiones de páginas', 'maint_image_cleanup_run' => 'Ejecutar limpieza', 'maint_image_cleanup_warning' => 'Se encontraron :count imágenes pontencialmente sin uso. Está seguro de que quiere eliminarlas?', @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Borrar rol', 'role_delete_confirm' => 'Se borrará el rol con nombre \':roleName\'.', 'role_delete_users_assigned' => 'Este rol tiene :userCount usuarios asignados. Si ud. quisiera migrar los usuarios de este rol, seleccione un nuevo rol a continuación.', - 'role_delete_no_migration' => "No migrar usuarios", + 'role_delete_no_migration' => 'No migrar usuarios', 'role_delete_sure' => '¿Está seguro que desea borrar este rol?', 'role_delete_success' => 'Rol borrado satisfactoriamente', 'role_edit' => 'Editar rol', @@ -274,6 +274,6 @@ return [ 'vi' => 'Tiếng Việt', 'zh_CN' => '简体中文', 'zh_TW' => '繁體中文', - ] + ], //!//////////////////////////////// ]; diff --git a/resources/lang/et/auth.php b/resources/lang/et/auth.php index 6022d933b..bfce41079 100644 --- a/resources/lang/et/auth.php +++ b/resources/lang/et/auth.php @@ -38,7 +38,6 @@ return [ 'registration_email_domain_invalid' => 'Sellel e-posti domeenil ei ole rakendusele ligipääsu', 'register_success' => 'Aitäh, et registreerusid! Oled nüüd sisse logitud.', - // Password Reset 'reset_password' => 'Lähtesta parool', 'reset_password_send_instructions' => 'Siseta oma e-posti aadress ning sulle saadetakse link parooli lähtestamiseks.', @@ -49,7 +48,6 @@ return [ 'email_reset_text' => 'Said selle e-kirja, sest meile laekus soov sinu konto parooli lähtestamiseks.', 'email_reset_not_requested' => 'Kui sa ei soovinud parooli lähtestada, ei pea sa rohkem midagi tegema.', - // Email Confirmation 'email_confirm_subject' => 'Kinnita oma :appName konto e-posti aadress', 'email_confirm_greeting' => 'Aitäh, et liitusid rakendusega :appName!', @@ -109,4 +107,4 @@ return [ 'mfa_verify_backup_code_enter_here' => 'Sisesta varukood siia', 'mfa_verify_totp_desc' => 'Sisesta oma mobiilirakenduse poolt genereeritud kood allpool:', 'mfa_setup_login_notification' => 'Mitmeastmeline autentimine seadistatud. Logi nüüd uuesti sisse, kasutades seadistatud meetodit.', -]; \ No newline at end of file +]; diff --git a/resources/lang/et/common.php b/resources/lang/et/common.php index d3349f5fb..acef3c1da 100644 --- a/resources/lang/et/common.php +++ b/resources/lang/et/common.php @@ -20,7 +20,7 @@ return [ 'role' => 'Roll', 'cover_image' => 'Kaanepilt', 'cover_image_description' => 'See pilt peaks olema umbes 440x250 pikslit.', - + // Actions 'actions' => 'Tegevused', 'view' => 'Vaata', diff --git a/resources/lang/et/entities.php b/resources/lang/et/entities.php index 0fabc32df..e685e2bc6 100644 --- a/resources/lang/et/entities.php +++ b/resources/lang/et/entities.php @@ -321,5 +321,5 @@ return [ 'revision_delete_confirm' => 'Kas oled kindel, et soovid selle redaktsiooni kustutada?', 'revision_restore_confirm' => 'Kas oled kindel, et soovid selle redaktsiooni taastada? Lehe praegune sisu asendatakse.', 'revision_delete_success' => 'Redaktsioon kustutatud', - 'revision_cannot_delete_latest' => 'Kõige viimast redaktsiooni ei saa kustutada.' + 'revision_cannot_delete_latest' => 'Kõige viimast redaktsiooni ei saa kustutada.', ]; diff --git a/resources/lang/et/passwords.php b/resources/lang/et/passwords.php index 8559d60b2..6457887d3 100644 --- a/resources/lang/et/passwords.php +++ b/resources/lang/et/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'Paroolides peab olema vähemalt kaheksa tähemärki ja nad peavad omavahel ühtima.', - 'user' => "Sellise e-posti aadressiga kasutajat ei leitud.", + 'user' => 'Sellise e-posti aadressiga kasutajat ei leitud.', 'token' => 'Parooli lähtestamise link ei kehti selle e-posti aadressiga.', 'sent' => 'Parooli lähtestamise link saadeti e-postiga!', 'reset' => 'Parool on lähtestatud!', diff --git a/resources/lang/et/settings.php b/resources/lang/et/settings.php index bb2dba47c..c6ca6425b 100644 --- a/resources/lang/et/settings.php +++ b/resources/lang/et/settings.php @@ -72,7 +72,7 @@ return [ // Maintenance settings 'maint' => 'Hooldus', 'maint_image_cleanup' => 'Pildifailide koristus', - 'maint_image_cleanup_desc' => "Kontrollib lehtede ja redaktsioonide sisu, et leida pilte ja jooniseid, mis enam kasutusel ei ole. Enne selle käivitamist tee andmebaasist ja pildifailidest täielik varukoopia.", + 'maint_image_cleanup_desc' => 'Kontrollib lehtede ja redaktsioonide sisu, et leida pilte ja jooniseid, mis enam kasutusel ei ole. Enne selle käivitamist tee andmebaasist ja pildifailidest täielik varukoopia.', 'maint_delete_images_only_in_revisions' => 'Kustuta ka pildifailid, mis on kasutusel ainult vanades redaktsioonides', 'maint_image_cleanup_run' => 'Käivita koristus', 'maint_image_cleanup_warning' => 'Leiti :count potentsiaalselt kasutamata pildifaili. Kas oled kindel, et soovid need kustutada?', @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Kustuta roll', 'role_delete_confirm' => 'See kustutab rolli nimega \':roleName\'.', 'role_delete_users_assigned' => 'Selle rolliga on seotud :userCount kasutajat. Kui soovid neile selle asemel uue rolli määrata, siis vali see allpool.', - 'role_delete_no_migration' => "Ära määra uut rolli", + 'role_delete_no_migration' => 'Ära määra uut rolli', 'role_delete_sure' => 'Kas oled kindel, et soovid selle rolli kustutada?', 'role_delete_success' => 'Roll on kustutatud', 'role_edit' => 'Muuda rolli', @@ -273,6 +273,6 @@ return [ 'vi' => 'Tiếng Việt', 'zh_CN' => '简体中文', 'zh_TW' => '繁體中文', - ] + ], //!//////////////////////////////// ]; diff --git a/resources/lang/fa/auth.php b/resources/lang/fa/auth.php index 4f950b77f..1b6340747 100644 --- a/resources/lang/fa/auth.php +++ b/resources/lang/fa/auth.php @@ -38,7 +38,6 @@ return [ 'registration_email_domain_invalid' => 'دامنه پست الکترونیک به این برنامه دسترسی ندارد', 'register_success' => 'از ثبت نام شما سپاسگزاریم! شما اکنون ثبت نام کرده و وارد سیستم شده اید.', - // Password Reset 'reset_password' => 'بازنشانی کلمه عبور', 'reset_password_send_instructions' => 'پست الکترونیک خود را در کادر زیر وارد نموده تا یک پیام حاوی لینک بازنشانی کلمه عبور دریافت نمایید.', @@ -49,7 +48,6 @@ return [ 'email_reset_text' => 'شما این پیام را به علت درخواست بازنشانی کلمه عبور دریافت می نمایید.', 'email_reset_not_requested' => 'در صورتی که درخواست بازنشانی کلمه عبور از سمت شما نمی باشد، نیاز به انجام هیچ فعالیتی ندارید.', - // Email Confirmation 'email_confirm_subject' => 'پست الکترونیک خود را در:appName تایید نمایید', 'email_confirm_greeting' => 'برای پیوستن به :appName متشکریم!', @@ -109,4 +107,4 @@ return [ 'mfa_verify_backup_code_enter_here' => 'Enter backup code here', 'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:', 'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.', -]; \ No newline at end of file +]; diff --git a/resources/lang/fa/common.php b/resources/lang/fa/common.php index 6d3768de4..1081e48ff 100644 --- a/resources/lang/fa/common.php +++ b/resources/lang/fa/common.php @@ -20,7 +20,7 @@ return [ 'role' => 'نقش', 'cover_image' => 'تصویر روی جلد', 'cover_image_description' => 'سایز تصویر باید 440x250 باشد.', - + // Actions 'actions' => 'عملیات', 'view' => 'نمایش', diff --git a/resources/lang/fa/entities.php b/resources/lang/fa/entities.php index 47335af8e..a2b5e945d 100644 --- a/resources/lang/fa/entities.php +++ b/resources/lang/fa/entities.php @@ -321,5 +321,5 @@ return [ 'revision_delete_confirm' => 'Are you sure you want to delete this revision?', 'revision_restore_confirm' => 'Are you sure you want to restore this revision? The current page contents will be replaced.', 'revision_delete_success' => 'Revision deleted', - 'revision_cannot_delete_latest' => 'Cannot delete the latest revision.' + 'revision_cannot_delete_latest' => 'Cannot delete the latest revision.', ]; diff --git a/resources/lang/fa/passwords.php b/resources/lang/fa/passwords.php index 06b8f8b50..6d342dbe8 100644 --- a/resources/lang/fa/passwords.php +++ b/resources/lang/fa/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'گذرواژه باید حداقل هشت حرف و با تایید مطابقت داشته باشد.', - 'user' => "ما کاربری با این نشانی ایمیل نداریم.", + 'user' => 'ما کاربری با این نشانی ایمیل نداریم.', 'token' => 'مشخصه‌ی بازگردانی رمز عبور معتبر نیست.', 'sent' => 'لینک بازگردانی رمز عبور به ایمیل شما ارسال شد!', 'reset' => 'رمز عبور شما بازگردانی شد!', diff --git a/resources/lang/fa/settings.php b/resources/lang/fa/settings.php index 46df0d07d..335a1b436 100644 --- a/resources/lang/fa/settings.php +++ b/resources/lang/fa/settings.php @@ -72,7 +72,7 @@ return [ // Maintenance settings 'maint' => 'Maintenance', 'maint_image_cleanup' => 'Cleanup Images', - 'maint_image_cleanup_desc' => "Scans page & revision content to check which images and drawings are currently in use and which images are redundant. Ensure you create a full database and image backup before running this.", + 'maint_image_cleanup_desc' => 'Scans page & revision content to check which images and drawings are currently in use and which images are redundant. Ensure you create a full database and image backup before running this.', 'maint_delete_images_only_in_revisions' => 'Also delete images that only exist in old page revisions', 'maint_image_cleanup_run' => 'Run Cleanup', 'maint_image_cleanup_warning' => ':count potentially unused images were found. Are you sure you want to delete these images?', @@ -273,6 +273,6 @@ return [ 'vi' => 'Tiếng Việt', 'zh_CN' => '简体中文', 'zh_TW' => '繁體中文', - ] + ], //!//////////////////////////////// ]; diff --git a/resources/lang/fr/auth.php b/resources/lang/fr/auth.php index c608f02fb..de1793229 100644 --- a/resources/lang/fr/auth.php +++ b/resources/lang/fr/auth.php @@ -38,7 +38,6 @@ return [ 'registration_email_domain_invalid' => 'Cette adresse e-mail ne peut pas accéder à l\'application', 'register_success' => 'Merci pour votre inscription. Vous êtes maintenant inscrit(e) et connecté(e)', - // Password Reset 'reset_password' => 'Réinitialiser le mot de passe', 'reset_password_send_instructions' => 'Entrez votre adresse e-mail ci-dessous et un e-mail avec un lien de réinitialisation de mot de passe vous sera envoyé.', @@ -49,7 +48,6 @@ return [ 'email_reset_text' => 'Vous recevez cet e-mail parce que nous avons reçu une demande de réinitialisation pour votre compte.', 'email_reset_not_requested' => 'Si vous n\'avez pas effectué cette demande, vous pouvez ignorer cet e-mail.', - // Email Confirmation 'email_confirm_subject' => 'Confirmez votre adresse e-mail pour :appName', 'email_confirm_greeting' => 'Merci d\'avoir rejoint :appName !', @@ -109,4 +107,4 @@ return [ 'mfa_verify_backup_code_enter_here' => 'Saisissez un code de secours ici', 'mfa_verify_totp_desc' => 'Entrez ci-dessous le code généré à l\'aide de votre application mobile :', 'mfa_setup_login_notification' => 'Méthode multi-facteurs configurée. Veuillez maintenant vous reconnecter en utilisant la méthode configurée.', -]; \ No newline at end of file +]; diff --git a/resources/lang/fr/common.php b/resources/lang/fr/common.php index e6e8bf1a2..494024785 100644 --- a/resources/lang/fr/common.php +++ b/resources/lang/fr/common.php @@ -20,7 +20,7 @@ return [ 'role' => 'Rôle', 'cover_image' => 'Image de couverture', 'cover_image_description' => 'Cette image doit faire environ 440x250 px.', - + // Actions 'actions' => 'Actions', 'view' => 'Voir', diff --git a/resources/lang/fr/entities.php b/resources/lang/fr/entities.php index 360780a25..3742f584e 100644 --- a/resources/lang/fr/entities.php +++ b/resources/lang/fr/entities.php @@ -255,7 +255,7 @@ return [ 'tags' => 'Mots-clés', 'tag_name' => 'Nom du tag', 'tag_value' => 'Valeur du mot-clé (optionnel)', - 'tags_explain' => "Ajouter des mots-clés pour catégoriser votre contenu.", + 'tags_explain' => 'Ajouter des mots-clés pour catégoriser votre contenu.', 'tags_add' => 'Ajouter un autre mot-clé', 'tags_remove' => 'Supprimer le mot-clé', 'attachments' => 'Fichiers joints', @@ -321,5 +321,5 @@ return [ 'revision_delete_confirm' => 'Êtes-vous sûr de vouloir supprimer cette révision ?', 'revision_restore_confirm' => 'Êtes-vous sûr de vouloir restaurer cette révision ? Le contenu courant de la page va être remplacé.', 'revision_delete_success' => 'Révision supprimée', - 'revision_cannot_delete_latest' => 'Impossible de supprimer la dernière révision.' + 'revision_cannot_delete_latest' => 'Impossible de supprimer la dernière révision.', ]; diff --git a/resources/lang/fr/settings.php b/resources/lang/fr/settings.php index 18958c825..56c9adc7b 100644 --- a/resources/lang/fr/settings.php +++ b/resources/lang/fr/settings.php @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Supprimer le rôle', 'role_delete_confirm' => 'Ceci va supprimer le rôle \':roleName\'.', 'role_delete_users_assigned' => 'Ce rôle a :userCount utilisateurs assignés. Vous pouvez choisir un rôle de remplacement pour ces utilisateurs.', - 'role_delete_no_migration' => "Ne pas assigner de nouveau rôle", + 'role_delete_no_migration' => 'Ne pas assigner de nouveau rôle', 'role_delete_sure' => 'Êtes-vous sûr de vouloir supprimer ce rôle ?', 'role_delete_success' => 'Le rôle a été supprimé avec succès', 'role_edit' => 'Modifier le rôle', @@ -273,6 +273,6 @@ return [ 'vi' => 'Tiếng Việt', 'zh_CN' => '简体中文', 'zh_TW' => '繁體中文', - ] + ], //!//////////////////////////////// ]; diff --git a/resources/lang/he/auth.php b/resources/lang/he/auth.php index a078cfcf8..ab8b1e963 100644 --- a/resources/lang/he/auth.php +++ b/resources/lang/he/auth.php @@ -38,7 +38,6 @@ return [ 'registration_email_domain_invalid' => 'לא ניתן להרשם באמצעות המייל שסופק', 'register_success' => 'תודה על הרשמתך! ניתן כעת להתחבר', - // Password Reset 'reset_password' => 'איפוס סיסמא', 'reset_password_send_instructions' => 'יש להזין את כתובת המייל למטה ואנו נשלח אלייך הוראות לאיפוס הסיסמא', @@ -49,7 +48,6 @@ return [ 'email_reset_text' => 'קישור זה נשלח עקב בקשה לאיפוס סיסמא בחשבון שלך', 'email_reset_not_requested' => 'אם לא ביקשת לאפס את סיסמתך, אפשר להתעלם ממייל זה', - // Email Confirmation 'email_confirm_subject' => 'אמת אי-מייל ב :appName', 'email_confirm_greeting' => 'תודה שהצטרפת אל :appName!', @@ -109,4 +107,4 @@ return [ 'mfa_verify_backup_code_enter_here' => 'Enter backup code here', 'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:', 'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.', -]; \ No newline at end of file +]; diff --git a/resources/lang/he/common.php b/resources/lang/he/common.php index 475987f34..1a2e5b918 100644 --- a/resources/lang/he/common.php +++ b/resources/lang/he/common.php @@ -20,7 +20,7 @@ return [ 'role' => 'תפקיד', 'cover_image' => 'תמונת נושא', 'cover_image_description' => 'התמונה צריכה להיות בסביבות 440x250px', - + // Actions 'actions' => 'פעולות', 'view' => 'הצג', diff --git a/resources/lang/he/entities.php b/resources/lang/he/entities.php index ac4e25c8b..5ad67afb8 100644 --- a/resources/lang/he/entities.php +++ b/resources/lang/he/entities.php @@ -94,7 +94,7 @@ return [ 'shelves_edit' => 'ערוך מדף', 'shelves_delete' => 'מחק מדף', 'shelves_delete_named' => 'מחיקת דף :name', - 'shelves_delete_explain' => "פעולה זו תמחק את המדף :name - הספרים שמופיעים בו ימחקו גם כן!", + 'shelves_delete_explain' => 'פעולה זו תמחק את המדף :name - הספרים שמופיעים בו ימחקו גם כן!', 'shelves_delete_confirmation' => 'האם ברצונך למחוק את המדף?', 'shelves_permissions' => 'הרשאות מדף', 'shelves_permissions_updated' => 'הרשאות מדף עודכנו', @@ -321,5 +321,5 @@ return [ 'revision_delete_confirm' => 'האם ברצונך למחוק נוסח זה?', 'revision_restore_confirm' => 'האם ברצונך לשחזר נוסח זה? תוכן הדף הנוכחי יעודכן לנוסח זה.', 'revision_delete_success' => 'נוסח נמחק', - 'revision_cannot_delete_latest' => 'לא ניתן למחוק את הנוסח האחרון' + 'revision_cannot_delete_latest' => 'לא ניתן למחוק את הנוסח האחרון', ]; diff --git a/resources/lang/he/passwords.php b/resources/lang/he/passwords.php index a94d7c30b..0b700f21e 100644 --- a/resources/lang/he/passwords.php +++ b/resources/lang/he/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'הסיסמה חייבת להיות בעלת 8 תווים לפחות ולהתאים לאימות.', - 'user' => "לא נמצא משתמש עם כתובת דוא\"ל זו.", + 'user' => 'לא נמצא משתמש עם כתובת דוא"ל זו.', 'token' => 'אסימון איפוס הסיסמה לא תקף עבור כתובת דוא"ל זו.', 'sent' => 'שלחנו לך דוא"ל עם קישור לאיפוס הסיסמה!', 'reset' => 'איפוס הסיסמה הושלם בהצלחה!', diff --git a/resources/lang/he/settings.php b/resources/lang/he/settings.php index 499ec3cd3..e8f25fe6c 100755 --- a/resources/lang/he/settings.php +++ b/resources/lang/he/settings.php @@ -72,7 +72,7 @@ return [ // Maintenance settings 'maint' => 'תחזוקה', 'maint_image_cleanup' => 'ניקוי תמונות', - 'maint_image_cleanup_desc' => "סורק את הדפים והגרסאות על מנת למצוא אילו תמונות לא בשימוש. יש לוודא גיבוי מלא של מסד הנתונים והתמונות לפני הרצה", + 'maint_image_cleanup_desc' => 'סורק את הדפים והגרסאות על מנת למצוא אילו תמונות לא בשימוש. יש לוודא גיבוי מלא של מסד הנתונים והתמונות לפני הרצה', 'maint_delete_images_only_in_revisions' => 'מחק בנוסף תמונות שקיימות בגרסאות ישנות של הדף בלבד', 'maint_image_cleanup_run' => 'הפעל ניקוי תמונות', 'maint_image_cleanup_warning' => 'נמצאו כ :count תמונות אשר לא בשימוש האם ברצונך להמשיך?', @@ -132,7 +132,7 @@ return [ 'role_delete' => 'מחק תפקיד', 'role_delete_confirm' => 'פעולה זו תמחק את התפקיד: :roleName', 'role_delete_users_assigned' => 'לתפקיד :userCount יש משתמשים אשר משויכים אליו. אם ברצונך להעבירם לתפקיד אחר אנא בחר תפקיד מלמטה', - 'role_delete_no_migration' => "אל תעביר משתמשים לתפקיד", + 'role_delete_no_migration' => 'אל תעביר משתמשים לתפקיד', 'role_delete_sure' => 'האם אתה בטוח שברצונך למחוק את התפקיד?', 'role_delete_success' => 'התפקיד נמחק בהצלחה', 'role_edit' => 'ערוך תפקיד', @@ -273,6 +273,6 @@ return [ 'vi' => 'Tiếng Việt', 'zh_CN' => '简体中文', 'zh_TW' => '繁體中文', - ] + ], //!//////////////////////////////// ]; diff --git a/resources/lang/hr/auth.php b/resources/lang/hr/auth.php index 23014439a..b5f3bf61b 100644 --- a/resources/lang/hr/auth.php +++ b/resources/lang/hr/auth.php @@ -38,7 +38,6 @@ return [ 'registration_email_domain_invalid' => 'Ova e-mail adresa se ne može koristiti u ovoj aplikaciji', 'register_success' => 'Hvala na prijavi! Sada ste registrirani i prijavljeni.', - // Password Reset 'reset_password' => 'Promijenite lozinku', 'reset_password_send_instructions' => 'Upišite svoju e-mail adresu kako biste primili poveznicu za promjenu lozinke.', @@ -49,7 +48,6 @@ return [ 'email_reset_text' => 'Primili ste ovu poruku jer je zatražena promjena lozinke za vaš račun.', 'email_reset_not_requested' => 'Ako niste tražili promjenu lozinke slobodno zanemarite ovu poruku.', - // Email Confirmation 'email_confirm_subject' => 'Potvrdite svoju e-mail adresu na :appName', 'email_confirm_greeting' => 'Hvala na prijavi :appName!', @@ -109,4 +107,4 @@ return [ 'mfa_verify_backup_code_enter_here' => 'Enter backup code here', 'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:', 'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.', -]; \ No newline at end of file +]; diff --git a/resources/lang/hr/common.php b/resources/lang/hr/common.php index bc51eed22..78018f8a9 100644 --- a/resources/lang/hr/common.php +++ b/resources/lang/hr/common.php @@ -20,7 +20,7 @@ return [ 'role' => 'Uloga', 'cover_image' => 'Naslovna slika', 'cover_image_description' => 'Slika treba biti približno 440x250px.', - + // Actions 'actions' => 'Aktivnost', 'view' => 'Pogled', diff --git a/resources/lang/hr/entities.php b/resources/lang/hr/entities.php index 5f3f8bedb..9e8a835f4 100644 --- a/resources/lang/hr/entities.php +++ b/resources/lang/hr/entities.php @@ -321,5 +321,5 @@ return [ 'revision_delete_confirm' => 'Jeste li sigurni da želite izbrisati ovaj ispravak?', 'revision_restore_confirm' => 'Jeste li sigurni da želite vratiti ovaj ispravak? Trenutni sadržaj će biti zamijenjen.', 'revision_delete_success' => 'Izbrisani ispravak', - 'revision_cannot_delete_latest' => 'Posljednji ispravak se ne može izbrisati.' + 'revision_cannot_delete_latest' => 'Posljednji ispravak se ne može izbrisati.', ]; diff --git a/resources/lang/hr/settings.php b/resources/lang/hr/settings.php index 25b5e3186..38a2878f6 100644 --- a/resources/lang/hr/settings.php +++ b/resources/lang/hr/settings.php @@ -72,7 +72,7 @@ return [ // Maintenance settings 'maint' => 'Održavanje', 'maint_image_cleanup' => 'Čišćenje slika', - 'maint_image_cleanup_desc' => "Scans page & revision content to check which images and drawings are currently in use and which images are redundant. Ensure you create a full database and image backup before running this.", + 'maint_image_cleanup_desc' => 'Scans page & revision content to check which images and drawings are currently in use and which images are redundant. Ensure you create a full database and image backup before running this.', 'maint_delete_images_only_in_revisions' => 'Izbriši slike koje postoje u prijašnjim revizijama', 'maint_image_cleanup_run' => 'Pokreni čišćenje', 'maint_image_cleanup_warning' => ':count moguće neiskorištene slike. Jeste li sigurni da želite izbrisati ove slike?', @@ -273,6 +273,6 @@ return [ 'vi' => 'Tiếng Việt', 'zh_CN' => '简体中文', 'zh_TW' => '繁體中文', - ] + ], //!//////////////////////////////// ]; diff --git a/resources/lang/hu/auth.php b/resources/lang/hu/auth.php index 7aaedf92d..fb207c904 100644 --- a/resources/lang/hu/auth.php +++ b/resources/lang/hu/auth.php @@ -38,7 +38,6 @@ return [ 'registration_email_domain_invalid' => 'Ebből az email tartományról nem lehet hozzáférni ehhez az alkalmazáshoz', 'register_success' => 'Köszönjük a regisztrációt! A regisztráció és a bejelentkezés megtörtént.', - // Password Reset 'reset_password' => 'Jelszó visszaállítása', 'reset_password_send_instructions' => 'Meg kell adni az email címet amire egy jelszó visszaállító hivatkozás lesz elküldve.', @@ -49,7 +48,6 @@ return [ 'email_reset_text' => 'Ezt az emailt azért küldtük mert egy jelszó visszaállításra vonatkozó kérést kaptunk ebből a fiókból.', 'email_reset_not_requested' => 'Ha nem történt jelszó visszaállításra vonatkozó kérés, akkor nincs szükség további intézkedésre.', - // Email Confirmation 'email_confirm_subject' => ':appName alkalmazásban beállított email címet meg kell erősíteni', 'email_confirm_greeting' => ':appName köszöni a csatlakozást!', @@ -109,4 +107,4 @@ return [ 'mfa_verify_backup_code_enter_here' => 'Enter backup code here', 'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:', 'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.', -]; \ No newline at end of file +]; diff --git a/resources/lang/hu/common.php b/resources/lang/hu/common.php index 2e850aa2e..1c0116a1a 100644 --- a/resources/lang/hu/common.php +++ b/resources/lang/hu/common.php @@ -20,7 +20,7 @@ return [ 'role' => 'Szerepkör', 'cover_image' => 'Borítókép', 'cover_image_description' => 'A kép méretének kb. 440x250px-nek kell lennie.', - + // Actions 'actions' => 'Műveletek', 'view' => 'Megtekintés', diff --git a/resources/lang/hu/entities.php b/resources/lang/hu/entities.php index f78392ec2..905c9b0b7 100644 --- a/resources/lang/hu/entities.php +++ b/resources/lang/hu/entities.php @@ -321,5 +321,5 @@ return [ 'revision_delete_confirm' => 'Biztosan törölhető ez a változat?', 'revision_restore_confirm' => 'Biztosan visszaállítható ez a változat? A oldal jelenlegi tartalma le lesz cserélve.', 'revision_delete_success' => 'Változat törölve', - 'revision_cannot_delete_latest' => 'A legutolsó változat nem törölhető.' + 'revision_cannot_delete_latest' => 'A legutolsó változat nem törölhető.', ]; diff --git a/resources/lang/hu/passwords.php b/resources/lang/hu/passwords.php index e06c6f6e3..f33be37d6 100644 --- a/resources/lang/hu/passwords.php +++ b/resources/lang/hu/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'A jelszónak legalább hat karakterből kell állnia és egyeznie kell a megerősítéssel.', - 'user' => "Nem található felhasználó ezzel az e-mail címmel.", + 'user' => 'Nem található felhasználó ezzel az e-mail címmel.', 'token' => 'The password reset token is invalid for this email address.', 'sent' => 'E-mailben elküldtük a jelszó visszaállító hivatkozást!', 'reset' => 'A jelszó visszaállítva!', diff --git a/resources/lang/hu/settings.php b/resources/lang/hu/settings.php index ea36c9641..57b640a99 100644 --- a/resources/lang/hu/settings.php +++ b/resources/lang/hu/settings.php @@ -72,7 +72,7 @@ return [ // Maintenance settings 'maint' => 'Karbantartás', 'maint_image_cleanup' => 'Képek tisztítása', - 'maint_image_cleanup_desc' => "Végigolvassa az oldalakat és a tartalmak változatait, hogy leellenőrizze jelenleg mely képek és rajzok vannak használatban, és mely képek szerepelnek többször. A futtatása előtt feltétlen készíteni kell egy teljes adatbázis és lemezkép mentést.", + 'maint_image_cleanup_desc' => 'Végigolvassa az oldalakat és a tartalmak változatait, hogy leellenőrizze jelenleg mely képek és rajzok vannak használatban, és mely képek szerepelnek többször. A futtatása előtt feltétlen készíteni kell egy teljes adatbázis és lemezkép mentést.', 'maint_delete_images_only_in_revisions' => 'Also delete images that only exist in old page revisions', 'maint_image_cleanup_run' => 'Tisztítás futtatása', 'maint_image_cleanup_warning' => ':count potenciálisan nem használt képet találtam. Biztosan törölhetőek ezek a képek?', @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Szerepkör törlése', 'role_delete_confirm' => 'Ez törölni fogja \':roleName\' szerepkört.', 'role_delete_users_assigned' => 'Ehhez a szerepkörhöz :userCount felhasználó van hozzárendelve. Ha a felhasználókat át kell helyezni ebből a szerepkörből, akkor ki kell választani egy új szerepkört.', - 'role_delete_no_migration' => "Nincs felhasználó áthelyezés", + 'role_delete_no_migration' => 'Nincs felhasználó áthelyezés', 'role_delete_sure' => 'Biztosan törölhető ez a szerepkör?', 'role_delete_success' => 'Szerepkör sikeresen törölve', 'role_edit' => 'Szerepkör szerkesztése', @@ -273,6 +273,6 @@ return [ 'vi' => 'Tiếng Việt', 'zh_CN' => '简体中文', 'zh_TW' => '繁體中文', - ] + ], //!//////////////////////////////// ]; diff --git a/resources/lang/id/auth.php b/resources/lang/id/auth.php index 84fc3a16e..f81ebde7a 100644 --- a/resources/lang/id/auth.php +++ b/resources/lang/id/auth.php @@ -38,7 +38,6 @@ return [ 'registration_email_domain_invalid' => 'Domain email tersebut tidak memiliki akses ke aplikasi ini', 'register_success' => 'Terima kasih telah mendaftar! Anda sekarang terdaftar dan masuk.', - // Password Reset 'reset_password' => 'Atur ulang kata sandi', 'reset_password_send_instructions' => 'Masukkan email Anda di bawah ini dan Anda akan dikirimi email dengan tautan pengaturan ulang kata sandi.', @@ -49,7 +48,6 @@ return [ 'email_reset_text' => 'Anda menerima email ini karena kami menerima permintaan pengaturan ulang kata sandi untuk akun Anda.', 'email_reset_not_requested' => 'Jika Anda tidak meminta pengaturan ulang kata sandi, tidak ada tindakan lebih lanjut yang diperlukan.', - // Email Confirmation 'email_confirm_subject' => 'Konfirmasikan email Anda di :appName', 'email_confirm_greeting' => 'Terima kasih telah bergabung :appName!', @@ -109,4 +107,4 @@ return [ 'mfa_verify_backup_code_enter_here' => 'Enter backup code here', 'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:', 'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.', -]; \ No newline at end of file +]; diff --git a/resources/lang/id/common.php b/resources/lang/id/common.php index c9aac2ed2..e95233a01 100644 --- a/resources/lang/id/common.php +++ b/resources/lang/id/common.php @@ -20,7 +20,7 @@ return [ 'role' => 'Peran', 'cover_image' => 'Sampul gambar', 'cover_image_description' => 'Gambar ini harus berukuran kira-kira 440x250 piksel.', - + // Actions 'actions' => 'Tindakan', 'view' => 'Lihat', diff --git a/resources/lang/id/entities.php b/resources/lang/id/entities.php index 0b58563fa..cfb65f144 100644 --- a/resources/lang/id/entities.php +++ b/resources/lang/id/entities.php @@ -321,5 +321,5 @@ return [ 'revision_delete_confirm' => 'Anda yakin ingin menghapus revisi ini?', 'revision_restore_confirm' => 'Apakah Anda yakin ingin memulihkan revisi ini? Konten halaman saat ini akan diganti.', 'revision_delete_success' => 'Revisi dihapus', - 'revision_cannot_delete_latest' => 'Tidak dapat menghapus revisi terakhir.' + 'revision_cannot_delete_latest' => 'Tidak dapat menghapus revisi terakhir.', ]; diff --git a/resources/lang/id/passwords.php b/resources/lang/id/passwords.php index 3ee2e4d57..c4578b8d1 100644 --- a/resources/lang/id/passwords.php +++ b/resources/lang/id/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'Kata sandi harus setidaknya delapan karakter dan sesuai dengan konfirmasi.', - 'user' => "Kami tidak dapat menemukan pengguna dengan alamat email tersebut.", + 'user' => 'Kami tidak dapat menemukan pengguna dengan alamat email tersebut.', 'token' => 'Token setel ulang sandi tidak valid untuk alamat email ini.', 'sent' => 'Kami telah mengirimkan email tautan pengaturan ulang kata sandi Anda!', 'reset' => 'Kata sandi Anda telah disetel ulang!', diff --git a/resources/lang/id/settings.php b/resources/lang/id/settings.php index 95499acde..134b62150 100644 --- a/resources/lang/id/settings.php +++ b/resources/lang/id/settings.php @@ -72,7 +72,7 @@ return [ // Maintenance settings 'maint' => 'Pemeliharaan', 'maint_image_cleanup' => 'Gambar Bersihkan', - 'maint_image_cleanup_desc' => "Pindai halaman & konten revisi untuk memeriksa gambar dan gambar mana yang saat ini digunakan dan gambar mana yang berlebihan. Pastikan Anda membuat database lengkap dan cadangan gambar sebelum menjalankan ini.", + 'maint_image_cleanup_desc' => 'Pindai halaman & konten revisi untuk memeriksa gambar dan gambar mana yang saat ini digunakan dan gambar mana yang berlebihan. Pastikan Anda membuat database lengkap dan cadangan gambar sebelum menjalankan ini.', 'maint_delete_images_only_in_revisions' => 'Hapus juga gambar yang hanya ada di revisi halaman lama', 'maint_image_cleanup_run' => 'Jalankan Pembersihan', 'maint_image_cleanup_warning' => ':count ditemukan gambar yang berpotensi tidak digunakan. Anda yakin ingin menghapus gambar-gambar ini?', @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Hapus Peran', 'role_delete_confirm' => 'Ini akan menghapus peran dengan nama \':roleName\'.', 'role_delete_users_assigned' => 'Peran ini memiliki :userCount pengguna yang ditugaskan padanya. Jika Anda ingin memindahkan pengguna dari peran ini pilih peran baru di bawah.', - 'role_delete_no_migration' => "Jangan migrasikan pengguna", + 'role_delete_no_migration' => 'Jangan migrasikan pengguna', 'role_delete_sure' => 'Anda yakin ingin menghapus peran ini?', 'role_delete_success' => 'Peran berhasil dihapus', 'role_edit' => 'Edit Peran', @@ -273,6 +273,6 @@ return [ 'vi' => 'Tiếng Việt', 'zh_CN' => '简体中文', 'zh_TW' => '繁體中文', - ] + ], //!//////////////////////////////// ]; diff --git a/resources/lang/it/auth.php b/resources/lang/it/auth.php index 2a33a3184..7cd745137 100755 --- a/resources/lang/it/auth.php +++ b/resources/lang/it/auth.php @@ -38,7 +38,6 @@ return [ 'registration_email_domain_invalid' => 'Questo dominio della mail non ha accesso a questa applicazione', 'register_success' => 'Grazie per la registrazione! Sei registrato e loggato.', - // Password Reset 'reset_password' => 'Reimposta Password', 'reset_password_send_instructions' => 'Inserisci il tuo indirizzo sotto e ti verrà inviata una mail contenente un link per resettare la tua password.', @@ -49,7 +48,6 @@ return [ 'email_reset_text' => 'Stai ricevendo questa mail perché abbiamo ricevuto una richiesta di reset della password per il tuo account.', 'email_reset_not_requested' => 'Se non hai richiesto un reset della password, ignora questa mail.', - // Email Confirmation 'email_confirm_subject' => 'Conferma email per :appName', 'email_confirm_greeting' => 'Grazie per esserti registrato a :appName!', @@ -109,4 +107,4 @@ return [ 'mfa_verify_backup_code_enter_here' => 'Inserisci qui il codice di backup', 'mfa_verify_totp_desc' => 'Inserisci il codice, generato tramite la tua app mobile, qui sotto:', 'mfa_setup_login_notification' => 'Metodo multi-fattore configurato, si prega di effettuare nuovamente il login utilizzando il metodo configurato.', -]; \ No newline at end of file +]; diff --git a/resources/lang/it/common.php b/resources/lang/it/common.php index bcd3aadf9..dc148f9f1 100755 --- a/resources/lang/it/common.php +++ b/resources/lang/it/common.php @@ -20,7 +20,7 @@ return [ 'role' => 'Ruolo', 'cover_image' => 'Immagine di copertina', 'cover_image_description' => 'Questa immagine dovrebbe essere approssimativamente 440x250px.', - + // Actions 'actions' => 'Azioni', 'view' => 'Visualizza', diff --git a/resources/lang/it/entities.php b/resources/lang/it/entities.php index 64354b751..507e502a0 100755 --- a/resources/lang/it/entities.php +++ b/resources/lang/it/entities.php @@ -321,5 +321,5 @@ return [ 'revision_delete_confirm' => 'Sei sicuro di voler eliminare questa revisione?', 'revision_restore_confirm' => 'Sei sicuro di voler ripristinare questa revisione? Il contenuto della pagina verrà rimpiazzato.', 'revision_delete_success' => 'Revisione cancellata', - 'revision_cannot_delete_latest' => 'Impossibile eliminare l\'ultima revisione.' + 'revision_cannot_delete_latest' => 'Impossibile eliminare l\'ultima revisione.', ]; diff --git a/resources/lang/it/passwords.php b/resources/lang/it/passwords.php index 7099d54f3..03afdbe2d 100755 --- a/resources/lang/it/passwords.php +++ b/resources/lang/it/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'La password deve avere almeno sei caratteri e corrispondere alla conferma.', - 'user' => "Non possiamo trovare un utente per quella mail.", + 'user' => 'Non possiamo trovare un utente per quella mail.', 'token' => 'Il token per reimpostare la password non è valido per questo indirizzo email.', 'sent' => 'Ti abbiamo inviato via mail il link per reimpostare la password!', 'reset' => 'La tua password è stata reimpostata!', diff --git a/resources/lang/it/settings.php b/resources/lang/it/settings.php index 3abb1c45e..6227dbf17 100755 --- a/resources/lang/it/settings.php +++ b/resources/lang/it/settings.php @@ -72,7 +72,7 @@ return [ // Maintenance settings 'maint' => 'Manutenzione', 'maint_image_cleanup' => 'Pulizia Immagini', - 'maint_image_cleanup_desc' => "Esegue la scansione del contenuto delle pagine e delle revisioni per verificare quali immagini e disegni sono attualmente in uso e quali immagini sono ridondanti. Assicurati di creare backup completo del database e delle immagini prima di eseguire la pulizia.", + 'maint_image_cleanup_desc' => 'Esegue la scansione del contenuto delle pagine e delle revisioni per verificare quali immagini e disegni sono attualmente in uso e quali immagini sono ridondanti. Assicurati di creare backup completo del database e delle immagini prima di eseguire la pulizia.', 'maint_delete_images_only_in_revisions' => 'Elimina anche le immagini che esistono solo nelle vecchie revisioni della pagina', 'maint_image_cleanup_run' => 'Esegui Pulizia', 'maint_image_cleanup_warning' => ':count immagini potenzialmente inutilizzate sono state trovate. Sei sicuro di voler eliminare queste immagini?', @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Elimina Ruolo', 'role_delete_confirm' => 'Questo eliminerà il ruolo con il nome \':roleName\'.', 'role_delete_users_assigned' => 'Questo ruolo ha :userCount utenti assegnati. Se vuoi migrare gli utenti da questo ruolo selezionane uno nuovo sotto.', - 'role_delete_no_migration' => "Non migrare gli utenti", + 'role_delete_no_migration' => 'Non migrare gli utenti', 'role_delete_sure' => 'Sei sicuro di voler eliminare questo ruolo?', 'role_delete_success' => 'Ruolo eliminato correttamente', 'role_edit' => 'Modifica Ruolo', @@ -273,6 +273,6 @@ return [ 'vi' => 'Tiếng Việt', 'zh_CN' => '简体中文', 'zh_TW' => '繁體中文', - ] + ], //!//////////////////////////////// ]; diff --git a/resources/lang/ja/auth.php b/resources/lang/ja/auth.php index 98f56e73e..ff7c3a68b 100644 --- a/resources/lang/ja/auth.php +++ b/resources/lang/ja/auth.php @@ -38,7 +38,6 @@ return [ 'registration_email_domain_invalid' => 'このEmailドメインでの登録は許可されていません。', 'register_success' => '登録が完了し、ログインできるようになりました!', - // Password Reset 'reset_password' => 'パスワードリセット', 'reset_password_send_instructions' => '以下にEメールアドレスを入力すると、パスワードリセットリンクが記載されたメールが送信されます。', @@ -49,7 +48,6 @@ return [ 'email_reset_text' => 'このメールは、パスワードリセットがリクエストされたため送信されています。', 'email_reset_not_requested' => 'もしパスワードリセットを希望しない場合、操作は不要です。', - // Email Confirmation 'email_confirm_subject' => ':appNameのメールアドレス確認', 'email_confirm_greeting' => ':appNameへ登録してくださりありがとうございます!', @@ -109,4 +107,4 @@ return [ 'mfa_verify_backup_code_enter_here' => 'Enter backup code here', 'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:', 'mfa_setup_login_notification' => '多要素認証が構成されました。設定された手段を利用して再度ログインしてください。', -]; \ No newline at end of file +]; diff --git a/resources/lang/ja/common.php b/resources/lang/ja/common.php index f7a0fdad6..873d367d7 100644 --- a/resources/lang/ja/common.php +++ b/resources/lang/ja/common.php @@ -20,7 +20,7 @@ return [ 'role' => '権限', 'cover_image' => 'カバー画像', 'cover_image_description' => 'この画像はおよそ440x250pxの大きさが必要です。', - + // Actions 'actions' => '実行', 'view' => '表示', diff --git a/resources/lang/ja/entities.php b/resources/lang/ja/entities.php index 62d806eec..5a1941057 100644 --- a/resources/lang/ja/entities.php +++ b/resources/lang/ja/entities.php @@ -94,7 +94,7 @@ return [ 'shelves_edit' => '本棚を編集', 'shelves_delete' => '本棚を削除', 'shelves_delete_named' => '本棚「:name」を削除', - 'shelves_delete_explain' => "これにより、この本棚「:name」が削除されます。含まれているブックは削除されません。", + 'shelves_delete_explain' => 'これにより、この本棚「:name」が削除されます。含まれているブックは削除されません。', 'shelves_delete_confirmation' => '本当にこの本棚を削除してよろしいですか?', 'shelves_permissions' => 'Bookshelf Permissions', 'shelves_permissions_updated' => 'Bookshelf Permissions Updated', @@ -321,5 +321,5 @@ return [ 'revision_delete_confirm' => 'このリビジョンを削除しますか?', 'revision_restore_confirm' => 'Are you sure you want to restore this revision? The current page contents will be replaced.', 'revision_delete_success' => 'リビジョンを削除しました', - 'revision_cannot_delete_latest' => '最新のリビジョンを削除できません。' + 'revision_cannot_delete_latest' => '最新のリビジョンを削除できません。', ]; diff --git a/resources/lang/ja/passwords.php b/resources/lang/ja/passwords.php index cf4d43114..40493f6ce 100644 --- a/resources/lang/ja/passwords.php +++ b/resources/lang/ja/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'パスワードは6文字以上である必要があります。', - 'user' => "このEメールアドレスに一致するユーザが見つかりませんでした。", + 'user' => 'このEメールアドレスに一致するユーザが見つかりませんでした。', 'token' => 'このメールアドレスのパスワードリセットトークンは無効です。', 'sent' => 'パスワードリセットリンクを送信しました。', 'reset' => 'パスワードはリセットされました。', diff --git a/resources/lang/ja/settings.php b/resources/lang/ja/settings.php index 4e2af0212..76da40deb 100644 --- a/resources/lang/ja/settings.php +++ b/resources/lang/ja/settings.php @@ -72,7 +72,7 @@ return [ // Maintenance settings 'maint' => 'メンテナンス', 'maint_image_cleanup' => '画像のクリーンアップ', - 'maint_image_cleanup_desc' => "ページや履歴の内容をスキャンして、どの画像や図面が現在使用されているか、どの画像が余っているかをチェックします。この機能を実行する前に、データベースと画像の完全なバックアップを作成してください。", + 'maint_image_cleanup_desc' => 'ページや履歴の内容をスキャンして、どの画像や図面が現在使用されているか、どの画像が余っているかをチェックします。この機能を実行する前に、データベースと画像の完全なバックアップを作成してください。', 'maint_delete_images_only_in_revisions' => 'また、古いページのリビジョンにしか存在しない画像も削除します。', 'maint_image_cleanup_run' => 'クリーンアップを実行', 'maint_image_cleanup_warning' => ':count 個、使用されていない可能性のある画像が見つかりました。これらの画像を削除してもよろしいですか?', @@ -132,7 +132,7 @@ return [ 'role_delete' => '役割を削除', 'role_delete_confirm' => '役割「:roleName」を削除します。', 'role_delete_users_assigned' => 'この役割は:userCount人のユーザに付与されています。該当するユーザを他の役割へ移行できます。', - 'role_delete_no_migration' => "ユーザを移行しない", + 'role_delete_no_migration' => 'ユーザを移行しない', 'role_delete_sure' => '本当に役割を削除してよろしいですか?', 'role_delete_success' => '役割を削除しました', 'role_edit' => '役割を編集', @@ -273,6 +273,6 @@ return [ 'vi' => 'Tiếng Việt', 'zh_CN' => '简体中文', 'zh_TW' => '繁體中文', - ] + ], //!//////////////////////////////// ]; diff --git a/resources/lang/ko/auth.php b/resources/lang/ko/auth.php index ce65f3ecc..3cff67d4d 100644 --- a/resources/lang/ko/auth.php +++ b/resources/lang/ko/auth.php @@ -38,7 +38,6 @@ return [ 'registration_email_domain_invalid' => '이 메일 주소로는 이 사이트에 접근할 수 없습니다.', 'register_success' => '가입했습니다! 이제 로그인할 수 있습니다.', - // Password Reset 'reset_password' => '비밀번호 바꾸기', 'reset_password_send_instructions' => '메일 주소를 입력하세요. 이 주소로 해당 과정을 위한 링크를 보낼 것입니다.', @@ -49,7 +48,6 @@ return [ 'email_reset_text' => '비밀번호를 바꿉니다.', 'email_reset_not_requested' => '원하지 않는다면 이 과정은 필요 없습니다.', - // Email Confirmation 'email_confirm_subject' => ':appName 메일 인증', 'email_confirm_greeting' => ':appName로 가입해 주셔서 감사합니다!', @@ -109,4 +107,4 @@ return [ 'mfa_verify_backup_code_enter_here' => 'Enter backup code here', 'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:', 'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.', -]; \ No newline at end of file +]; diff --git a/resources/lang/ko/common.php b/resources/lang/ko/common.php index 2349ab735..26b52744d 100644 --- a/resources/lang/ko/common.php +++ b/resources/lang/ko/common.php @@ -20,7 +20,7 @@ return [ 'role' => '권한', 'cover_image' => '대표 이미지', 'cover_image_description' => '이미지 규격은 440x250px 내외입니다.', - + // Actions 'actions' => '활동', 'view' => '보기', diff --git a/resources/lang/ko/entities.php b/resources/lang/ko/entities.php index 46dced1ec..41d4dfb01 100644 --- a/resources/lang/ko/entities.php +++ b/resources/lang/ko/entities.php @@ -94,7 +94,7 @@ return [ 'shelves_edit' => '서가 바꾸기', 'shelves_delete' => '서가 삭제하기', 'shelves_delete_named' => ':name 삭제하기', - 'shelves_delete_explain' => ":name을 지웁니다. 책자는 지우지 않습니다.", + 'shelves_delete_explain' => ':name을 지웁니다. 책자는 지우지 않습니다.', 'shelves_delete_confirmation' => '이 서가를 지울 건가요?', 'shelves_permissions' => '서가 권한', 'shelves_permissions_updated' => '서가 권한 바꿈', @@ -255,7 +255,7 @@ return [ 'tags' => '꼬리표', 'tag_name' => '꼬리표 이름', 'tag_value' => '리스트 값 (선택 사항)', - 'tags_explain' => "태그로 문서를 분류하세요.", + 'tags_explain' => '태그로 문서를 분류하세요.', 'tags_add' => '태그 추가', 'tags_remove' => '태그 삭제', 'attachments' => '첨부 파일', @@ -321,5 +321,5 @@ return [ 'revision_delete_confirm' => '이 수정본을 지울 건가요?', 'revision_restore_confirm' => '이 수정본을 되돌릴 건가요? 현재 판본을 바꿉니다.', 'revision_delete_success' => '수정본 지움', - 'revision_cannot_delete_latest' => '현재 판본은 지울 수 없습니다.' + 'revision_cannot_delete_latest' => '현재 판본은 지울 수 없습니다.', ]; diff --git a/resources/lang/ko/errors.php b/resources/lang/ko/errors.php index b52ee91bc..e4ed5ccb3 100644 --- a/resources/lang/ko/errors.php +++ b/resources/lang/ko/errors.php @@ -28,7 +28,7 @@ return [ 'oidc_no_email_address' => 'Could not find an email address, for this user, in the data provided by the external authentication system', 'oidc_fail_authed' => 'Login using :system failed, system did not provide successful authorization', 'social_no_action_defined' => '무슨 활동인지 알 수 없습니다.', - 'social_login_bad_response' => ":socialAccount에 로그인할 수 없습니다. : \\n:error", + 'social_login_bad_response' => ':socialAccount에 로그인할 수 없습니다. : \\n:error', 'social_account_in_use' => ':socialAccount(을)를 가진 사용자가 있습니다. :socialAccount로 로그인하세요.', 'social_account_email_in_use' => ':email(을)를 가진 사용자가 있습니다. 쓰고 있는 계정을 :socialAccount에 연결하세요.', 'social_account_existing' => ':socialAccount(와)과 연결 상태입니다.', diff --git a/resources/lang/ko/passwords.php b/resources/lang/ko/passwords.php index f93902aef..461afc74b 100644 --- a/resources/lang/ko/passwords.php +++ b/resources/lang/ko/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => '여덟 글자를 넘어야 합니다.', - 'user' => "메일 주소를 가진 사용자가 없습니다.", + 'user' => '메일 주소를 가진 사용자가 없습니다.', 'token' => '비밀번호 재설정 토큰이 이 이메일 주소에 유효하지 않습니다.', 'sent' => '메일을 보냈습니다.', 'reset' => '비밀번호를 바꿨습니다.', diff --git a/resources/lang/ko/settings.php b/resources/lang/ko/settings.php index f9c0290a6..de5b59d50 100755 --- a/resources/lang/ko/settings.php +++ b/resources/lang/ko/settings.php @@ -72,7 +72,7 @@ return [ // Maintenance settings 'maint' => '데이터', 'maint_image_cleanup' => '이미지 정리', - 'maint_image_cleanup_desc' => "중복한 이미지를 찾습니다. 실행하기 전에 이미지를 백업하세요.", + 'maint_image_cleanup_desc' => '중복한 이미지를 찾습니다. 실행하기 전에 이미지를 백업하세요.', 'maint_delete_images_only_in_revisions' => 'Also delete images that only exist in old page revisions', 'maint_image_cleanup_run' => '실행', 'maint_image_cleanup_warning' => '이미지 :count개를 지울 건가요?', @@ -132,7 +132,7 @@ return [ 'role_delete' => '권한 제거', 'role_delete_confirm' => ':roleName(을)를 지웁니다.', 'role_delete_users_assigned' => '이 권한을 가진 사용자 :userCount명에 할당할 권한을 고르세요.', - 'role_delete_no_migration' => "할당하지 않음", + 'role_delete_no_migration' => '할당하지 않음', 'role_delete_sure' => '이 권한을 지울 건가요?', 'role_delete_success' => '권한 지움', 'role_edit' => '권한 수정', @@ -273,6 +273,6 @@ return [ 'vi' => 'Tiếng Việt', 'zh_CN' => '简体中文', 'zh_TW' => '繁體中文', - ] + ], //!//////////////////////////////// ]; diff --git a/resources/lang/lt/auth.php b/resources/lang/lt/auth.php index f9bf271f6..e4a17eae5 100644 --- a/resources/lang/lt/auth.php +++ b/resources/lang/lt/auth.php @@ -38,7 +38,6 @@ return [ 'registration_email_domain_invalid' => 'Elektroninio pašto domenas neturi prieigos prie šios programos', 'register_success' => 'Ačiū už prisijungimą! Dabar jūs užsiregistravote ir prisijungėte.', - // Password Reset 'reset_password' => 'Pakeisti slaptažodį', 'reset_password_send_instructions' => 'Įveskite savo elektroninį paštą žemiau ir jums bus išsiųstas elektroninis laiškas su slaptažodžio nustatymo nuoroda.', @@ -49,7 +48,6 @@ return [ 'email_reset_text' => 'Šį laišką gaunate, nes mes gavome slaptažodžio atnaujinimo užklausą iš jūsų paskyros.', 'email_reset_not_requested' => 'Jeigu jums nereikia slaptažodžio atnaujinimo, tolimesnių veiksmų atlikti nereikia.', - // Email Confirmation 'email_confirm_subject' => 'Patvirtinkite savo elektroninį paštą :appName', 'email_confirm_greeting' => 'Ačiū už prisijungimą prie :appName!', @@ -109,4 +107,4 @@ return [ 'mfa_verify_backup_code_enter_here' => 'Enter backup code here', 'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:', 'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.', -]; \ No newline at end of file +]; diff --git a/resources/lang/lt/common.php b/resources/lang/lt/common.php index 7ed434b98..f1766a615 100644 --- a/resources/lang/lt/common.php +++ b/resources/lang/lt/common.php @@ -20,7 +20,7 @@ return [ 'role' => 'Vaidmuo', 'cover_image' => 'Viršelio nuotrauka', 'cover_image_description' => 'Ši nuotrauka turi būti maždaug 440x250px.', - + // Actions 'actions' => 'Veiksmai', 'view' => 'Rodyti', diff --git a/resources/lang/lt/entities.php b/resources/lang/lt/entities.php index f1eda39e0..4266f61de 100644 --- a/resources/lang/lt/entities.php +++ b/resources/lang/lt/entities.php @@ -321,5 +321,5 @@ return [ 'revision_delete_confirm' => 'Esate tikri, kad norite ištrinti šią peržiūrą?', 'revision_restore_confirm' => 'Esate tikri, kad norite atkurti šią peržiūrą? Dabartinis puslapio turinys bus pakeistas.', 'revision_delete_success' => 'Peržiūra ištrinta', - 'revision_cannot_delete_latest' => 'Negalima išrinti vėliausios peržiūros' + 'revision_cannot_delete_latest' => 'Negalima išrinti vėliausios peržiūros', ]; diff --git a/resources/lang/lt/settings.php b/resources/lang/lt/settings.php index c69694951..8d55646db 100644 --- a/resources/lang/lt/settings.php +++ b/resources/lang/lt/settings.php @@ -72,7 +72,7 @@ return [ // Maintenance settings 'maint' => 'Priežiūra', 'maint_image_cleanup' => 'Išvalykite vaizdus', - 'maint_image_cleanup_desc' => "Scans page & revision content to check which images and drawings are currently in use and which images are redundant. Ensure you create a full database and image backup before running this.", + 'maint_image_cleanup_desc' => 'Scans page & revision content to check which images and drawings are currently in use and which images are redundant. Ensure you create a full database and image backup before running this.', 'maint_delete_images_only_in_revisions' => 'Taip pat ištrinkite vaizdus, kurie yra tik senuose puslapių pataisymuose', 'maint_image_cleanup_run' => 'Paleisti valymą', 'maint_image_cleanup_warning' => ':count potencialiai nepanaudoti vaizdai rasti. Ar esate tikri, kad norite ištrinti šiuos vaizdus?', @@ -273,6 +273,6 @@ return [ 'vi' => 'Tiếng Việt', 'zh_CN' => '简体中文', 'zh_TW' => '繁體中文', - ] + ], //!//////////////////////////////// ]; diff --git a/resources/lang/lv/auth.php b/resources/lang/lv/auth.php index 497509d54..e228bed00 100644 --- a/resources/lang/lv/auth.php +++ b/resources/lang/lv/auth.php @@ -38,7 +38,6 @@ return [ 'registration_email_domain_invalid' => 'E-pasta domēnam nav piekļuves pie šīs aplikācijas', 'register_success' => 'Paldies par reģistrēšanos! Tagad varat pieslēgties.', - // Password Reset 'reset_password' => 'Atiestatīt paroli', 'reset_password_send_instructions' => 'Ievadiet savu e-pastu zemāk un nosūtīsim e-pastu ar paroles atiestatīšanas saiti.', @@ -49,7 +48,6 @@ return [ 'email_reset_text' => 'Jūs saņemat šo e-pastu, jo mēs saņēmām Jūsu profila paroles atiestatīšanas pieprasījumu.', 'email_reset_not_requested' => 'Ja Jūs nepieprasījāt paroles atiestatīšanu, tad tālākas darbības nav nepieciešamas.', - // Email Confirmation 'email_confirm_subject' => 'Apstiprinat savu :appName e-pastu', 'email_confirm_greeting' => 'Paldies, ka pievienojāties :appName!', @@ -109,4 +107,4 @@ return [ 'mfa_verify_backup_code_enter_here' => 'Enter backup code here', 'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:', 'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.', -]; \ No newline at end of file +]; diff --git a/resources/lang/lv/common.php b/resources/lang/lv/common.php index 23cd07d7d..3bc022e42 100644 --- a/resources/lang/lv/common.php +++ b/resources/lang/lv/common.php @@ -20,7 +20,7 @@ return [ 'role' => 'Loma', 'cover_image' => 'Vāka attēls', 'cover_image_description' => 'Šim attēlam būtu jābūt aptuveni 440x250px.', - + // Actions 'actions' => 'Darbības', 'view' => 'Skatīt', diff --git a/resources/lang/lv/entities.php b/resources/lang/lv/entities.php index 4cfca7aa5..f5ef3b06c 100644 --- a/resources/lang/lv/entities.php +++ b/resources/lang/lv/entities.php @@ -94,7 +94,7 @@ return [ 'shelves_edit' => 'Labot grāmatplauktu', 'shelves_delete' => 'Dzēst grāmatplauktu', 'shelves_delete_named' => 'Dzēst grāmatplauktu :name', - 'shelves_delete_explain' => "Tiks dzēsts grāmatplaukts ar nosaukumu \":name\". Tajā ievietotās grāmatas netiks dzēstas.", + 'shelves_delete_explain' => 'Tiks dzēsts grāmatplaukts ar nosaukumu ":name". Tajā ievietotās grāmatas netiks dzēstas.', 'shelves_delete_confirmation' => 'Vai esat pārliecināts, ka vēlaties dzēst šo grāmatplauktu?', 'shelves_permissions' => 'Grāmatplaukta atļaujas', 'shelves_permissions_updated' => 'Grāmatplaukta atļaujas atjauninātas', @@ -321,5 +321,5 @@ return [ 'revision_delete_confirm' => 'Vai esat pārliecināts, ka vēlaties dzēst šo revīziju?', 'revision_restore_confirm' => 'Vai tiešām vēlaties atjaunot šo revīziju? Pašreizējais lapas saturs tiks aizvietots.', 'revision_delete_success' => 'Revīzija dzēsta', - 'revision_cannot_delete_latest' => 'Nevar dzēst pašreizējo revīziju.' + 'revision_cannot_delete_latest' => 'Nevar dzēst pašreizējo revīziju.', ]; diff --git a/resources/lang/lv/passwords.php b/resources/lang/lv/passwords.php index 7d939574f..5824e71e6 100644 --- a/resources/lang/lv/passwords.php +++ b/resources/lang/lv/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'Parolēm jābūt vismaz astoņu simbolu garām un jāatbilst apstiprinājumam.', - 'user' => "Mēs nevaram atrast lietotāju ar šādu e-pasta adresi.", + 'user' => 'Mēs nevaram atrast lietotāju ar šādu e-pasta adresi.', 'token' => 'Paroles atiestatīšanas atslēga neatbilst šai e-pasta adresei.', 'sent' => 'Esam nosūtījuši paroles atiestatīšanas saiti!', 'reset' => 'Parole ir atiestatīta!', diff --git a/resources/lang/lv/settings.php b/resources/lang/lv/settings.php index 79aca4e54..1ecc00524 100644 --- a/resources/lang/lv/settings.php +++ b/resources/lang/lv/settings.php @@ -72,7 +72,7 @@ return [ // Maintenance settings 'maint' => 'Apkope', 'maint_image_cleanup' => 'Tīrīt neizmantotās bildes', - 'maint_image_cleanup_desc' => "Pārbauda lapu un lapu versiju saturu, lai noteiktu, kuri attēli pašlaik tiek izmantoti, un kuri nav nepieciešami. Pārliecinieties, ka ir veikta pilna datubāzes un attēlu rezerves kopija pirms šīs darbības.", + 'maint_image_cleanup_desc' => 'Pārbauda lapu un lapu versiju saturu, lai noteiktu, kuri attēli pašlaik tiek izmantoti, un kuri nav nepieciešami. Pārliecinieties, ka ir veikta pilna datubāzes un attēlu rezerves kopija pirms šīs darbības.', 'maint_delete_images_only_in_revisions' => 'Dzēst arī attēlus, kas izmantoti tikai vecās lapu satura versijās', 'maint_image_cleanup_run' => 'Veikt tīrīšanu', 'maint_image_cleanup_warning' => ':count iespējami neizmantoti attēli atrasti. Vai tiešām vēlaties izdzēst šos attēlus?', @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Dzēst grupu', 'role_delete_confirm' => 'Loma \':roleName\' tiks dzēsta.', 'role_delete_users_assigned' => 'Šajā grupā ir pievienoti :userCount lietotāji. Ja vēlaties pārvietot lietotājus no šīs grupas, tad izvēlaties kādu no zemāk redzamajām grupām.', - 'role_delete_no_migration' => "Nepārvietot lietotājus", + 'role_delete_no_migration' => 'Nepārvietot lietotājus', 'role_delete_sure' => 'Vai tiešām vēlaties dzēst grupu?', 'role_delete_success' => 'Grupa veiksmīgi dzēsta', 'role_edit' => 'Rediģēt grupu', @@ -273,6 +273,6 @@ return [ 'vi' => 'Tiếng Việt', 'zh_CN' => '简体中文', 'zh_TW' => '繁體中文', - ] + ], //!//////////////////////////////// ]; diff --git a/resources/lang/nb/auth.php b/resources/lang/nb/auth.php index 4c1f55577..a59e18bb5 100644 --- a/resources/lang/nb/auth.php +++ b/resources/lang/nb/auth.php @@ -38,7 +38,6 @@ return [ 'registration_email_domain_invalid' => 'Du kan ikke bruke det domenet for å registrere en konto.', 'register_success' => 'Takk for registreringen! Du kan nå logge inn på tjenesten.', - // Password Reset 'reset_password' => 'Nullstille passord', 'reset_password_send_instructions' => 'Oppgi e-posten som er koblet til kontoen din, så sender vi en epost hvor du kan nullstille passordet.', @@ -49,7 +48,6 @@ return [ 'email_reset_text' => 'Du mottar denne eposten fordi det er blitt bedt om en nullstilling av passord på denne kontoen.', 'email_reset_not_requested' => 'Om det ikke var deg, så trenger du ikke foreta deg noe.', - // Email Confirmation 'email_confirm_subject' => 'Bekreft epost-adressen for :appName', 'email_confirm_greeting' => 'Takk for at du registrerte deg for :appName!', @@ -109,4 +107,4 @@ return [ 'mfa_verify_backup_code_enter_here' => 'Skriv inn sikkerhetskode her', 'mfa_verify_totp_desc' => 'Skriv inn koden, generert ved hjelp av mobilapplikasjonen, nedenfor:', 'mfa_setup_login_notification' => 'Flerfaktorautentisering er konfigurert, vennligst logg inn på nytt med denne metoden.', -]; \ No newline at end of file +]; diff --git a/resources/lang/nb/common.php b/resources/lang/nb/common.php index 8ba4e7474..cd01b132f 100644 --- a/resources/lang/nb/common.php +++ b/resources/lang/nb/common.php @@ -20,7 +20,7 @@ return [ 'role' => 'Rolle', 'cover_image' => 'Bokomslag', 'cover_image_description' => 'Bildet bør være ca. 440x250px.', - + // Actions 'actions' => 'Handlinger', 'view' => 'Vis', diff --git a/resources/lang/nb/entities.php b/resources/lang/nb/entities.php index 705c33875..756ee5c71 100644 --- a/resources/lang/nb/entities.php +++ b/resources/lang/nb/entities.php @@ -321,5 +321,5 @@ return [ 'revision_delete_confirm' => 'Vil du slette revisjonen?', 'revision_restore_confirm' => 'Vil du gjenopprette revisjonen? Innholdet på siden vil bli overskrevet med denne revisjonen.', 'revision_delete_success' => 'Revisjonen ble slettet', - 'revision_cannot_delete_latest' => 'CKan ikke slette siste revisjon.' + 'revision_cannot_delete_latest' => 'CKan ikke slette siste revisjon.', ]; diff --git a/resources/lang/nb/passwords.php b/resources/lang/nb/passwords.php index 8c3215b42..b7afdaa80 100644 --- a/resources/lang/nb/passwords.php +++ b/resources/lang/nb/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'Passord må inneholde minst åtte tegn og samsvarer med bekreftelsen.', - 'user' => "Vi finner ikke en bruker med den e-postadressen.", + 'user' => 'Vi finner ikke en bruker med den e-postadressen.', 'token' => 'Passordet for tilbakestilling av passord er ugyldig for denne e-postadressen.', 'sent' => 'Vi har sendt e-postadressen til tilbakestilling av passordet ditt!', 'reset' => 'Passordet ditt har blitt tilbakestilt!', diff --git a/resources/lang/nb/settings.php b/resources/lang/nb/settings.php index 134208d7d..5a6a0fb06 100644 --- a/resources/lang/nb/settings.php +++ b/resources/lang/nb/settings.php @@ -72,7 +72,7 @@ return [ // Maintenance settings 'maint' => 'Vedlikehold', 'maint_image_cleanup' => 'Bildeopprydding', - 'maint_image_cleanup_desc' => "Skanner side og revisjonsinnhold for å sjekke hvilke bilder og tegninger som for øyeblikket er i bruk, og hvilke bilder som er overflødige. Forsikre deg om at du lager en full database og sikkerhetskopiering av bilder før du kjører denne.", + 'maint_image_cleanup_desc' => 'Skanner side og revisjonsinnhold for å sjekke hvilke bilder og tegninger som for øyeblikket er i bruk, og hvilke bilder som er overflødige. Forsikre deg om at du lager en full database og sikkerhetskopiering av bilder før du kjører denne.', 'maint_delete_images_only_in_revisions' => 'Slett også bilder som bare finnes i game siderevisjoner', 'maint_image_cleanup_run' => 'Kjør opprydding', 'maint_image_cleanup_warning' => ':count potensielt ubrukte bilder ble funnet. Er du sikker på at du vil slette disse bildene?', @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Rolle slettet', 'role_delete_confirm' => 'Dette vil slette rollen «:roleName».', 'role_delete_users_assigned' => 'Denne rollen har :userCount kontoer koblet opp mot seg. Velg hvilke rolle du vil flytte disse til.', - 'role_delete_no_migration' => "Ikke flytt kontoer", + 'role_delete_no_migration' => 'Ikke flytt kontoer', 'role_delete_sure' => 'Er du sikker på at du vil slette rollen?', 'role_delete_success' => 'Rollen ble slettet', 'role_edit' => 'Endre rolle', @@ -273,6 +273,6 @@ return [ 'vi' => 'Tiếng Việt', 'zh_CN' => '简体中文', 'zh_TW' => '繁體中文', - ] + ], //!//////////////////////////////// ]; diff --git a/resources/lang/nl/auth.php b/resources/lang/nl/auth.php index f57b2ecc7..3cec0a94d 100644 --- a/resources/lang/nl/auth.php +++ b/resources/lang/nl/auth.php @@ -38,7 +38,6 @@ return [ 'registration_email_domain_invalid' => 'Dit e-maildomein is niet toegestaan', 'register_success' => 'Bedankt voor het aanmelden! Je bent nu geregistreerd en aangemeld.', - // Password Reset 'reset_password' => 'Wachtwoord herstellen', 'reset_password_send_instructions' => 'Geef je e-mail en we sturen je een link om je wachtwoord te herstellen', @@ -49,7 +48,6 @@ return [ 'email_reset_text' => 'Je ontvangt deze e-mail omdat je een wachtwoord herstel verzoek had verzonden.', 'email_reset_not_requested' => 'Als je geen wachtwoord herstel hebt aangevraagd, hoef je niets te doen.', - // Email Confirmation 'email_confirm_subject' => 'Bevestig je e-mailadres op :appName', 'email_confirm_greeting' => 'Bedankt voor je aanmelding op :appName!', @@ -109,4 +107,4 @@ return [ 'mfa_verify_backup_code_enter_here' => 'Enter backup code here', 'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:', 'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.', -]; \ No newline at end of file +]; diff --git a/resources/lang/nl/common.php b/resources/lang/nl/common.php index c53df6f2c..793e87b11 100644 --- a/resources/lang/nl/common.php +++ b/resources/lang/nl/common.php @@ -20,7 +20,7 @@ return [ 'role' => 'Rol', 'cover_image' => 'Omslagfoto', 'cover_image_description' => 'Deze afbeelding moet ongeveer 440x250px zijn.', - + // Actions 'actions' => 'Acties', 'view' => 'Bekijk', diff --git a/resources/lang/nl/entities.php b/resources/lang/nl/entities.php index e08ae3e62..3c3148a8b 100644 --- a/resources/lang/nl/entities.php +++ b/resources/lang/nl/entities.php @@ -321,5 +321,5 @@ return [ 'revision_delete_confirm' => 'Weet u zeker dat u deze revisie wilt verwijderen?', 'revision_restore_confirm' => 'Weet u zeker dat u deze revisie wilt herstellen? De huidige pagina-inhoud wordt vervangen.', 'revision_delete_success' => 'Revisie verwijderd', - 'revision_cannot_delete_latest' => 'Kan de laatste revisie niet verwijderen.' + 'revision_cannot_delete_latest' => 'Kan de laatste revisie niet verwijderen.', ]; diff --git a/resources/lang/nl/passwords.php b/resources/lang/nl/passwords.php index 4b27f03c2..5f90eb0df 100644 --- a/resources/lang/nl/passwords.php +++ b/resources/lang/nl/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'Wachtwoorden moeten overeenkomen en minimaal zes tekens lang zijn.', - 'user' => "We kunnen niemand vinden met dat e-mailadres.", + 'user' => 'We kunnen niemand vinden met dat e-mailadres.', 'token' => 'Het wachtwoord reset token is ongeldig voor dit e-mailadres.', 'sent' => 'We hebben je een link gestuurd om je wachtwoord te herstellen!', 'reset' => 'Je wachtwoord is hersteld!', diff --git a/resources/lang/nl/settings.php b/resources/lang/nl/settings.php index df5c93b97..ad94d0f2c 100644 --- a/resources/lang/nl/settings.php +++ b/resources/lang/nl/settings.php @@ -72,7 +72,7 @@ return [ // Maintenance settings 'maint' => 'Onderhoud', 'maint_image_cleanup' => 'Afbeeldingen opschonen', - 'maint_image_cleanup_desc' => "Scant pagina- en revisie inhoud om te controleren welke afbeeldingen en tekeningen momenteel worden gebruikt en welke afbeeldingen overbodig zijn. Zorg ervoor dat je een volledige database en afbeelding backup maakt voordat je dit uitvoert.", + 'maint_image_cleanup_desc' => 'Scant pagina- en revisie inhoud om te controleren welke afbeeldingen en tekeningen momenteel worden gebruikt en welke afbeeldingen overbodig zijn. Zorg ervoor dat je een volledige database en afbeelding backup maakt voordat je dit uitvoert.', 'maint_delete_images_only_in_revisions' => 'Ook afbeeldingen die alleen in oude pagina revisies bestaan verwijderen', 'maint_image_cleanup_run' => 'Opschonen uitvoeren', 'maint_image_cleanup_warning' => ':count potentieel ongebruikte afbeeldingen gevonden. Weet u zeker dat u deze afbeeldingen wilt verwijderen?', @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Rol Verwijderen', 'role_delete_confirm' => 'Dit verwijdert de rol \':roleName\'.', 'role_delete_users_assigned' => 'Er zijn :userCount gebruikers met deze rol. Selecteer hieronder een nieuwe rol als je deze gebruikers een andere rol wilt geven.', - 'role_delete_no_migration' => "Geen gebruikers migreren", + 'role_delete_no_migration' => 'Geen gebruikers migreren', 'role_delete_sure' => 'Weet je zeker dat je deze rol wilt verwijderen?', 'role_delete_success' => 'Rol succesvol verwijderd', 'role_edit' => 'Rol Bewerken', @@ -273,6 +273,6 @@ return [ 'vi' => 'Tiếng Việt', 'zh_CN' => '简体中文', 'zh_TW' => '繁體中文', - ] + ], //!//////////////////////////////// ]; diff --git a/resources/lang/pl/auth.php b/resources/lang/pl/auth.php index a1f66fdbe..2f42fc70a 100644 --- a/resources/lang/pl/auth.php +++ b/resources/lang/pl/auth.php @@ -38,7 +38,6 @@ return [ 'registration_email_domain_invalid' => 'Adresy e-mail z tej domeny nie mają dostępu do tej aplikacji', 'register_success' => 'Dziękujemy za rejestrację! Zostałeś zalogowany automatycznie.', - // Password Reset 'reset_password' => 'Resetowanie hasła', 'reset_password_send_instructions' => 'Wprowadź adres e-mail powiązany z Twoim kontem, by otrzymać link do resetowania hasła.', @@ -49,7 +48,6 @@ return [ 'email_reset_text' => 'Otrzymujesz tę wiadomość ponieważ ktoś zażądał zresetowania hasła do Twojego konta.', 'email_reset_not_requested' => 'Jeśli to nie Ty złożyłeś żądanie zresetowania hasła, zignoruj tę wiadomość.', - // Email Confirmation 'email_confirm_subject' => 'Potwierdź swój adres e-mail w :appName', 'email_confirm_greeting' => 'Dziękujemy za dołączenie do :appName!', @@ -109,4 +107,4 @@ return [ 'mfa_verify_backup_code_enter_here' => 'Wprowadź kod zapasowy tutaj', 'mfa_verify_totp_desc' => 'Wprowadź kod, wygenerowany przy użyciu aplikacji mobilnej poniżej:', 'mfa_setup_login_notification' => 'Metoda wieloskładnikowa skonfigurowana, zaloguj się ponownie za pomocą skonfigurowanej metody.', -]; \ No newline at end of file +]; diff --git a/resources/lang/pl/common.php b/resources/lang/pl/common.php index 1e718a63c..e9bb14011 100644 --- a/resources/lang/pl/common.php +++ b/resources/lang/pl/common.php @@ -20,7 +20,7 @@ return [ 'role' => 'Rola', 'cover_image' => 'Zdjęcie z okładki', 'cover_image_description' => 'Ten obraz powinien posiadać wymiary około 440x250px.', - + // Actions 'actions' => 'Akcje', 'view' => 'Widok', diff --git a/resources/lang/pl/entities.php b/resources/lang/pl/entities.php index af1f7eecd..31d40a63e 100644 --- a/resources/lang/pl/entities.php +++ b/resources/lang/pl/entities.php @@ -321,5 +321,5 @@ return [ 'revision_delete_confirm' => 'Czy na pewno chcesz usunąć tę wersję?', 'revision_restore_confirm' => 'Czu ma pewno chcesz przywrócić tą wersję? Aktualna zawartość strony zostanie nadpisana.', 'revision_delete_success' => 'Usunięto wersję', - 'revision_cannot_delete_latest' => 'Nie można usunąć najnowszej wersji.' + 'revision_cannot_delete_latest' => 'Nie można usunąć najnowszej wersji.', ]; diff --git a/resources/lang/pl/passwords.php b/resources/lang/pl/passwords.php index 7b67bf38d..dad844f74 100644 --- a/resources/lang/pl/passwords.php +++ b/resources/lang/pl/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'Hasło musi zawierać co najmniej 6 znaków i być zgodne z powtórzeniem.', - 'user' => "Nie znaleziono użytkownika o takim adresie e-mail.", + 'user' => 'Nie znaleziono użytkownika o takim adresie e-mail.', 'token' => 'Token resetowania hasła jest nieprawidłowy dla tego adresu e-mail.', 'sent' => 'Wysłaliśmy Ci link do resetowania hasła!', 'reset' => 'Twoje hasło zostało zresetowane!', diff --git a/resources/lang/pl/settings.php b/resources/lang/pl/settings.php index b9abe3311..fde8cc209 100644 --- a/resources/lang/pl/settings.php +++ b/resources/lang/pl/settings.php @@ -72,7 +72,7 @@ return [ // Maintenance settings 'maint' => 'Konserwacja', 'maint_image_cleanup' => 'Czyszczenie obrazków', - 'maint_image_cleanup_desc' => "Skanuje zawartość strony i poprzednie wersje, aby sprawdzić, które obrazy i rysunki są aktualnie używane, a które obrazy są zbędne. Przed uruchomieniem tej opcji należy utworzyć pełną kopię zapasową bazy danych i obrazków.", + 'maint_image_cleanup_desc' => 'Skanuje zawartość strony i poprzednie wersje, aby sprawdzić, które obrazy i rysunki są aktualnie używane, a które obrazy są zbędne. Przed uruchomieniem tej opcji należy utworzyć pełną kopię zapasową bazy danych i obrazków.', 'maint_delete_images_only_in_revisions' => 'Usuń również obrazy, które istnieją tylko w starych rewizjach strony', 'maint_image_cleanup_run' => 'Uruchom czyszczenie', 'maint_image_cleanup_warning' => 'Znaleziono :count potencjalnie niepotrzebnych obrazków. Czy na pewno chcesz je usunąć?', @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Usuń rolę', 'role_delete_confirm' => 'To spowoduje usunięcie roli \':roleName\'.', 'role_delete_users_assigned' => 'Tę rolę ma przypisanych :userCount użytkowników. Jeśli chcesz zmigrować użytkowników z tej roli, wybierz nową poniżej.', - 'role_delete_no_migration' => "Nie migruj użytkowników", + 'role_delete_no_migration' => 'Nie migruj użytkowników', 'role_delete_sure' => 'Czy na pewno chcesz usunąć tę rolę?', 'role_delete_success' => 'Rola usunięta pomyślnie', 'role_edit' => 'Edytuj rolę', @@ -273,6 +273,6 @@ return [ 'vi' => 'Tiếng Việt', 'zh_CN' => '简体中文', 'zh_TW' => '繁體中文', - ] + ], //!//////////////////////////////// ]; diff --git a/resources/lang/pt/auth.php b/resources/lang/pt/auth.php index 849bfc22e..41fdd40df 100644 --- a/resources/lang/pt/auth.php +++ b/resources/lang/pt/auth.php @@ -38,7 +38,6 @@ return [ 'registration_email_domain_invalid' => 'O domínio de e-mail usado não tem acesso permitido a esta aplicação', 'register_success' => 'Obrigado por se registar! Você está agora registado e com a sessão iniciada.', - // Password Reset 'reset_password' => 'Redefinir Senha', 'reset_password_send_instructions' => 'Insira o seu endereço de e-mail abaixo, e uma mensagem com o link de redefinição de palavra-passe será lhe enviada.', @@ -49,7 +48,6 @@ return [ 'email_reset_text' => 'Você recebeu este e-mail pois recebemos uma solicitação de redefinição de senha para a sua conta.', 'email_reset_not_requested' => 'Caso não tenha sido você a solicitar a redefinição de senha, ignore este e-mail.', - // Email Confirmation 'email_confirm_subject' => 'Confirme o seu endereço de e-mail para :appName', 'email_confirm_greeting' => 'Obrigado por se registar em :appName!', @@ -109,4 +107,4 @@ return [ 'mfa_verify_backup_code_enter_here' => 'Enter backup code here', 'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:', 'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.', -]; \ No newline at end of file +]; diff --git a/resources/lang/pt/common.php b/resources/lang/pt/common.php index d2d18a2e4..0e6e468d6 100644 --- a/resources/lang/pt/common.php +++ b/resources/lang/pt/common.php @@ -20,7 +20,7 @@ return [ 'role' => 'Cargo', 'cover_image' => 'Imagem de capa', 'cover_image_description' => 'Esta imagem deve ser aproximadamente 440x250px.', - + // Actions 'actions' => 'Ações', 'view' => 'Visualizar', diff --git a/resources/lang/pt/entities.php b/resources/lang/pt/entities.php index 07e2d5f64..1ebd805d4 100644 --- a/resources/lang/pt/entities.php +++ b/resources/lang/pt/entities.php @@ -321,5 +321,5 @@ return [ 'revision_delete_confirm' => 'Tem a certeza de que deseja eliminar esta revisão?', 'revision_restore_confirm' => 'Tem a certeza que deseja restaurar esta revisão? O conteúdo atual da página será substituído.', 'revision_delete_success' => 'Revisão excluída', - 'revision_cannot_delete_latest' => 'Não é possível eliminar a revisão mais recente.' + 'revision_cannot_delete_latest' => 'Não é possível eliminar a revisão mais recente.', ]; diff --git a/resources/lang/pt/passwords.php b/resources/lang/pt/passwords.php index e468b9f68..bf30e0e13 100644 --- a/resources/lang/pt/passwords.php +++ b/resources/lang/pt/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'As palavras-passe devem ter no mínimo oito caracteres e serem iguais à confirmação.', - 'user' => "Não pudemos encontrar um utilizador com o endereço de e-mail fornecido.", + 'user' => 'Não pudemos encontrar um utilizador com o endereço de e-mail fornecido.', 'token' => 'O token de redefinição de senha é inválido para este endereço de e-mail.', 'sent' => 'Enviamos o link de redefinição de palavra-passe para o seu e-mail!', 'reset' => 'A sua palavra-passe foi redefinida com sucesso!', diff --git a/resources/lang/pt/settings.php b/resources/lang/pt/settings.php index 83a3f5da0..31e5e87ab 100644 --- a/resources/lang/pt/settings.php +++ b/resources/lang/pt/settings.php @@ -72,7 +72,7 @@ return [ // Maintenance settings 'maint' => 'Manutenção', 'maint_image_cleanup' => 'Limpeza de Imagens', - 'maint_image_cleanup_desc' => "Examina páginas e reviste os seus conteúdos para verificar quais imagens e desenhos estão atualmente em uso e quais são redundantes. Certifique-se de criar uma cópia de segurança completa da base de dados e imagens antes de executar esta ação.", + 'maint_image_cleanup_desc' => 'Examina páginas e reviste os seus conteúdos para verificar quais imagens e desenhos estão atualmente em uso e quais são redundantes. Certifique-se de criar uma cópia de segurança completa da base de dados e imagens antes de executar esta ação.', 'maint_delete_images_only_in_revisions' => 'Eliminar também imagens que existam apenas em revisões de página antigas', 'maint_image_cleanup_run' => 'Executar Limpeza', 'maint_image_cleanup_warning' => ':count imagens potencialmente não utilizadas foram encontradas. Tem certeza de que deseja eliminar estas imagens?', @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Excluir Cargo', 'role_delete_confirm' => 'A ação vai eliminar o cargo de nome \':roleName\'.', 'role_delete_users_assigned' => 'Esse cargo tem :userCount utilizadores vinculados nele. Se quiser migrar utilizadores deste cargo para outro, selecione um novo cargo.', - 'role_delete_no_migration' => "Não migrar utilizadores", + 'role_delete_no_migration' => 'Não migrar utilizadores', 'role_delete_sure' => 'Tem certeza que deseja excluir este cargo?', 'role_delete_success' => 'Cargo excluído com sucesso', 'role_edit' => 'Editar Cargo', @@ -273,6 +273,6 @@ return [ 'vi' => 'Tiếng Việt', 'zh_CN' => '简体中文', 'zh_TW' => '繁體中文', - ] + ], //!//////////////////////////////// ]; diff --git a/resources/lang/pt_BR/auth.php b/resources/lang/pt_BR/auth.php index a5f0c18bc..707bea034 100644 --- a/resources/lang/pt_BR/auth.php +++ b/resources/lang/pt_BR/auth.php @@ -38,7 +38,6 @@ return [ 'registration_email_domain_invalid' => 'O domínio de e-mail usado não tem acesso permitido a essa aplicação', 'register_success' => 'Obrigado por se cadastrar! Você agora encontra-se cadastrado(a) e logado(a).', - // Password Reset 'reset_password' => 'Redefinir Senha', 'reset_password_send_instructions' => 'Insira seu e-mail abaixo e uma mensagem com o link de redefinição de senha lhe será enviada.', @@ -49,7 +48,6 @@ return [ 'email_reset_text' => 'Você recebeu esse e-mail pois recebemos uma solicitação de redefinição de senha para a sua conta.', 'email_reset_not_requested' => 'Caso não tenha sido você a solicitar a redefinição de senha, ignore esse e-mail.', - // Email Confirmation 'email_confirm_subject' => 'Confirme seu e-mail para :appName', 'email_confirm_greeting' => 'Obrigado por se cadastrar em :appName!', @@ -109,4 +107,4 @@ return [ 'mfa_verify_backup_code_enter_here' => 'Enter backup code here', 'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:', 'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.', -]; \ No newline at end of file +]; diff --git a/resources/lang/pt_BR/common.php b/resources/lang/pt_BR/common.php index 1435a380d..5a3fa2528 100644 --- a/resources/lang/pt_BR/common.php +++ b/resources/lang/pt_BR/common.php @@ -20,7 +20,7 @@ return [ 'role' => 'Cargo', 'cover_image' => 'Imagem de capa', 'cover_image_description' => 'Esta imagem deve ser aproximadamente 440x250px.', - + // Actions 'actions' => 'Ações', 'view' => 'Visualizar', diff --git a/resources/lang/pt_BR/entities.php b/resources/lang/pt_BR/entities.php index 14ce2a832..fc4119932 100644 --- a/resources/lang/pt_BR/entities.php +++ b/resources/lang/pt_BR/entities.php @@ -321,5 +321,5 @@ return [ 'revision_delete_confirm' => 'Tem certeza de que deseja excluir esta revisão?', 'revision_restore_confirm' => 'Tem certeza que deseja restaurar esta revisão? O conteúdo atual da página será substituído.', 'revision_delete_success' => 'Revisão excluída', - 'revision_cannot_delete_latest' => 'Não é possível excluir a revisão mais recente.' + 'revision_cannot_delete_latest' => 'Não é possível excluir a revisão mais recente.', ]; diff --git a/resources/lang/pt_BR/passwords.php b/resources/lang/pt_BR/passwords.php index fde9e2937..8343ad57a 100644 --- a/resources/lang/pt_BR/passwords.php +++ b/resources/lang/pt_BR/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'Senhas devem ter ao menos oito caracteres e ser iguais à confirmação.', - 'user' => "Não pudemos encontrar um usuário com o e-mail fornecido.", + 'user' => 'Não pudemos encontrar um usuário com o e-mail fornecido.', 'token' => 'O token de redefinição de senha é inválido para este endereço de e-mail.', 'sent' => 'Enviamos o link de redefinição de senha para o seu e-mail!', 'reset' => 'Sua senha foi redefinida com sucesso!', diff --git a/resources/lang/pt_BR/settings.php b/resources/lang/pt_BR/settings.php index e2d29f459..b73a006e8 100644 --- a/resources/lang/pt_BR/settings.php +++ b/resources/lang/pt_BR/settings.php @@ -72,7 +72,7 @@ return [ // Maintenance settings 'maint' => 'Manutenção', 'maint_image_cleanup' => 'Limpeza de Imagens', - 'maint_image_cleanup_desc' => "Examina páginas e revisa seus conteúdos para verificar quais imagens e desenhos estão atualmente em uso e quais são redundantes. Certifique-se de criar um backup completo do banco de dados e imagens antes de executar esta ação.", + 'maint_image_cleanup_desc' => 'Examina páginas e revisa seus conteúdos para verificar quais imagens e desenhos estão atualmente em uso e quais são redundantes. Certifique-se de criar um backup completo do banco de dados e imagens antes de executar esta ação.', 'maint_delete_images_only_in_revisions' => 'Também excluir imagens que existem apenas em revisões de página antigas', 'maint_image_cleanup_run' => 'Executar Limpeza', 'maint_image_cleanup_warning' => ':count imagens potencialmente não utilizadas foram encontradas. Tem certeza de que deseja excluir estas imagens?', @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Excluir Cargo', 'role_delete_confirm' => 'A ação vai excluír o cargo de nome \':roleName\'.', 'role_delete_users_assigned' => 'Esse cargo tem :userCount usuários vinculados a ele. Se quiser migrar usuários desse cargo para outro, selecione um novo cargo.', - 'role_delete_no_migration' => "Não migre os usuários", + 'role_delete_no_migration' => 'Não migre os usuários', 'role_delete_sure' => 'Tem certeza que deseja excluir esse cargo?', 'role_delete_success' => 'Cargo excluído com sucesso', 'role_edit' => 'Editar Cargo', @@ -273,6 +273,6 @@ return [ 'vi' => 'Tiếng Việt', 'zh_CN' => '简体中文', 'zh_TW' => '繁體中文', - ] + ], //!//////////////////////////////// ]; diff --git a/resources/lang/ru/auth.php b/resources/lang/ru/auth.php index 8410e40e4..69b0b20d3 100644 --- a/resources/lang/ru/auth.php +++ b/resources/lang/ru/auth.php @@ -38,7 +38,6 @@ return [ 'registration_email_domain_invalid' => 'Данный домен электронной почты недоступен для регистрации', 'register_success' => 'Спасибо за регистрацию! Регистрация и вход в систему выполнены.', - // Password Reset 'reset_password' => 'Сброс пароля', 'reset_password_send_instructions' => 'Введите свой адрес электронной почты ниже, и вам будет отправлено письмо со ссылкой для сброса пароля.', @@ -49,7 +48,6 @@ return [ 'email_reset_text' => 'Вы получили это письмо, потому что запросили сброс пароля для вашей учетной записи.', 'email_reset_not_requested' => 'Если вы не запрашивали сброса пароля, то никаких дополнительных действий не требуется.', - // Email Confirmation 'email_confirm_subject' => 'Подтвердите ваш почтовый адрес на :appName', 'email_confirm_greeting' => 'Благодарим за участие :appName!', @@ -109,4 +107,4 @@ return [ 'mfa_verify_backup_code_enter_here' => 'Введите резервный код', 'mfa_verify_totp_desc' => 'Введите код, сгенерированный с помощью мобильного приложения, ниже:', 'mfa_setup_login_notification' => 'Двухфакторный метод настроен, пожалуйста, войдите снова, используя сконфигурированный метод.', -]; \ No newline at end of file +]; diff --git a/resources/lang/ru/common.php b/resources/lang/ru/common.php index 6e2a31931..8b6fbda73 100644 --- a/resources/lang/ru/common.php +++ b/resources/lang/ru/common.php @@ -20,7 +20,7 @@ return [ 'role' => 'Роль', 'cover_image' => 'Обложка', 'cover_image_description' => 'Изображение должно быть размером около 440x250px.', - + // Actions 'actions' => 'Действия', 'view' => 'Просмотр', diff --git a/resources/lang/ru/entities.php b/resources/lang/ru/entities.php index 0bcb7c1d4..d5418955c 100644 --- a/resources/lang/ru/entities.php +++ b/resources/lang/ru/entities.php @@ -255,7 +255,7 @@ return [ 'tags' => 'Теги', 'tag_name' => 'Имя тега', 'tag_value' => 'Значение тега (опционально)', - 'tags_explain' => "Добавьте теги, чтобы лучше классифицировать ваш контент. \\n Вы можете присвоить значение тегу для более глубокой организации.", + 'tags_explain' => 'Добавьте теги, чтобы лучше классифицировать ваш контент. \\n Вы можете присвоить значение тегу для более глубокой организации.', 'tags_add' => 'Добавить тег', 'tags_remove' => 'Удалить этот тег', 'attachments' => 'Вложения', @@ -321,5 +321,5 @@ return [ 'revision_delete_confirm' => 'Удалить эту версию?', 'revision_restore_confirm' => 'Вы уверены, что хотите восстановить эту версию? Текущее содержимое страницы будет заменено.', 'revision_delete_success' => 'Версия удалена', - 'revision_cannot_delete_latest' => 'Нельзя удалить последнюю версию.' + 'revision_cannot_delete_latest' => 'Нельзя удалить последнюю версию.', ]; diff --git a/resources/lang/ru/errors.php b/resources/lang/ru/errors.php index 1edef426c..ae7bac814 100644 --- a/resources/lang/ru/errors.php +++ b/resources/lang/ru/errors.php @@ -28,7 +28,7 @@ return [ 'oidc_no_email_address' => 'Could not find an email address, for this user, in the data provided by the external authentication system', 'oidc_fail_authed' => 'Login using :system failed, system did not provide successful authorization', 'social_no_action_defined' => 'Действие не определено', - 'social_login_bad_response' => "При попытке входа с :socialAccount произошла ошибка: \\n:error", + 'social_login_bad_response' => 'При попытке входа с :socialAccount произошла ошибка: \\n:error', 'social_account_in_use' => 'Этот :socialAccount аккаунт уже используется, попробуйте войти с параметрами :socialAccount.', 'social_account_email_in_use' => 'Электронный ящик :email уже используется. Если у вас уже есть учетная запись, вы можете подключить свою учетную запись :socialAccount из настроек своего профиля.', 'social_account_existing' => 'Этот :socialAccount уже привязан к вашему профилю.', diff --git a/resources/lang/ru/passwords.php b/resources/lang/ru/passwords.php index 433c70454..6880c0db6 100644 --- a/resources/lang/ru/passwords.php +++ b/resources/lang/ru/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'Пароль должен содержать не менее восьми символов и совпадать с подтверждением.', - 'user' => "Пользователя с данным адресом электронной почты не существует.", + 'user' => 'Пользователя с данным адресом электронной почты не существует.', 'token' => 'Токен сброса пароля недействителен для этого адреса электронной почты.', 'sent' => 'Ссылка для сброса пароля отправлена на вашу почту!', 'reset' => 'Ваш пароль был сброшен!', diff --git a/resources/lang/ru/settings.php b/resources/lang/ru/settings.php index cfa802f34..79c5d90c6 100755 --- a/resources/lang/ru/settings.php +++ b/resources/lang/ru/settings.php @@ -72,7 +72,7 @@ return [ // Maintenance settings 'maint' => 'Обслуживание', 'maint_image_cleanup' => 'Очистка изображений', - 'maint_image_cleanup_desc' => "Сканирует содержимое страниц и предыдущих версий и определяет изображения, которые не используются. Убедитесь, что у вас есть резервная копия базы данных и папки изображений перед запуском этой функции.", + 'maint_image_cleanup_desc' => 'Сканирует содержимое страниц и предыдущих версий и определяет изображения, которые не используются. Убедитесь, что у вас есть резервная копия базы данных и папки изображений перед запуском этой функции.', 'maint_delete_images_only_in_revisions' => 'Также удалять изображения, которые существуют только в старой версии страницы', 'maint_image_cleanup_run' => 'Выполнить очистку', 'maint_image_cleanup_warning' => 'Найдено :count возможно бесполезных изображений. Вы уверены, что хотите удалить эти изображения?', @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Удалить роль', 'role_delete_confirm' => 'Это удалит роль с именем \':roleName\'.', 'role_delete_users_assigned' => 'Эта роль назначена :userCount пользователям. Если вы хотите перенести их, выберите новую роль ниже.', - 'role_delete_no_migration' => "Не переносить пользователей", + 'role_delete_no_migration' => 'Не переносить пользователей', 'role_delete_sure' => 'Вы уверены что хотите удалить данную роль?', 'role_delete_success' => 'Роль успешно удалена', 'role_edit' => 'Редактировать роль', @@ -273,6 +273,6 @@ return [ 'vi' => 'Tiếng Việt', 'zh_CN' => '简体中文', 'zh_TW' => '繁體中文', - ] + ], //!//////////////////////////////// ]; diff --git a/resources/lang/sk/auth.php b/resources/lang/sk/auth.php index f79e79cca..cb978baf5 100644 --- a/resources/lang/sk/auth.php +++ b/resources/lang/sk/auth.php @@ -38,7 +38,6 @@ return [ 'registration_email_domain_invalid' => 'Táto e-mailová doména nemá prístup k tejto aplikácii', 'register_success' => 'Ďakujeme za registráciu! Teraz ste registrovaný a prihlásený.', - // Password Reset 'reset_password' => 'Resetovanie hesla', 'reset_password_send_instructions' => 'Nižšie zadajte svoj e-mail, na ktorý Vám zašleme odkaz pre resetovanie hesla.', @@ -49,7 +48,6 @@ return [ 'email_reset_text' => 'Tento e-mail ste obdržali, pretože sme dostali požiadavku na resetovanie hesla pre Váš účet.', 'email_reset_not_requested' => 'Ak ste nepožiadali o resetovanie hesla, nemusíte robiť nič.', - // Email Confirmation 'email_confirm_subject' => 'Potvrdiť e-mail na :appName', 'email_confirm_greeting' => 'Ďakujeme, že ste sa pridali k :appName!', @@ -109,4 +107,4 @@ return [ 'mfa_verify_backup_code_enter_here' => 'Zadajte záložný kód', 'mfa_verify_totp_desc' => 'Zadajte kód vygenerovaný vašou mobilnou aplikáciou:', 'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.', -]; \ No newline at end of file +]; diff --git a/resources/lang/sk/common.php b/resources/lang/sk/common.php index b9913db59..f84e62989 100644 --- a/resources/lang/sk/common.php +++ b/resources/lang/sk/common.php @@ -20,7 +20,7 @@ return [ 'role' => 'Rola', 'cover_image' => 'Obal knihy', 'cover_image_description' => 'Tento obrázok by mal byť približne 300 x 170 pixelov.', - + // Actions 'actions' => 'Akcie', 'view' => 'Zobraziť', diff --git a/resources/lang/sk/entities.php b/resources/lang/sk/entities.php index e7531795f..114421118 100644 --- a/resources/lang/sk/entities.php +++ b/resources/lang/sk/entities.php @@ -321,5 +321,5 @@ return [ 'revision_delete_confirm' => 'Naozaj chcete túto revíziu odstrániť?', 'revision_restore_confirm' => 'Naozaj chcete obnoviť túto revíziu? Aktuálny obsah stránky sa nahradí.', 'revision_delete_success' => 'Revízia bola vymazaná', - 'revision_cannot_delete_latest' => 'Nie je možné vymazať poslednú revíziu.' + 'revision_cannot_delete_latest' => 'Nie je možné vymazať poslednú revíziu.', ]; diff --git a/resources/lang/sk/passwords.php b/resources/lang/sk/passwords.php index 5b80f62da..9894b91b3 100644 --- a/resources/lang/sk/passwords.php +++ b/resources/lang/sk/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'Heslo musí obsahovať aspoň osem znakov a musí byť rovnaké ako potvrdzujúce.', - 'user' => "Nenašli sme používateľa s takou emailovou adresou.", + 'user' => 'Nenašli sme používateľa s takou emailovou adresou.', 'token' => 'Token na obnovenie hesla je pre túto e-mailovú adresu neplatný.', 'sent' => 'Poslali sme Vám email s odkazom na reset hesla!', 'reset' => 'Vaše heslo bolo resetované!', diff --git a/resources/lang/sk/settings.php b/resources/lang/sk/settings.php index 875239aca..b738c9465 100644 --- a/resources/lang/sk/settings.php +++ b/resources/lang/sk/settings.php @@ -72,7 +72,7 @@ return [ // Maintenance settings 'maint' => 'Údržba', 'maint_image_cleanup' => 'Prečistenie obrázkov', - 'maint_image_cleanup_desc' => "Scans page & revision content to check which images and drawings are currently in use and which images are redundant. Ensure you create a full database and image backup before running this.", + 'maint_image_cleanup_desc' => 'Scans page & revision content to check which images and drawings are currently in use and which images are redundant. Ensure you create a full database and image backup before running this.', 'maint_delete_images_only_in_revisions' => 'Also delete images that only exist in old page revisions', 'maint_image_cleanup_run' => 'Spustiť prečistenie', 'maint_image_cleanup_warning' => ':count potentially unused images were found. Are you sure you want to delete these images?', @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Zmazať rolu', 'role_delete_confirm' => 'Toto zmaže rolu menom \':roleName\'.', 'role_delete_users_assigned' => 'Túto rolu má priradenú :userCount používateľov. Ak chcete premigrovať používateľov z tejto roly, vyberte novú rolu nižšie.', - 'role_delete_no_migration' => "Nemigrovať používateľov", + 'role_delete_no_migration' => 'Nemigrovať používateľov', 'role_delete_sure' => 'Ste si istý, že chcete zmazať túto rolu?', 'role_delete_success' => 'Rola úspešne zmazaná', 'role_edit' => 'Upraviť rolu', @@ -273,6 +273,6 @@ return [ 'vi' => 'Tiếng Việt', 'zh_CN' => '简体中文', 'zh_TW' => '繁體中文', - ] + ], //!//////////////////////////////// ]; diff --git a/resources/lang/sl/auth.php b/resources/lang/sl/auth.php index b6c41666a..77203cde9 100644 --- a/resources/lang/sl/auth.php +++ b/resources/lang/sl/auth.php @@ -38,7 +38,6 @@ return [ 'registration_email_domain_invalid' => 'Ta e-poštna domena nima dostopa do te aplikacije', 'register_success' => 'Hvala za registracijo! Sedaj ste registrirani in prijavljeni.', - // Password Reset 'reset_password' => 'Ponastavi geslo', 'reset_password_send_instructions' => 'Spodaj vpišite vaš e-poštni naslov in prejeli boste e-pošto s povezavo za ponastavitev gesla.', @@ -49,7 +48,6 @@ return [ 'email_reset_text' => 'To e-poštno sporočilo ste prejeli, ker smo prejeli zahtevo za ponastavitev gesla za vaš račun.', 'email_reset_not_requested' => 'Če niste zahtevali ponastavitve gesla, vam ni potrebno ničesar storiti.', - // Email Confirmation 'email_confirm_subject' => 'Potrdi svojo e-pošto za :appName', 'email_confirm_greeting' => 'Hvala ker ste se pridružili :appName!', @@ -109,4 +107,4 @@ return [ 'mfa_verify_backup_code_enter_here' => 'Enter backup code here', 'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:', 'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.', -]; \ No newline at end of file +]; diff --git a/resources/lang/sl/common.php b/resources/lang/sl/common.php index 9f478e75d..d58467ecf 100644 --- a/resources/lang/sl/common.php +++ b/resources/lang/sl/common.php @@ -20,7 +20,7 @@ return [ 'role' => 'Vloga', 'cover_image' => 'Naslovna slika', 'cover_image_description' => 'Slika naj bo velika približno 440x250px.', - + // Actions 'actions' => 'Dejanja', 'view' => 'Pogled', diff --git a/resources/lang/sl/entities.php b/resources/lang/sl/entities.php index 4ad1aea00..e524d4140 100644 --- a/resources/lang/sl/entities.php +++ b/resources/lang/sl/entities.php @@ -321,5 +321,5 @@ return [ 'revision_delete_confirm' => 'Ali ste prepričani, da želite izbrisati to revizijo?', 'revision_restore_confirm' => 'Ali ste prepričani da želite obnoviti to revizijo? Vsebina trenutne strani bo zamenjana.', 'revision_delete_success' => 'Revizija izbrisana', - 'revision_cannot_delete_latest' => 'Ne morem izbrisati zadnje revizije.' + 'revision_cannot_delete_latest' => 'Ne morem izbrisati zadnje revizije.', ]; diff --git a/resources/lang/sl/passwords.php b/resources/lang/sl/passwords.php index e9e195fe9..4a3b791b5 100644 --- a/resources/lang/sl/passwords.php +++ b/resources/lang/sl/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'Gesla morajo biti najmanj osem znakov dolga in se morajo ujemati s potrditvijo.', - 'user' => "Ne moremo najti uporabnika s tem e-poštnim naslovom.", + 'user' => 'Ne moremo najti uporabnika s tem e-poštnim naslovom.', 'token' => 'Žeton za ponastavitev gesla ni veljaven za ta e-poštni naslov.', 'sent' => 'Poslali smo vam povezavo za ponastavitev gesla!', 'reset' => 'Vaše geslo je bilo ponastavljeno!', diff --git a/resources/lang/sl/settings.php b/resources/lang/sl/settings.php index a25488d15..c0f636456 100644 --- a/resources/lang/sl/settings.php +++ b/resources/lang/sl/settings.php @@ -72,7 +72,7 @@ return [ // Maintenance settings 'maint' => 'Vzdrževanje', 'maint_image_cleanup' => 'Odstrani /počisti slike', - 'maint_image_cleanup_desc' => "Pregleda vsebino strani in revizij ter ugotovi, katere slike in risbe so v uporabi in katere so odvečne. Preden to poženeš, naredi popolno varnostno kopijo podatkovne zbirke in slik.", + 'maint_image_cleanup_desc' => 'Pregleda vsebino strani in revizij ter ugotovi, katere slike in risbe so v uporabi in katere so odvečne. Preden to poženeš, naredi popolno varnostno kopijo podatkovne zbirke in slik.', 'maint_delete_images_only_in_revisions' => 'Izbriši tudi slike, ki obstajajo le v starih različicah strani', 'maint_image_cleanup_run' => 'Zaženi čiščenje', 'maint_image_cleanup_warning' => 'Najdenih je bilo :count verjetno neuporabljenih slik. Ali si prepričan, da želiš odstraniti izbrane slike?', @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Brisanje vloge', 'role_delete_confirm' => 'Izbrisana bo vloga z imenom \':roleName\'.', 'role_delete_users_assigned' => 'Ta vloga ima dodeljenih :userCount uporabnikov. V kolikor želite uporabnike preseliti iz te vloge, spodaj izberite novo vlogo.', - 'role_delete_no_migration' => "Ne prenašaj uporabnikov", + 'role_delete_no_migration' => 'Ne prenašaj uporabnikov', 'role_delete_sure' => 'Ali ste prepričani, da želite izbrisati to vlogo?', 'role_delete_success' => 'Vloga uspešno izbrisana', 'role_edit' => 'Uredi vlogo', @@ -274,6 +274,6 @@ return [ 'vi' => 'Tiếng Việt', 'zh_CN' => '简体中文', 'zh_TW' => '繁體中文', - ] + ], //!//////////////////////////////// ]; diff --git a/resources/lang/sv/auth.php b/resources/lang/sv/auth.php index 1d1a81c74..2cf218b5a 100644 --- a/resources/lang/sv/auth.php +++ b/resources/lang/sv/auth.php @@ -38,7 +38,6 @@ return [ 'registration_email_domain_invalid' => 'Den e-postadressen har inte tillgång till den här applikationen', 'register_success' => 'Tack för din registrering! Du är nu registerad och inloggad.', - // Password Reset 'reset_password' => 'Återställ lösenord', 'reset_password_send_instructions' => 'Ange din e-postadress nedan så skickar vi ett mail med en länk för att återställa ditt lösenord.', @@ -49,7 +48,6 @@ return [ 'email_reset_text' => 'Du får detta mail eftersom vi fått en begäran om att återställa lösenordet till ditt konto.', 'email_reset_not_requested' => 'Om du inte begärt att få ditt lösenord återställt behöver du inte göra någonting', - // Email Confirmation 'email_confirm_subject' => 'Bekräfta din e-post på :appName', 'email_confirm_greeting' => 'Tack för att du gått med i :appName!', @@ -109,4 +107,4 @@ return [ 'mfa_verify_backup_code_enter_here' => 'Enter backup code here', 'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:', 'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.', -]; \ No newline at end of file +]; diff --git a/resources/lang/sv/common.php b/resources/lang/sv/common.php index 177a8abef..3be74d566 100644 --- a/resources/lang/sv/common.php +++ b/resources/lang/sv/common.php @@ -20,7 +20,7 @@ return [ 'role' => 'Roll', 'cover_image' => 'Omslagsbild', 'cover_image_description' => 'Bilden bör vara cirka 440x250px stor.', - + // Actions 'actions' => 'Åtgärder', 'view' => 'Visa', diff --git a/resources/lang/sv/entities.php b/resources/lang/sv/entities.php index 80eb570c9..1eadf1f74 100644 --- a/resources/lang/sv/entities.php +++ b/resources/lang/sv/entities.php @@ -321,5 +321,5 @@ return [ 'revision_delete_confirm' => 'Är du säker på att du vill radera den här versionen?', 'revision_restore_confirm' => 'Är du säker på att du vill använda denna revision? Det nuvarande innehållet kommer att ersättas.', 'revision_delete_success' => 'Revisionen raderad', - 'revision_cannot_delete_latest' => 'Det går inte att ta bort den senaste versionen.' + 'revision_cannot_delete_latest' => 'Det går inte att ta bort den senaste versionen.', ]; diff --git a/resources/lang/sv/passwords.php b/resources/lang/sv/passwords.php index 640309b88..9bd8dbc02 100644 --- a/resources/lang/sv/passwords.php +++ b/resources/lang/sv/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'Lösenord måste vara minst sex tecken långa och anges likadant två gånger.', - 'user' => "Det finns ingen användare med den e-postadressen.", + 'user' => 'Det finns ingen användare med den e-postadressen.', 'token' => 'Lösenordsåterställningstoken är ogiltig för denna e-postadress.', 'sent' => 'Vi har mailat dig en länk för att återställa ditt lösenord!', 'reset' => 'Ditt lösenord har blivit återställt!', diff --git a/resources/lang/sv/settings.php b/resources/lang/sv/settings.php index 9065407f7..61326e496 100644 --- a/resources/lang/sv/settings.php +++ b/resources/lang/sv/settings.php @@ -72,7 +72,7 @@ return [ // Maintenance settings 'maint' => 'Underhåll', 'maint_image_cleanup' => 'Rensa bilder', - 'maint_image_cleanup_desc' => "Söker igenom innehåll i sidor & revisioner för att se vilka bilder och teckningar som är i bruk och vilka som är överflödiga. Se till att ta en komplett backup av databas och bilder innan du kör detta.", + 'maint_image_cleanup_desc' => 'Söker igenom innehåll i sidor & revisioner för att se vilka bilder och teckningar som är i bruk och vilka som är överflödiga. Se till att ta en komplett backup av databas och bilder innan du kör detta.', 'maint_delete_images_only_in_revisions' => 'Ta också bort bilder som bara finns i gamla sidrevideringar', 'maint_image_cleanup_run' => 'Kör rensning', 'maint_image_cleanup_warning' => 'Hittade :count bilder som potentiellt inte används. Vill du verkligen ta bort dessa bilder?', @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Ta bort roll', 'role_delete_confirm' => 'Rollen med namn \':roleName\' kommer att tas bort.', 'role_delete_users_assigned' => 'Det finns :userCount användare som tillhör den här rollen. Om du vill migrera användarna från den här rollen, välj en ny roll nedan.', - 'role_delete_no_migration' => "Migrera inte användare", + 'role_delete_no_migration' => 'Migrera inte användare', 'role_delete_sure' => 'Är du säker på att du vill ta bort den här rollen?', 'role_delete_success' => 'Rollen har tagits bort', 'role_edit' => 'Redigera roll', @@ -273,6 +273,6 @@ return [ 'vi' => 'Tiếng Việt', 'zh_CN' => '简体中文', 'zh_TW' => '繁體中文', - ] + ], //!//////////////////////////////// ]; diff --git a/resources/lang/th/auth.php b/resources/lang/th/auth.php index d64fce93a..8ff408021 100644 --- a/resources/lang/th/auth.php +++ b/resources/lang/th/auth.php @@ -38,7 +38,6 @@ return [ 'registration_email_domain_invalid' => 'That email domain does not have access to this application', 'register_success' => 'Thanks for signing up! You are now registered and signed in.', - // Password Reset 'reset_password' => 'Reset Password', 'reset_password_send_instructions' => 'Enter your email below and you will be sent an email with a password reset link.', @@ -49,7 +48,6 @@ return [ 'email_reset_text' => 'You are receiving this email because we received a password reset request for your account.', 'email_reset_not_requested' => 'If you did not request a password reset, no further action is required.', - // Email Confirmation 'email_confirm_subject' => 'Confirm your email on :appName', 'email_confirm_greeting' => 'Thanks for joining :appName!', @@ -73,5 +71,5 @@ return [ 'user_invite_page_welcome' => 'Welcome to :appName!', 'user_invite_page_text' => 'To finalise your account and gain access you need to set a password which will be used to log-in to :appName on future visits.', 'user_invite_page_confirm_button' => 'Confirm Password', - 'user_invite_success' => 'Password set, you now have access to :appName!' -]; \ No newline at end of file + 'user_invite_success' => 'Password set, you now have access to :appName!', +]; diff --git a/resources/lang/th/common.php b/resources/lang/th/common.php index e87bd11a5..e3bec6837 100644 --- a/resources/lang/th/common.php +++ b/resources/lang/th/common.php @@ -20,7 +20,7 @@ return [ 'role' => 'Role', 'cover_image' => 'Cover image', 'cover_image_description' => 'This image should be approx 440x250px.', - + // Actions 'actions' => 'Actions', 'view' => 'View', diff --git a/resources/lang/th/entities.php b/resources/lang/th/entities.php index f64867a56..67c451319 100644 --- a/resources/lang/th/entities.php +++ b/resources/lang/th/entities.php @@ -312,5 +312,5 @@ return [ 'revision_delete_confirm' => 'Are you sure you want to delete this revision?', 'revision_restore_confirm' => 'Are you sure you want to restore this revision? The current page contents will be replaced.', 'revision_delete_success' => 'Revision deleted', - 'revision_cannot_delete_latest' => 'Cannot delete the latest revision.' -]; \ No newline at end of file + 'revision_cannot_delete_latest' => 'Cannot delete the latest revision.', +]; diff --git a/resources/lang/th/settings.php b/resources/lang/th/settings.php index 2bd314cf0..c2e4ee734 100644 --- a/resources/lang/th/settings.php +++ b/resources/lang/th/settings.php @@ -67,7 +67,7 @@ return [ // Maintenance settings 'maint' => 'Maintenance', 'maint_image_cleanup' => 'Cleanup Images', - 'maint_image_cleanup_desc' => "Scans page & revision content to check which images and drawings are currently in use and which images are redundant. Ensure you create a full database and image backup before running this.", + 'maint_image_cleanup_desc' => 'Scans page & revision content to check which images and drawings are currently in use and which images are redundant. Ensure you create a full database and image backup before running this.', 'maint_image_cleanup_ignore_revisions' => 'Ignore images in revisions', 'maint_image_cleanup_run' => 'Run Cleanup', 'maint_image_cleanup_warning' => ':count potentially unused images were found. Are you sure you want to delete these images?', @@ -224,6 +224,6 @@ return [ 'vi' => 'Tiếng Việt', 'zh_CN' => '简体中文', 'zh_TW' => '繁體中文', - ] + ], //!//////////////////////////////// ]; diff --git a/resources/lang/tr/auth.php b/resources/lang/tr/auth.php index 0ce90d4d0..62c7653bf 100644 --- a/resources/lang/tr/auth.php +++ b/resources/lang/tr/auth.php @@ -38,7 +38,6 @@ return [ 'registration_email_domain_invalid' => 'Bu e-posta sağlayıcısının uygulamaya erişim izni bulunmuyor', 'register_success' => 'Kaydolduğunuz için teşekkürler! Artık kayıtlı bir kullanıcı olarak giriş yaptınız.', - // Password Reset 'reset_password' => 'Şifreyi Sıfırla', 'reset_password_send_instructions' => 'Aşağıya gireceğiniz e-posta adresine şifre sıfırlama bağlantısı gönderilecektir.', @@ -49,7 +48,6 @@ return [ 'email_reset_text' => 'Hesap şifrenizi sıfırlama isteğinde bulunduğunuz için bu e-postayı aldınız.', 'email_reset_not_requested' => 'Şifre sıfırlama isteğinde bulunmadıysanız herhangi bir işlem yapmanıza gerek yoktur.', - // Email Confirmation 'email_confirm_subject' => ':appName için girdiğiniz e-posta adresini doğrulayın', 'email_confirm_greeting' => ':appName uygulamasına katıldığınız için teşekkürler!', @@ -109,4 +107,4 @@ return [ 'mfa_verify_backup_code_enter_here' => 'Enter backup code here', 'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:', 'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.', -]; \ No newline at end of file +]; diff --git a/resources/lang/tr/common.php b/resources/lang/tr/common.php index 1f19a62f4..add3767af 100644 --- a/resources/lang/tr/common.php +++ b/resources/lang/tr/common.php @@ -20,7 +20,7 @@ return [ 'role' => 'Rol', 'cover_image' => 'Kapak resmi', 'cover_image_description' => 'Bu görsel yaklaşık 440x250px boyutlarında olmalıdır.', - + // Actions 'actions' => 'İşlemler', 'view' => 'Görüntüle', diff --git a/resources/lang/tr/entities.php b/resources/lang/tr/entities.php index 9b0a15c5d..c562ec824 100644 --- a/resources/lang/tr/entities.php +++ b/resources/lang/tr/entities.php @@ -255,7 +255,7 @@ return [ 'tags' => 'Etiketler', 'tag_name' => 'Etiket İsmi', 'tag_value' => 'Etiket Değeri (Opsiyonel)', - 'tags_explain' => "İçeriğinizi daha iyi kategorize etmek için etiket ekleyin. Etiketlere değer atayarak daha derinlemesine bir düzen elde edebilirsiniz.", + 'tags_explain' => 'İçeriğinizi daha iyi kategorize etmek için etiket ekleyin. Etiketlere değer atayarak daha derinlemesine bir düzen elde edebilirsiniz.', 'tags_add' => 'Başka etiket ekle', 'tags_remove' => 'Bu etiketi sil', 'attachments' => 'Ekler', @@ -321,5 +321,5 @@ return [ 'revision_delete_confirm' => 'Bu revizyonu silmek istediğinize emin misiniz?', 'revision_restore_confirm' => 'Bu revizyonu yeniden yüklemek istediğinize emin misiniz? Sayfanın şu anki içeriği değiştirilecektir.', 'revision_delete_success' => 'Revizyon silindi', - 'revision_cannot_delete_latest' => 'Son revizyonu silemezsiniz.' + 'revision_cannot_delete_latest' => 'Son revizyonu silemezsiniz.', ]; diff --git a/resources/lang/tr/passwords.php b/resources/lang/tr/passwords.php index ba1fd913f..890f2d628 100644 --- a/resources/lang/tr/passwords.php +++ b/resources/lang/tr/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'Şifreniz en az 6 karakterden oluşmalı ve her iki şifre de birbiri ile eşleşmelidir.', - 'user' => "Bu e-posta adresine sahip bir kullanıcı bulamadık.", + 'user' => 'Bu e-posta adresine sahip bir kullanıcı bulamadık.', 'token' => 'Şifre sıfırlama anahtarı, bu e-posta adresi için geçersizdir.', 'sent' => 'Şifre sıfırlama bağlantısını e-posta adresinize gönderdik!', 'reset' => 'Şifreniz sıfırlandı!', diff --git a/resources/lang/tr/settings.php b/resources/lang/tr/settings.php index b95f28b39..766e01fad 100755 --- a/resources/lang/tr/settings.php +++ b/resources/lang/tr/settings.php @@ -72,7 +72,7 @@ return [ // Maintenance settings 'maint' => 'Bakım', 'maint_image_cleanup' => 'Görselleri Temizle', - 'maint_image_cleanup_desc' => "Sayfaları ve revizyon içeriklerini tarayarak hangi görsellerin ve çizimlerin kullanımda olduğunu ve hangilerinin gereksiz olduğunu tespit eder. Bunu başlatmadan önce veritabanının ve görsellerin tam bir yedeğinin alındığından emin olun.", + 'maint_image_cleanup_desc' => 'Sayfaları ve revizyon içeriklerini tarayarak hangi görsellerin ve çizimlerin kullanımda olduğunu ve hangilerinin gereksiz olduğunu tespit eder. Bunu başlatmadan önce veritabanının ve görsellerin tam bir yedeğinin alındığından emin olun.', 'maint_delete_images_only_in_revisions' => 'Eski sayfa revizyonlarındaki görselleri de sil', 'maint_image_cleanup_run' => 'Temizliği Başlat', 'maint_image_cleanup_warning' => 'Muhtemelen kullanılmayan :count adet görsel bulundu. Bu görselleri silmek istediğinize emin misiniz?', @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Rolü Sil', 'role_delete_confirm' => 'Bu işlem, \':roleName\' adlı rolü silecektir.', 'role_delete_users_assigned' => 'Bu role atanmış :userCount adet kullanıcı var. Eğer bu kullanıcıların rollerini değiştirmek istiyorsanız, aşağıdan yeni bir rol seçin.', - 'role_delete_no_migration' => "Kullanıcıları taşıma", + 'role_delete_no_migration' => 'Kullanıcıları taşıma', 'role_delete_sure' => 'Bu rolü silmek istediğinize emin misiniz?', 'role_delete_success' => 'Rol başarıyla silindi', 'role_edit' => 'Rolü Düzenle', @@ -273,6 +273,6 @@ return [ 'vi' => 'Tiếng Việt', 'zh_CN' => '简体中文', 'zh_TW' => '繁體中文', - ] + ], //!//////////////////////////////// ]; diff --git a/resources/lang/uk/auth.php b/resources/lang/uk/auth.php index 52625b60f..6bab87fc1 100644 --- a/resources/lang/uk/auth.php +++ b/resources/lang/uk/auth.php @@ -38,7 +38,6 @@ return [ 'registration_email_domain_invalid' => 'Цей домен електронної пошти заборонений для реєстрації', 'register_success' => 'Дякуємо за реєстрацію! Ви зареєстровані та ввійшли в систему.', - // Password Reset 'reset_password' => 'Скинути пароль', 'reset_password_send_instructions' => 'Введіть адресу електронної пошти нижче, і вам буде надіслано електронне повідомлення з посиланням на зміну пароля.', @@ -49,7 +48,6 @@ return [ 'email_reset_text' => 'Ви отримали цей електронний лист, оскільки до нас надійшов запит на скидання пароля для вашого облікового запису.', 'email_reset_not_requested' => 'Якщо ви не надсилали запит на скидання пароля, подальші дії не потрібні.', - // Email Confirmation 'email_confirm_subject' => 'Підтвердьте свою електронну пошту на :appName', 'email_confirm_greeting' => 'Дякуємо, що приєдналися до :appName!', @@ -109,4 +107,4 @@ return [ 'mfa_verify_backup_code_enter_here' => 'Enter backup code here', 'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:', 'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.', -]; \ No newline at end of file +]; diff --git a/resources/lang/uk/common.php b/resources/lang/uk/common.php index 734c566e5..f07f713c6 100644 --- a/resources/lang/uk/common.php +++ b/resources/lang/uk/common.php @@ -20,7 +20,7 @@ return [ 'role' => 'Роль', 'cover_image' => 'Обкладинка', 'cover_image_description' => 'Це зображення має бути приблизно 440x250px.', - + // Actions 'actions' => 'Дії', 'view' => 'Подивитись', diff --git a/resources/lang/uk/entities.php b/resources/lang/uk/entities.php index 6f9b4dae8..f5955c0e9 100644 --- a/resources/lang/uk/entities.php +++ b/resources/lang/uk/entities.php @@ -321,5 +321,5 @@ return [ 'revision_delete_confirm' => 'Ви впевнені, що хочете видалити цю версію?', 'revision_restore_confirm' => 'Дійсно відновити цю версію? Вміст поточної сторінки буде замінено.', 'revision_delete_success' => 'Версія видалена', - 'revision_cannot_delete_latest' => 'Неможливо видалити останню версію.' + 'revision_cannot_delete_latest' => 'Неможливо видалити останню версію.', ]; diff --git a/resources/lang/uk/passwords.php b/resources/lang/uk/passwords.php index 90c31777c..62a02073d 100644 --- a/resources/lang/uk/passwords.php +++ b/resources/lang/uk/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'Пароль повинен містити не менше восьми символів і збігатись з підтвердженням.', - 'user' => "Ми не можемо знайти користувача з цією адресою електронної пошти.", + 'user' => 'Ми не можемо знайти користувача з цією адресою електронної пошти.', 'token' => 'Токен скидання пароля недійсний для цієї адреси електронної пошти.', 'sent' => 'Ми надіслали Вам електронний лист із посиланням для скидання пароля!', 'reset' => 'Ваш пароль скинуто!', diff --git a/resources/lang/uk/settings.php b/resources/lang/uk/settings.php index 602fa9bcd..afdbd657d 100644 --- a/resources/lang/uk/settings.php +++ b/resources/lang/uk/settings.php @@ -72,7 +72,7 @@ return [ // Maintenance settings 'maint' => 'Обслуговування', 'maint_image_cleanup' => 'Очищення зображень', - 'maint_image_cleanup_desc' => "Сканує вміст сторінки та версій, щоб перевірити, які зображення та малюнки в даний час використовуються, а також які зображення зайві. Переконайтеся, що ви створили повну резервну копію бази даних та зображення, перш ніж запускати це.", + 'maint_image_cleanup_desc' => 'Сканує вміст сторінки та версій, щоб перевірити, які зображення та малюнки в даний час використовуються, а також які зображення зайві. Переконайтеся, що ви створили повну резервну копію бази даних та зображення, перш ніж запускати це.', 'maint_delete_images_only_in_revisions' => 'Також видалити зображення, що існують лише в старих версіях сторінки', 'maint_image_cleanup_run' => 'Запустити очищення', 'maint_image_cleanup_warning' => ':count потенційно невикористаних зображень було знайдено. Ви впевнені, що хочете видалити ці зображення?', @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Видалити роль', 'role_delete_confirm' => 'Це призведе до видалення ролі з назвою \':roleName\'.', 'role_delete_users_assigned' => 'Цій ролі належать :userCount користувачі(в). Якщо ви хочете перенести користувачів із цієї ролі, виберіть нову роль нижче.', - 'role_delete_no_migration' => "Не мігрувати користувачів", + 'role_delete_no_migration' => 'Не мігрувати користувачів', 'role_delete_sure' => 'Ви впевнені, що хочете видалити цю роль?', 'role_delete_success' => 'Роль успішно видалена', 'role_edit' => 'Редагувати роль', @@ -273,6 +273,6 @@ return [ 'vi' => 'Tiếng Việt', 'zh_CN' => '简体中文', 'zh_TW' => '繁體中文', - ] + ], //!//////////////////////////////// ]; diff --git a/resources/lang/vi/auth.php b/resources/lang/vi/auth.php index e95d26ac6..0475570dd 100644 --- a/resources/lang/vi/auth.php +++ b/resources/lang/vi/auth.php @@ -38,7 +38,6 @@ return [ 'registration_email_domain_invalid' => 'Tên miền của email không có quyền truy cập tới ứng dụng này', 'register_success' => 'Cảm ơn bạn đã đăng kí! Bạn đã được xác nhận và đăng nhập.', - // Password Reset 'reset_password' => 'Đặt lại mật khẩu', 'reset_password_send_instructions' => 'Nhập email vào ô dưới đây và bạn sẽ nhận được một email với liên kết để đặt lại mật khẩu.', @@ -49,7 +48,6 @@ return [ 'email_reset_text' => 'Bạn nhận được email này bởi vì chúng tôi nhận được một yêu cầu đặt lại mật khẩu cho tài khoản của bạn.', 'email_reset_not_requested' => 'Nếu bạn không yêu cầu đặt lại mật khẩu, không cần có bất cứ hành động nào khác.', - // Email Confirmation 'email_confirm_subject' => 'Xác nhận email trên :appName', 'email_confirm_greeting' => 'Cảm ơn bạn đã tham gia :appName!', @@ -109,4 +107,4 @@ return [ 'mfa_verify_backup_code_enter_here' => 'Nhập mã xác thực của bạn tại đây', 'mfa_verify_totp_desc' => 'Nhập mã do ứng dụng di động của bạn tạo ra vào dưới đây:', 'mfa_setup_login_notification' => 'Đã cài đặt xác thực nhiều bước, bạn vui lòng đăng nhập lại sử dụng phương thức đã cài đặt.', -]; \ No newline at end of file +]; diff --git a/resources/lang/vi/common.php b/resources/lang/vi/common.php index f118d34c3..2a1de7863 100644 --- a/resources/lang/vi/common.php +++ b/resources/lang/vi/common.php @@ -20,7 +20,7 @@ return [ 'role' => 'Quyền', 'cover_image' => 'Ảnh bìa', 'cover_image_description' => 'Ảnh nên có kích thước 440x250px.', - + // Actions 'actions' => 'Hành động', 'view' => 'Xem', diff --git a/resources/lang/vi/entities.php b/resources/lang/vi/entities.php index 8162509d7..58e1d6b1f 100644 --- a/resources/lang/vi/entities.php +++ b/resources/lang/vi/entities.php @@ -321,5 +321,5 @@ return [ 'revision_delete_confirm' => 'Bạn có chắc bạn muốn xóa phiên bản này?', 'revision_restore_confirm' => 'Bạn có chắc bạn muốn khôi phục phiên bản này? Nội dung trang hiện tại sẽ được thay thế.', 'revision_delete_success' => 'Phiên bản đã được xóa', - 'revision_cannot_delete_latest' => 'Không thể xóa phiên bản mới nhất.' + 'revision_cannot_delete_latest' => 'Không thể xóa phiên bản mới nhất.', ]; diff --git a/resources/lang/vi/passwords.php b/resources/lang/vi/passwords.php index 65b42b4d8..e31974161 100644 --- a/resources/lang/vi/passwords.php +++ b/resources/lang/vi/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'Mật khẩu phải có tối thiểu 8 ký tự và và phải trùng với mật khẩu xác nhận.', - 'user' => "Chúng tôi không tìm thấy người dùng với địa chỉ email đó.", + 'user' => 'Chúng tôi không tìm thấy người dùng với địa chỉ email đó.', 'token' => 'Mã token đặt lại mật khẩu cho địa chỉ email này không hợp lệ.', 'sent' => 'Chúng tôi đã gửi email chứa liên kết đặt lại mật khẩu cho bạn!', 'reset' => 'Mật khẩu của bạn đã được đặt lại!', diff --git a/resources/lang/vi/settings.php b/resources/lang/vi/settings.php index 25dd2da0e..d4d5322f1 100644 --- a/resources/lang/vi/settings.php +++ b/resources/lang/vi/settings.php @@ -72,7 +72,7 @@ return [ // Maintenance settings 'maint' => 'Bảo trì', 'maint_image_cleanup' => 'Dọn dẹp ảnh', - 'maint_image_cleanup_desc' => "Quét nội dung trang và phiên bản để kiểm tra xem các ảnh và hình vẽ nào đang được sử dụng và ảnh nào dư thừa. Đảm bảo rằng bạn đã tạo bản sao lưu toàn dữ liệu và ảnh trước khi chạy chức năng này.", + 'maint_image_cleanup_desc' => 'Quét nội dung trang và phiên bản để kiểm tra xem các ảnh và hình vẽ nào đang được sử dụng và ảnh nào dư thừa. Đảm bảo rằng bạn đã tạo bản sao lưu toàn dữ liệu và ảnh trước khi chạy chức năng này.', 'maint_delete_images_only_in_revisions' => 'Also delete images that only exist in old page revisions', 'maint_image_cleanup_run' => 'Chạy Dọn dẹp', 'maint_image_cleanup_warning' => 'Đã tìm thấy :count ảnh có thể không được sử dụng. Bạn muốn chắc rằng muốn xóa các ảnh này?', @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Xóa quyền', 'role_delete_confirm' => 'Chức năng này sẽ xóa quyền với tên \':roleName\'.', 'role_delete_users_assigned' => 'Quyền này có :userCount người dùng được gán. Nếu bạn muốn di dời các người dùng từ quyền này hãy chọn một quyền mới bên dưới.', - 'role_delete_no_migration' => "Không di dời các người dùng", + 'role_delete_no_migration' => 'Không di dời các người dùng', 'role_delete_sure' => 'Bạn có chắc rằng muốn xóa quyền này?', 'role_delete_success' => 'Quyền đã được xóa thành công', 'role_edit' => 'Sửa quyền', @@ -273,6 +273,6 @@ return [ 'vi' => 'Tiếng Việt', 'zh_CN' => '简体中文', 'zh_TW' => '繁體中文', - ] + ], //!//////////////////////////////// ]; diff --git a/resources/lang/zh_CN/auth.php b/resources/lang/zh_CN/auth.php index a31ee20e7..8411eb866 100644 --- a/resources/lang/zh_CN/auth.php +++ b/resources/lang/zh_CN/auth.php @@ -38,7 +38,6 @@ return [ 'registration_email_domain_invalid' => '该Email域名无权访问此应用程序', 'register_success' => '感谢您注册:appName,您现在已经登录。', - // Password Reset 'reset_password' => '重置密码', 'reset_password_send_instructions' => '在下面输入您的Email地址,您将收到一封带有密码重置链接的邮件。', @@ -49,7 +48,6 @@ return [ 'email_reset_text' => '您收到此电子邮件是因为我们收到了您的帐户的密码重置请求。', 'email_reset_not_requested' => '如果您没有要求重置密码,则不需要采取进一步的操作。', - // Email Confirmation 'email_confirm_subject' => '确认您在:appName的Email地址', 'email_confirm_greeting' => '感谢您加入:appName!', @@ -109,4 +107,4 @@ return [ 'mfa_verify_backup_code_enter_here' => '在这里输入备用认证码', 'mfa_verify_totp_desc' => '在下面输入您的移动 App 生成的认证码:', 'mfa_setup_login_notification' => '多重身份认证已设置,请使用新配置的方法重新登录。', -]; \ No newline at end of file +]; diff --git a/resources/lang/zh_CN/common.php b/resources/lang/zh_CN/common.php index 6c2fa668b..42d0eb87f 100644 --- a/resources/lang/zh_CN/common.php +++ b/resources/lang/zh_CN/common.php @@ -20,7 +20,7 @@ return [ 'role' => '角色', 'cover_image' => '封面图片', 'cover_image_description' => '该图像大小需要为440x250px。', - + // Actions 'actions' => '操作', 'view' => '浏览', diff --git a/resources/lang/zh_CN/entities.php b/resources/lang/zh_CN/entities.php index f3414179b..4b2d17eca 100644 --- a/resources/lang/zh_CN/entities.php +++ b/resources/lang/zh_CN/entities.php @@ -321,5 +321,5 @@ return [ 'revision_delete_confirm' => '您确定要删除此修订版吗?', 'revision_restore_confirm' => '您确定要恢复到此修订版吗?恢复后原有内容将会被替换。', 'revision_delete_success' => '修订删除', - 'revision_cannot_delete_latest' => '无法删除最新版本。' + 'revision_cannot_delete_latest' => '无法删除最新版本。', ]; diff --git a/resources/lang/zh_CN/passwords.php b/resources/lang/zh_CN/passwords.php index 8d8272ee0..712120f60 100644 --- a/resources/lang/zh_CN/passwords.php +++ b/resources/lang/zh_CN/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => '密码必须至少包含六个字符并与确认相符。', - 'user' => "使用该Email地址的用户不存在。", + 'user' => '使用该Email地址的用户不存在。', 'token' => '重置密码链接无法发送至此邮件地址。', 'sent' => '我们已经通过Email发送您的密码重置链接!', 'reset' => '您的密码已被重置!', diff --git a/resources/lang/zh_CN/settings.php b/resources/lang/zh_CN/settings.php index 6fa0e84d4..3f4d7bead 100755 --- a/resources/lang/zh_CN/settings.php +++ b/resources/lang/zh_CN/settings.php @@ -72,7 +72,7 @@ return [ // Maintenance settings 'maint' => '维护', 'maint_image_cleanup' => '清理图像', - 'maint_image_cleanup_desc' => "扫描页面和修订内容以检查哪些图片是正在使用的以及哪些图片是多余的。确保在运行前完整备份数据库和图片。", + 'maint_image_cleanup_desc' => '扫描页面和修订内容以检查哪些图片是正在使用的以及哪些图片是多余的。确保在运行前完整备份数据库和图片。', 'maint_delete_images_only_in_revisions' => '同时删除只存在于旧的页面修订中的图片', 'maint_image_cleanup_run' => '运行清理', 'maint_image_cleanup_warning' => '发现了 :count 张可能未使用的图像。您确定要删除这些图像吗?', @@ -132,7 +132,7 @@ return [ 'role_delete' => '删除角色', 'role_delete_confirm' => '这将会删除名为 \':roleName\' 的角色.', 'role_delete_users_assigned' => '有:userCount位用户属于此角色。如果您想将此角色中的用户迁移,请在下面选择一个新角色。', - 'role_delete_no_migration' => "不要迁移用户", + 'role_delete_no_migration' => '不要迁移用户', 'role_delete_sure' => '您确定要删除这个角色?', 'role_delete_success' => '角色删除成功', 'role_edit' => '编辑角色', @@ -273,6 +273,6 @@ return [ 'vi' => 'Tiếng Việt', 'zh_CN' => '简体中文', 'zh_TW' => '繁體中文', - ] + ], //!//////////////////////////////// ]; diff --git a/resources/lang/zh_TW/auth.php b/resources/lang/zh_TW/auth.php index 89fc6f55a..a12c12178 100644 --- a/resources/lang/zh_TW/auth.php +++ b/resources/lang/zh_TW/auth.php @@ -38,7 +38,6 @@ return [ 'registration_email_domain_invalid' => '這個電子郵件網域沒有權限使用', 'register_success' => '感謝您註冊!您已註冊完成並可登入。', - // Password Reset 'reset_password' => '重設密碼', 'reset_password_send_instructions' => '在下方輸入您的電子郵件,您將收到一封帶有密碼重設連結的郵件。', @@ -49,7 +48,6 @@ return [ 'email_reset_text' => '您收到此電子郵件是因為我們收到了您的帳號的密碼重設請求。', 'email_reset_not_requested' => '如果您沒有要求重設密碼,則不需要採取進一步的操作。', - // Email Confirmation 'email_confirm_subject' => '確認您在 :appName 的電子郵件', 'email_confirm_greeting' => '感謝您加入 :appName!', @@ -109,4 +107,4 @@ return [ 'mfa_verify_backup_code_enter_here' => 'Enter backup code here', 'mfa_verify_totp_desc' => 'Enter the code, generated using your mobile app, below:', 'mfa_setup_login_notification' => 'Multi-factor method configured, Please now login again using the configured method.', -]; \ No newline at end of file +]; diff --git a/resources/lang/zh_TW/common.php b/resources/lang/zh_TW/common.php index b358111fd..8209bf4d0 100644 --- a/resources/lang/zh_TW/common.php +++ b/resources/lang/zh_TW/common.php @@ -20,7 +20,7 @@ return [ 'role' => '角色', 'cover_image' => '封面圖片', 'cover_image_description' => '此圖片大小應約為 440x250px。', - + // Actions 'actions' => '動作', 'view' => '檢視', diff --git a/resources/lang/zh_TW/entities.php b/resources/lang/zh_TW/entities.php index e35a0795a..a19e53860 100644 --- a/resources/lang/zh_TW/entities.php +++ b/resources/lang/zh_TW/entities.php @@ -94,7 +94,7 @@ return [ 'shelves_edit' => '編輯書架', 'shelves_delete' => '刪除書架', 'shelves_delete_named' => '刪除書架 :name', - 'shelves_delete_explain' => "這將刪除名為「:name」的書架。但其中的書本不會被刪除。", + 'shelves_delete_explain' => '這將刪除名為「:name」的書架。但其中的書本不會被刪除。', 'shelves_delete_confirmation' => '您確定要刪除此書架嗎?', 'shelves_permissions' => '書架權限', 'shelves_permissions_updated' => '書架權限已更新', @@ -321,5 +321,5 @@ return [ 'revision_delete_confirm' => '您確定要刪除此修訂版本嗎?', 'revision_restore_confirm' => '您確定要還原此修訂版本嗎? 目前頁面內容將被替換。', 'revision_delete_success' => '修訂版本已刪除', - 'revision_cannot_delete_latest' => '無法刪除最新修訂版本。' + 'revision_cannot_delete_latest' => '無法刪除最新修訂版本。', ]; diff --git a/resources/lang/zh_TW/passwords.php b/resources/lang/zh_TW/passwords.php index f4d8dc30c..614b9e2bf 100644 --- a/resources/lang/zh_TW/passwords.php +++ b/resources/lang/zh_TW/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => '密碼必須至少八個字元,並與確認密碼相符。', - 'user' => "沒有使用這個電子郵件位址的使用者。", + 'user' => '沒有使用這個電子郵件位址的使用者。', 'token' => '這個電子郵件地址的密碼重設權杖無效。', 'sent' => '我們已經透過電子郵件發送您的密碼重設連結。', 'reset' => '您的密碼已被重設!', diff --git a/resources/lang/zh_TW/settings.php b/resources/lang/zh_TW/settings.php index 53871de45..9d0439a37 100644 --- a/resources/lang/zh_TW/settings.php +++ b/resources/lang/zh_TW/settings.php @@ -72,7 +72,7 @@ return [ // Maintenance settings 'maint' => '維護', 'maint_image_cleanup' => '清理圖片', - 'maint_image_cleanup_desc' => "掃描頁面與修訂版本內容來檢查目前使用了哪些圖片,而哪些圖片又是多餘的。請確保您在執行這個動作前建立了完整的資料庫與映像檔備份。", + 'maint_image_cleanup_desc' => '掃描頁面與修訂版本內容來檢查目前使用了哪些圖片,而哪些圖片又是多餘的。請確保您在執行這個動作前建立了完整的資料庫與映像檔備份。', 'maint_delete_images_only_in_revisions' => '也刪除僅存在於舊的頁面修訂版本中存在的圖片', 'maint_image_cleanup_run' => '執行清理', 'maint_image_cleanup_warning' => '發現了 :count 張可能未使用的圖片。您確定要刪除這些圖片嗎?', @@ -132,7 +132,7 @@ return [ 'role_delete' => '刪除角色', 'role_delete_confirm' => '這將會刪除名為「:roleName」的角色.', 'role_delete_users_assigned' => '有 :userCount 位使用者屬於此角色。如果您想將此角色中的使用者遷移,請在下面選擇一個新角色。', - 'role_delete_no_migration' => "不要遷移使用者", + 'role_delete_no_migration' => '不要遷移使用者', 'role_delete_sure' => '您確定要刪除此角色?', 'role_delete_success' => '角色刪除成功', 'role_edit' => '編輯角色', @@ -273,6 +273,6 @@ return [ 'vi' => 'Tiếng Việt', 'zh_CN' => '简体中文', 'zh_TW' => '繁體中文', - ] + ], //!//////////////////////////////// ]; diff --git a/tests/Api/AttachmentsApiTest.php b/tests/Api/AttachmentsApiTest.php index 40624dcdf..ceab5d49a 100644 --- a/tests/Api/AttachmentsApiTest.php +++ b/tests/Api/AttachmentsApiTest.php @@ -325,6 +325,6 @@ class AttachmentsApiTest extends TestCase */ protected function getTestFile(string $fileName): UploadedFile { - return new UploadedFile(base_path('tests/test-data/test-file.txt'), $fileName, 'text/plain', 55, null, true); + return new UploadedFile(base_path('tests/test-data/test-file.txt'), $fileName, 'text/plain', null, true); } } diff --git a/tests/Auth/MfaConfigurationTest.php b/tests/Auth/MfaConfigurationTest.php index 59a2a41b5..fab94817c 100644 --- a/tests/Auth/MfaConfigurationTest.php +++ b/tests/Auth/MfaConfigurationTest.php @@ -39,7 +39,7 @@ class MfaConfigurationTest extends TestCase $this->assertTrue($svg === $revisitSvg); $secret = decrypt(session()->get('mfa-setup-totp-secret')); - $resp->assertSee(htmlentities("?secret={$secret}&issuer=BookStack&algorithm=SHA1&digits=6&period=30")); + $resp->assertSee("?secret={$secret}&issuer=BookStack&algorithm=SHA1&digits=6&period=30"); // Successful confirmation $google2fa = new Google2FA(); @@ -180,7 +180,7 @@ class MfaConfigurationTest extends TestCase $resp = $this->get('/mfa/totp/generate'); $resp->assertSeeText('Mobile App Setup'); - $resp->assertDontSee('otpauth://totp/BookStack:guest%40example.com'); - $resp->assertSee('otpauth://totp/BookStack:admin%40admin.com'); + $resp->assertDontSee('otpauth://totp/BookStack:guest%40example.com', false); + $resp->assertSee('otpauth://totp/BookStack:admin%40admin.com', false); } } diff --git a/tests/Auth/Saml2Test.php b/tests/Auth/Saml2Test.php index 7fb8d6ddb..c534b2d78 100644 --- a/tests/Auth/Saml2Test.php +++ b/tests/Auth/Saml2Test.php @@ -49,7 +49,7 @@ class Saml2Test extends TestCase $req = $this->get('/saml2/metadata'); $req->assertSee('https://example.com/super-cats'); $req->assertSee('md:ContactPerson'); - $req->assertSee('Barry Scott'); + $req->assertSee('Barry Scott', false); } public function test_login_option_shows_on_login_page() diff --git a/tests/Entity/BookShelfTest.php b/tests/Entity/BookShelfTest.php index 1780ddee8..afd6a1a06 100644 --- a/tests/Entity/BookShelfTest.php +++ b/tests/Entity/BookShelfTest.php @@ -290,7 +290,7 @@ class BookShelfTest extends TestCase $shelf = Bookshelf::first(); $resp = $this->asAdmin()->get($shelf->getUrl('/permissions')); $resp->assertSeeText('Copy Permissions'); - $resp->assertSee("action=\"{$shelf->getUrl('/copy-permissions')}\""); + $resp->assertSee("action=\"{$shelf->getUrl('/copy-permissions')}\"", false); $child = $shelf->books()->first(); $editorRole = $this->getEditor()->roles()->first(); diff --git a/tests/Entity/BookTest.php b/tests/Entity/BookTest.php index fa63c0bf9..53ee6faf9 100644 --- a/tests/Entity/BookTest.php +++ b/tests/Entity/BookTest.php @@ -187,7 +187,7 @@ class BookTest extends TestCase 'name' => 'информация', ]); - $this->assertEquals('informatsiya', $book->slug); + $this->assertEquals('informaciya', $book->slug); $book = $this->newBook([ 'name' => '¿Qué?', diff --git a/tests/Entity/CommentTest.php b/tests/Entity/CommentTest.php index 3bf51556e..b613f80a1 100644 --- a/tests/Entity/CommentTest.php +++ b/tests/Entity/CommentTest.php @@ -88,7 +88,7 @@ class CommentTest extends TestCase ]); $pageView = $this->get($page->getUrl()); - $pageView->assertSee('

My Title

'); + $pageView->assertSee('

My Title

', false); } public function test_html_cannot_be_injected_via_comment_content() @@ -102,7 +102,7 @@ class CommentTest extends TestCase ]); $pageView = $this->get($page->getUrl()); - $pageView->assertDontSee($script); + $pageView->assertDontSee($script, false); $pageView->assertSee('sometextinthecomment'); $comment = $page->comments()->first(); @@ -111,7 +111,7 @@ class CommentTest extends TestCase ]); $pageView = $this->get($page->getUrl()); - $pageView->assertDontSee($script); + $pageView->assertDontSee($script, false); $pageView->assertSee('sometextinthecommentupdated'); } } diff --git a/tests/Entity/ExportTest.php b/tests/Entity/ExportTest.php index c8397b695..9ea336db8 100644 --- a/tests/Entity/ExportTest.php +++ b/tests/Entity/ExportTest.php @@ -139,7 +139,7 @@ class ExportTest extends TestCase $this->setSettings(['app-custom-head' => $customHeadContent]); $resp = $this->asEditor()->get($page->getUrl('/export/html')); - $resp->assertSee($customHeadContent); + $resp->assertSee($customHeadContent, false); } public function test_page_html_export_does_not_break_with_only_comments_in_custom_head() @@ -151,7 +151,7 @@ class ExportTest extends TestCase $resp = $this->asEditor()->get($page->getUrl('/export/html')); $resp->assertStatus(200); - $resp->assertSee($customHeadContent); + $resp->assertSee($customHeadContent, false); } public function test_page_html_export_use_absolute_dates() @@ -188,7 +188,7 @@ class ExportTest extends TestCase Storage::disk('local')->delete('uploads/images/gallery/svg_test.svg'); $resp->assertStatus(200); - $resp->assertSee('delete('uploads/images/gallery/svg_test.svg'); $storageDisk->delete('uploads/svg_test.svg'); - $resp->assertDontSee('http://localhost/uploads/images/gallery/svg_test.svg'); + $resp->assertDontSee('http://localhost/uploads/images/gallery/svg_test.svg', false); $resp->assertSee('http://localhost/uploads/svg_test.svg'); - $resp->assertSee('src="/uploads/svg_test.svg"'); + $resp->assertSee('src="/uploads/svg_test.svg"', false); } public function test_page_export_contained_html_does_not_allow_upward_traversal_with_local() @@ -333,7 +333,7 @@ class ExportTest extends TestCase $page->save(); $resp = $this->asEditor()->get($page->getUrl('/export/markdown')); - $resp->assertSee("# Dogcat\n\n

Some callout text

\n\nAnother line"); + $resp->assertSee("# Dogcat\n\n

Some callout text

\n\nAnother line", false); } public function test_page_markdown_export_handles_bookstacks_wysiwyg_codeblock_format() @@ -345,7 +345,7 @@ class ExportTest extends TestCase $page->save(); $resp = $this->asEditor()->get($page->getUrl('/export/markdown')); - $resp->assertSee("# Dogcat\n\n```JavaScript\nvar a = 'cat';\n```\n\nAnother line"); + $resp->assertSee("# Dogcat\n\n```JavaScript\nvar a = 'cat';\n```\n\nAnother line", false); } public function test_chapter_markdown_export() diff --git a/tests/Entity/PageContentTest.php b/tests/Entity/PageContentTest.php index ca2a24131..dd996b926 100644 --- a/tests/Entity/PageContentTest.php +++ b/tests/Entity/PageContentTest.php @@ -74,7 +74,7 @@ class PageContentTest extends TestCase $this->asEditor(); $pageResp = $this->get($page->getUrl()); - $pageResp->assertSee($content); + $pageResp->assertSee($content, false); } public function test_page_includes_rendered_on_book_export() @@ -106,7 +106,7 @@ class PageContentTest extends TestCase $pageView = $this->get($page->getUrl()); $pageView->assertStatus(200); - $pageView->assertDontSee($script); + $pageView->assertDontSee($script, false); $pageView->assertSee('abc123abc123'); } @@ -260,8 +260,8 @@ class PageContentTest extends TestCase $pageView = $this->get($page->getUrl()); $pageView->assertStatus(200); - $pageView->assertDontSee($script); - $pageView->assertSee('

Hello

'); + $pageView->assertDontSee($script, false); + $pageView->assertSee('

Hello

', false); } public function test_more_complex_inline_on_attributes_escaping_scenarios() @@ -301,7 +301,7 @@ class PageContentTest extends TestCase $page->save(); $pageView = $this->get($page->getUrl()); - $pageView->assertSee($script); + $pageView->assertSee($script, false); $pageView->assertDontSee('abc123abc123'); } @@ -338,8 +338,8 @@ class PageContentTest extends TestCase $page->save(); $pageView = $this->get($page->getUrl()); - $pageView->assertSee($script); - $pageView->assertDontSee('

Hello

'); + $pageView->assertSee($script, false); + $pageView->assertDontSee('

Hello

', false); } public function test_duplicate_ids_does_not_break_page_render() @@ -545,7 +545,7 @@ class PageContentTest extends TestCase $pageView = $this->get($page->getUrl()); $pageView->assertStatus(200); - $pageView->assertSee($content); + $pageView->assertSee($content, false); } public function test_base64_images_get_extracted_from_page_content() diff --git a/tests/Permissions/RolesTest.php b/tests/Permissions/RolesTest.php index 5248ae152..3178bd8ce 100644 --- a/tests/Permissions/RolesTest.php +++ b/tests/Permissions/RolesTest.php @@ -173,11 +173,11 @@ class RolesTest extends TestCase public function test_manage_users_permission_shows_link_in_header_if_does_not_have_settings_manage_permision() { $usersLink = 'href="' . url('/settings/users') . '"'; - $this->actingAs($this->user)->get('/')->assertDontSee($usersLink); + $this->actingAs($this->user)->get('/')->assertDontSee($usersLink, false); $this->giveUserPermissions($this->user, ['users-manage']); - $this->actingAs($this->user)->get('/')->assertSee($usersLink); + $this->actingAs($this->user)->get('/')->assertSee($usersLink, false); $this->giveUserPermissions($this->user, ['settings-manage', 'users-manage']); - $this->actingAs($this->user)->get('/')->assertDontSee($usersLink); + $this->actingAs($this->user)->get('/')->assertDontSee($usersLink, false); } public function test_user_cannot_change_email_unless_they_have_manage_users_permission() diff --git a/tests/SecurityHeaderTest.php b/tests/SecurityHeaderTest.php index 10551fc55..78691badb 100644 --- a/tests/SecurityHeaderTest.php +++ b/tests/SecurityHeaderTest.php @@ -76,7 +76,7 @@ class SecurityHeaderTest extends TestCase $nonce = app()->make(CspService::class)->getNonce(); $this->assertStringContainsString('nonce-' . $nonce, $scriptHeader); - $resp->assertSee(''); + $resp->assertSee('', false); } public function test_script_csp_nonce_changes_per_request() diff --git a/tests/Settings/CustomHeadContentTest.php b/tests/Settings/CustomHeadContentTest.php index 94ef4711d..36c8a4c0f 100644 --- a/tests/Settings/CustomHeadContentTest.php +++ b/tests/Settings/CustomHeadContentTest.php @@ -11,21 +11,21 @@ class CustomHeadContentTest extends TestCase { $this->setSettings(['app-custom-head' => '']); $resp = $this->get('/login'); - $resp->assertSee('console.log("cat")'); + $resp->assertSee('console.log("cat")', false); } public function test_configured_content_does_not_show_on_settings_page() { $this->setSettings(['app-custom-head' => '']); $resp = $this->asAdmin()->get('/settings'); - $resp->assertDontSee('console.log("cat")'); + $resp->assertDontSee('console.log("cat")', false); } public function test_divs_in_js_preserved_in_configured_content() { $this->setSettings(['app-custom-head' => '']); $resp = $this->get('/login'); - $resp->assertSee('
cat
'); + $resp->assertSee('
cat
', false); } public function test_nonce_application_handles_edge_cases() @@ -61,6 +61,6 @@ const b = `setSettings(['app-custom-head' => $content]); $resp = $this->get('/login'); - $resp->assertSee($expectedOutput); + $resp->assertSee($expectedOutput, false); } } diff --git a/tests/Settings/FooterLinksTest.php b/tests/Settings/FooterLinksTest.php index 55c3e107d..f1b5d4294 100644 --- a/tests/Settings/FooterLinksTest.php +++ b/tests/Settings/FooterLinksTest.php @@ -31,10 +31,10 @@ class FooterLinksTest extends TestCase ]]); $resp = $this->asAdmin()->get('/settings'); - $resp->assertSee('value="My custom link"'); - $resp->assertSee('value="Another Link"'); - $resp->assertSee('value="https://example.com/link-a"'); - $resp->assertSee('value="https://example.com/link-b"'); + $resp->assertSee('value="My custom link"', false); + $resp->assertSee('value="Another Link"', false); + $resp->assertSee('value="https://example.com/link-a"', false); + $resp->assertSee('value="https://example.com/link-b"', false); } public function test_footer_links_show_on_pages() diff --git a/tests/SharedTestHelpers.php b/tests/SharedTestHelpers.php index 04952d223..d96fcb710 100644 --- a/tests/SharedTestHelpers.php +++ b/tests/SharedTestHelpers.php @@ -22,10 +22,10 @@ use GuzzleHttp\Client; use GuzzleHttp\Handler\MockHandler; use GuzzleHttp\HandlerStack; use GuzzleHttp\Middleware; -use Illuminate\Foundation\Testing\Assert as PHPUnit; use Illuminate\Http\JsonResponse; use Illuminate\Support\Env; use Illuminate\Support\Facades\Log; +use Illuminate\Testing\Assert as PHPUnit; use Mockery; use Monolog\Handler\TestHandler; use Monolog\Logger; @@ -127,7 +127,7 @@ trait SharedTestHelpers /** * Create and return a new test chapter. */ - public function newChapter(array $input = ['name' => 'test chapter', 'description' => 'My new test chapter'], Book $book): Chapter + public function newChapter(array $input, Book $book): Chapter { return app(ChapterRepo::class)->create($input, $book); } diff --git a/tests/TestResponse.php b/tests/TestResponse.php index 79f173c9b..5e2be3ac3 100644 --- a/tests/TestResponse.php +++ b/tests/TestResponse.php @@ -2,7 +2,7 @@ namespace Tests; -use Illuminate\Foundation\Testing\TestResponse as BaseTestResponse; +use Illuminate\Testing\TestResponse as BaseTestResponse; use PHPUnit\Framework\Assert as PHPUnit; use Symfony\Component\DomCrawler\Crawler; diff --git a/tests/Uploads/AttachmentTest.php b/tests/Uploads/AttachmentTest.php index 60fd370b6..588b7054a 100644 --- a/tests/Uploads/AttachmentTest.php +++ b/tests/Uploads/AttachmentTest.php @@ -17,13 +17,13 @@ class AttachmentTest extends TestCase */ protected function getTestFile(string $fileName): UploadedFile { - return new UploadedFile(base_path('tests/test-data/test-file.txt'), $fileName, 'text/plain', 55, null, true); + return new UploadedFile(base_path('tests/test-data/test-file.txt'), $fileName, 'text/plain', null, true); } /** * Uploads a file with the given name. */ - protected function uploadFile(string $name, int $uploadedTo = 0): \Illuminate\Foundation\Testing\TestResponse + protected function uploadFile(string $name, int $uploadedTo = 0): \Illuminate\Testing\TestResponse { $file = $this->getTestFile($name); diff --git a/tests/Uploads/DrawioTest.php b/tests/Uploads/DrawioTest.php index 422de472a..1fc3d1049 100644 --- a/tests/Uploads/DrawioTest.php +++ b/tests/Uploads/DrawioTest.php @@ -61,7 +61,7 @@ class DrawioTest extends TestCase $editor = $this->getEditor(); $resp = $this->actingAs($editor)->get($page->getUrl('/edit')); - $resp->assertSee('drawio-url="http://cats.com?dog=tree"'); + $resp->assertSee('drawio-url="http://cats.com?dog=tree"', false); } public function test_drawio_url_can_be_disabled() @@ -71,10 +71,10 @@ class DrawioTest extends TestCase $editor = $this->getEditor(); $resp = $this->actingAs($editor)->get($page->getUrl('/edit')); - $resp->assertSee('drawio-url="https://embed.diagrams.net/?embed=1&proto=json&spin=1"'); + $resp->assertSee('drawio-url="https://embed.diagrams.net/?embed=1&proto=json&spin=1"', false); config()->set('services.drawio', false); $resp = $this->actingAs($editor)->get($page->getUrl('/edit')); - $resp->assertDontSee('drawio-url'); + $resp->assertDontSee('drawio-url', false); } } From f139cded789908efce3ac2ed1be26b947df647db Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 30 Oct 2021 21:29:59 +0100 Subject: [PATCH 02/59] Laravel 8 shift squash & merge (#3029) * Temporarily moved back config path * Apply Laravel coding style * Shift exception handler * Shift HTTP kernel and middleware * Shift service providers * Convert options array to fluent methods * Shift to class based routes * Shift console routes * Ignore temporary framework files * Shift to class based factories * Namespace seeders * Shift PSR-4 autoloading * Shift config files * Default config files * Shift Laravel dependencies * Shift return type of base TestCase methods * Shift cleanup * Applied stylci style changes * Reverted config files location * Applied manual changes to Laravel 8 shift Co-authored-by: Shift --- app/Actions/Comment.php | 2 + app/Actions/Tag.php | 3 + app/Auth/Role.php | 3 + app/Auth/User.php | 2 + app/Config/app.php | 11 +- app/Config/auth.php | 15 +- app/Config/broadcasting.php | 84 ++- app/Config/cache.php | 105 ++- app/Config/filesystems.php | 13 +- app/Config/logging.php | 13 +- app/Config/queue.php | 24 +- app/Entities/Models/Book.php | 3 + app/Entities/Models/Bookshelf.php | 3 + app/Entities/Models/Chapter.php | 3 + app/Entities/Models/Page.php | 3 + app/Exceptions/Handler.php | 1 + app/Http/Kernel.php | 2 +- ...p => PreventRequestsDuringMaintenance.php} | 4 +- .../Middleware/RedirectIfAuthenticated.php | 42 +- app/Http/Middleware/TrustHosts.php | 2 +- app/Http/Middleware/TrustProxies.php | 4 +- app/Providers/AppServiceProvider.php | 4 + app/Providers/EventServiceProvider.php | 1 - app/Providers/RouteServiceProvider.php | 41 +- app/Uploads/Image.php | 2 + composer.json | 33 +- composer.lock | 629 ++++++++++-------- database/factories/Actions/CommentFactory.php | 32 + database/factories/Actions/TagFactory.php | 28 + database/factories/Auth/RoleFactory.php | 28 + database/factories/Auth/UserFactory.php | 35 + .../factories/Entities/Models/BookFactory.php | 30 + .../Entities/Models/BookshelfFactory.php | 30 + .../Entities/Models/ChapterFactory.php | 30 + .../factories/Entities/Models/PageFactory.php | 34 + database/factories/ModelFactory.php | 96 --- database/factories/Uploads/ImageFactory.php | 31 + database/{seeds => seeders}/.gitkeep | 0 .../{seeds => seeders}/DatabaseSeeder.php | 2 + .../{seeds => seeders}/DummyContentSeeder.php | 23 +- .../{seeds => seeders}/LargeContentSeeder.php | 10 +- public/index.php | 63 +- routes/api.php | 87 +-- routes/console.php | 19 + routes/web.php | 435 ++++++------ storage/framework/.gitignore | 12 +- tests/AuditLogTest.php | 2 +- tests/Auth/AuthTest.php | 8 +- tests/Auth/LdapTest.php | 28 +- tests/Auth/OidcTest.php | 4 +- tests/Auth/Saml2Test.php | 8 +- tests/Auth/SocialAuthTest.php | 8 +- tests/Entity/BookShelfTest.php | 2 +- tests/Entity/BookTest.php | 4 +- tests/Entity/ChapterTest.php | 2 +- tests/Entity/CommentSettingTest.php | 2 +- tests/Entity/CommentTest.php | 6 +- tests/Entity/PageDraftTest.php | 2 +- tests/Entity/PageEditorTest.php | 2 +- tests/Entity/PageTest.php | 2 +- tests/Entity/SortTest.php | 2 +- tests/Entity/TagTest.php | 58 +- tests/HomepageTest.php | 2 +- tests/LanguageTest.php | 2 +- tests/Permissions/EntityPermissionsTest.php | 2 +- tests/Permissions/RolesTest.php | 14 +- tests/SharedTestHelpers.php | 8 +- tests/ThemeTest.php | 2 +- tests/Uploads/AvatarTest.php | 8 +- tests/User/UserManagementTest.php | 2 +- tests/User/UserProfileTest.php | 8 +- 71 files changed, 1349 insertions(+), 916 deletions(-) mode change 100755 => 100644 app/Config/app.php rename app/Http/Middleware/{CheckForMaintenanceMode.php => PreventRequestsDuringMaintenance.php} (58%) create mode 100644 database/factories/Actions/CommentFactory.php create mode 100644 database/factories/Actions/TagFactory.php create mode 100644 database/factories/Auth/RoleFactory.php create mode 100644 database/factories/Auth/UserFactory.php create mode 100644 database/factories/Entities/Models/BookFactory.php create mode 100644 database/factories/Entities/Models/BookshelfFactory.php create mode 100644 database/factories/Entities/Models/ChapterFactory.php create mode 100644 database/factories/Entities/Models/PageFactory.php delete mode 100644 database/factories/ModelFactory.php create mode 100644 database/factories/Uploads/ImageFactory.php rename database/{seeds => seeders}/.gitkeep (100%) rename database/{seeds => seeders}/DatabaseSeeder.php (92%) rename database/{seeds => seeders}/DummyContentSeeder.php (71%) rename database/{seeds => seeders}/LargeContentSeeder.php (60%) create mode 100644 routes/console.php diff --git a/app/Actions/Comment.php b/app/Actions/Comment.php index 34fd84709..885ba6ed1 100644 --- a/app/Actions/Comment.php +++ b/app/Actions/Comment.php @@ -4,6 +4,7 @@ namespace BookStack\Actions; use BookStack\Model; use BookStack\Traits\HasCreatorAndUpdater; +use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\MorphTo; /** @@ -15,6 +16,7 @@ use Illuminate\Database\Eloquent\Relations\MorphTo; */ class Comment extends Model { + use HasFactory; use HasCreatorAndUpdater; protected $fillable = ['text', 'parent_id']; diff --git a/app/Actions/Tag.php b/app/Actions/Tag.php index ce0954f00..db9328b7d 100644 --- a/app/Actions/Tag.php +++ b/app/Actions/Tag.php @@ -3,10 +3,13 @@ namespace BookStack\Actions; use BookStack\Model; +use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\MorphTo; class Tag extends Model { + use HasFactory; + protected $fillable = ['name', 'value', 'order']; protected $hidden = ['id', 'entity_id', 'entity_type', 'created_at', 'updated_at']; diff --git a/app/Auth/Role.php b/app/Auth/Role.php index fc2e39aa9..71da88e19 100644 --- a/app/Auth/Role.php +++ b/app/Auth/Role.php @@ -7,6 +7,7 @@ use BookStack\Auth\Permissions\RolePermission; use BookStack\Interfaces\Loggable; use BookStack\Model; use Illuminate\Database\Eloquent\Collection; +use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\HasMany; @@ -23,6 +24,8 @@ use Illuminate\Database\Eloquent\Relations\HasMany; */ class Role extends Model implements Loggable { + use HasFactory; + protected $fillable = ['display_name', 'description', 'external_auth_id']; /** diff --git a/app/Auth/User.php b/app/Auth/User.php index aa8b44e9f..68e2ad625 100644 --- a/app/Auth/User.php +++ b/app/Auth/User.php @@ -18,6 +18,7 @@ use Illuminate\Auth\Passwords\CanResetPassword; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\HasMany; @@ -43,6 +44,7 @@ use Illuminate\Support\Collection; */ class User extends Model implements AuthenticatableContract, CanResetPasswordContract, Loggable, Sluggable { + use HasFactory; use Authenticatable; use CanResetPassword; use Notifiable; diff --git a/app/Config/app.php b/app/Config/app.php old mode 100755 new mode 100644 index f90a7dd76..44e382cdc --- a/app/Config/app.php +++ b/app/Config/app.php @@ -143,7 +143,6 @@ return [ // Class aliases, Registered on application start 'aliases' => [ - // Laravel 'App' => Illuminate\Support\Facades\App::class, 'Arr' => Illuminate\Support\Arr::class, @@ -155,21 +154,23 @@ return [ 'Config' => Illuminate\Support\Facades\Config::class, 'Cookie' => Illuminate\Support\Facades\Cookie::class, 'Crypt' => Illuminate\Support\Facades\Crypt::class, + 'Date' => Illuminate\Support\Facades\Date::class, 'DB' => Illuminate\Support\Facades\DB::class, 'Eloquent' => Illuminate\Database\Eloquent\Model::class, 'Event' => Illuminate\Support\Facades\Event::class, 'File' => Illuminate\Support\Facades\File::class, + 'Gate' => Illuminate\Support\Facades\Gate::class, 'Hash' => Illuminate\Support\Facades\Hash::class, - 'Input' => Illuminate\Support\Facades\Input::class, - 'Inspiring' => Illuminate\Foundation\Inspiring::class, + 'Http' => Illuminate\Support\Facades\Http::class, 'Lang' => Illuminate\Support\Facades\Lang::class, 'Log' => Illuminate\Support\Facades\Log::class, 'Mail' => Illuminate\Support\Facades\Mail::class, 'Notification' => Illuminate\Support\Facades\Notification::class, 'Password' => Illuminate\Support\Facades\Password::class, 'Queue' => Illuminate\Support\Facades\Queue::class, + 'RateLimiter' => Illuminate\Support\Facades\RateLimiter::class, 'Redirect' => Illuminate\Support\Facades\Redirect::class, - 'Redis' => Illuminate\Support\Facades\Redis::class, + // 'Redis' => Illuminate\Support\Facades\Redis::class, 'Request' => Illuminate\Support\Facades\Request::class, 'Response' => Illuminate\Support\Facades\Response::class, 'Route' => Illuminate\Support\Facades\Route::class, @@ -180,6 +181,8 @@ return [ 'URL' => Illuminate\Support\Facades\URL::class, 'Validator' => Illuminate\Support\Facades\Validator::class, 'View' => Illuminate\Support\Facades\View::class, + + // Laravel Packages 'Socialite' => Laravel\Socialite\Facades\Socialite::class, // Third Party diff --git a/app/Config/auth.php b/app/Config/auth.php index 88c22e70a..1e1a9d350 100644 --- a/app/Config/auth.php +++ b/app/Config/auth.php @@ -10,7 +10,6 @@ return [ - // Method of authentication to use // Options: standard, ldap, saml2, oidc 'method' => env('AUTH_METHOD', 'standard'), @@ -45,7 +44,7 @@ return [ 'provider' => 'external', ], 'api' => [ - 'driver' => 'api-token', + 'driver' => 'api-token', ], ], @@ -58,10 +57,16 @@ return [ 'driver' => 'eloquent', 'model' => \BookStack\Auth\User::class, ], + 'external' => [ 'driver' => 'external-users', 'model' => \BookStack\Auth\User::class, ], + + // 'users' => [ + // 'driver' => 'database', + // 'table' => 'users', + // ], ], // Resetting Passwords @@ -78,4 +83,10 @@ return [ ], ], + // Password Confirmation Timeout + // Here you may define the amount of seconds before a password confirmation + // times out and the user is prompted to re-enter their password via the + // confirmation screen. By default, the timeout lasts for three hours. + 'password_timeout' => 10800, + ]; diff --git a/app/Config/broadcasting.php b/app/Config/broadcasting.php index 5e929d373..be0d7376c 100644 --- a/app/Config/broadcasting.php +++ b/app/Config/broadcasting.php @@ -1,51 +1,79 @@ $memcachedServer) { + $memcachedServerDetails = explode(':', $memcachedServer); + if (count($memcachedServerDetails) < 2) { + $memcachedServerDetails[] = '11211'; + } + if (count($memcachedServerDetails) < 3) { + $memcachedServerDetails[] = '100'; + } + $memcachedServers[$index] = array_combine($memcachedServerKeys, $memcachedServerDetails); + } +} + 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' => env('BROADCAST_DRIVER', 'pusher'), + // Default cache store to use + // Can be overridden at cache call-time + 'default' => env('CACHE_DRIVER', 'file'), - // 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' => [ + // Available caches stores + 'stores' => [ - 'pusher' => [ - 'driver' => 'pusher', - 'key' => env('PUSHER_APP_KEY'), - 'secret' => env('PUSHER_APP_SECRET'), - 'app_id' => env('PUSHER_APP_ID'), - 'options' => [ - 'cluster' => env('PUSHER_APP_CLUSTER'), - 'useTLS' => true, - ], + 'apc' => [ + 'driver' => 'apc', + ], + + 'array' => [ + 'driver' => 'array', + 'serialize' => false, + ], + + 'database' => [ + 'driver' => 'database', + 'table' => 'cache', + 'connection' => null, + 'lock_connection' => null, + ], + + 'file' => [ + 'driver' => 'file', + 'path' => storage_path('framework/cache'), + ], + + 'memcached' => [ + 'driver' => 'memcached', + 'servers' => env('CACHE_DRIVER') === 'memcached' ? $memcachedServers : [], + 'options' => [], ], 'redis' => [ - 'driver' => 'redis', - 'connection' => 'default', + 'driver' => 'redis', + 'connection' => 'default', + 'lock_connection' => 'default', ], - 'log' => [ - 'driver' => 'log', - ], - - 'null' => [ - 'driver' => 'null', + 'octane' => [ + 'driver' => 'octane', ], ], + // Cache key prefix + // Used to prevent collisions in shared cache systems. + 'prefix' => env('CACHE_PREFIX', 'bookstack_cache'), + ]; diff --git a/app/Config/cache.php b/app/Config/cache.php index f9b7ed1d2..6fd4807da 100644 --- a/app/Config/cache.php +++ b/app/Config/cache.php @@ -1,36 +1,36 @@ $memcachedServer) { - $memcachedServerDetails = explode(':', $memcachedServer); - if (count($memcachedServerDetails) < 2) { - $memcachedServerDetails[] = '11211'; - } - if (count($memcachedServerDetails) < 3) { - $memcachedServerDetails[] = '100'; - } - $memcachedServers[$index] = array_combine($memcachedServerKeys, $memcachedServerDetails); - } -} +use Illuminate\Support\Str; return [ - // Default cache store to use - // Can be overridden at cache call-time + /* + |-------------------------------------------------------------------------- + | Default Cache Store + |-------------------------------------------------------------------------- + | + | This option controls the default cache connection that gets used while + | using this caching library. This connection is used when another is + | not explicitly specified when executing a given caching function. + | + */ + 'default' => env('CACHE_DRIVER', 'file'), - // Available caches stores + /* + |-------------------------------------------------------------------------- + | Cache Stores + |-------------------------------------------------------------------------- + | + | Here you may define all of the cache "stores" for your application as + | well as their drivers. You may even define multiple stores for the + | same cache driver to group types of items stored in your caches. + | + | Supported drivers: "apc", "array", "database", "file", + | "memcached", "redis", "dynamodb", "octane", "null" + | + */ + 'stores' => [ 'apc' => [ @@ -38,13 +38,15 @@ return [ ], 'array' => [ - 'driver' => 'array', + 'driver' => 'array', + 'serialize' => false, ], 'database' => [ - 'driver' => 'database', - 'table' => 'cache', - 'connection' => null, + 'driver' => 'database', + 'table' => 'cache', + 'connection' => null, + 'lock_connection' => null, ], 'file' => [ @@ -53,19 +55,50 @@ return [ ], 'memcached' => [ - 'driver' => 'memcached', + 'driver' => 'memcached', + 'persistent_id' => env('MEMCACHED_PERSISTENT_ID'), + 'sasl' => [ + env('MEMCACHED_USERNAME'), + env('MEMCACHED_PASSWORD'), + ], + 'options' => [ + // Memcached::OPT_CONNECT_TIMEOUT => 2000, + ], 'servers' => env('CACHE_DRIVER') === 'memcached' ? $memcachedServers : [], ], 'redis' => [ - 'driver' => 'redis', - 'connection' => 'default', + 'driver' => 'redis', + 'connection' => 'default', + 'lock_connection' => 'default', + ], + + 'dynamodb' => [ + 'driver' => 'dynamodb', + 'key' => env('AWS_ACCESS_KEY_ID'), + 'secret' => env('AWS_SECRET_ACCESS_KEY'), + 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), + 'table' => env('DYNAMODB_CACHE_TABLE', 'cache'), + 'endpoint' => env('DYNAMODB_ENDPOINT'), + ], + + 'octane' => [ + 'driver' => 'octane', ], ], - // Cache key prefix - // Used to prevent collisions in shared cache systems. - 'prefix' => env('CACHE_PREFIX', 'bookstack_cache'), + /* + |-------------------------------------------------------------------------- + | Cache Key Prefix + |-------------------------------------------------------------------------- + | + | When utilizing a RAM based store such as APC or Memcached, there might + | be other applications utilizing the same cache. So, we'll specify a + | value to get prefixed to all our keys so we can avoid collisions. + | + */ + + 'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_') . '_cache'), ]; diff --git a/app/Config/filesystems.php b/app/Config/filesystems.php index a6b05c8c4..4d59ba919 100644 --- a/app/Config/filesystems.php +++ b/app/Config/filesystems.php @@ -25,9 +25,6 @@ return [ // file storage service, such as s3, to store publicly accessible assets. 'url' => env('STORAGE_URL', false), - // Default Cloud Filesystem Disk - 'cloud' => 's3', - // Available filesystem disks // Only local, local_secure & s3 are supported by BookStack 'disks' => [ @@ -35,6 +32,7 @@ return [ 'local' => [ 'driver' => 'local', 'root' => public_path(), + 'visibility' => 'public', ], 'local_secure_attachments' => [ @@ -45,6 +43,7 @@ return [ 'local_secure_images' => [ 'driver' => 'local', 'root' => storage_path('uploads/images/'), + 'visibility' => 'public', ], 's3' => [ @@ -59,4 +58,12 @@ return [ ], + // Symbolic Links + // Here you may configure the symbolic links that will be created when the + // `storage:link` Artisan command is executed. The array keys should be + // the locations of the links and the values should be their targets. + 'links' => [ + public_path('storage') => storage_path('app/public'), + ], + ]; diff --git a/app/Config/logging.php b/app/Config/logging.php index 220aa0607..2b80147c8 100644 --- a/app/Config/logging.php +++ b/app/Config/logging.php @@ -49,16 +49,9 @@ return [ 'days' => 7, ], - 'slack' => [ - 'driver' => 'slack', - 'url' => env('LOG_SLACK_WEBHOOK_URL'), - 'username' => 'Laravel Log', - 'emoji' => ':boom:', - 'level' => 'critical', - ], - 'stderr' => [ 'driver' => 'monolog', + 'level' => 'debug', 'handler' => StreamHandler::class, 'with' => [ 'stream' => 'php://stderr', @@ -99,6 +92,10 @@ return [ 'testing' => [ 'driver' => 'testing', ], + + 'emergency' => [ + 'path' => storage_path('logs/laravel.log'), + ], ], // Failed Login Message diff --git a/app/Config/queue.php b/app/Config/queue.php index 0c79fcdd2..0f5ee3ce5 100644 --- a/app/Config/queue.php +++ b/app/Config/queue.php @@ -22,25 +22,29 @@ return [ ], 'database' => [ - 'driver' => 'database', - 'table' => 'jobs', - 'queue' => 'default', - 'retry_after' => 90, + 'driver' => 'database', + 'table' => 'jobs', + 'queue' => 'default', + 'retry_after' => 90, + 'after_commit' => false, ], 'redis' => [ - 'driver' => 'redis', - 'connection' => 'default', - 'queue' => env('REDIS_QUEUE', 'default'), - 'retry_after' => 90, - 'block_for' => null, + 'driver' => 'redis', + 'connection' => 'default', + 'queue' => env('REDIS_QUEUE', 'default'), + 'retry_after' => 90, + 'block_for' => null, + 'after_commit' => false, ], ], // Failed queue job logging 'failed' => [ - 'database' => 'mysql', 'table' => 'failed_jobs', + 'driver' => 'database-uuids', + 'database' => 'mysql', + 'table' => 'failed_jobs', ], ]; diff --git a/app/Entities/Models/Book.php b/app/Entities/Models/Book.php index 1e4591bd7..982df5c90 100644 --- a/app/Entities/Models/Book.php +++ b/app/Entities/Models/Book.php @@ -4,6 +4,7 @@ namespace BookStack\Entities\Models; use BookStack\Uploads\Image; use Exception; +use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\HasMany; @@ -21,6 +22,8 @@ use Illuminate\Support\Collection; */ class Book extends Entity implements HasCoverImage { + use HasFactory; + public $searchFactor = 2; protected $fillable = ['name', 'description']; diff --git a/app/Entities/Models/Bookshelf.php b/app/Entities/Models/Bookshelf.php index f427baf49..8fe9dbe41 100644 --- a/app/Entities/Models/Bookshelf.php +++ b/app/Entities/Models/Bookshelf.php @@ -3,11 +3,14 @@ namespace BookStack\Entities\Models; use BookStack\Uploads\Image; +use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsToMany; class Bookshelf extends Entity implements HasCoverImage { + use HasFactory; + protected $table = 'bookshelves'; public $searchFactor = 3; diff --git a/app/Entities/Models/Chapter.php b/app/Entities/Models/Chapter.php index f6f8427a3..abf496b44 100644 --- a/app/Entities/Models/Chapter.php +++ b/app/Entities/Models/Chapter.php @@ -2,6 +2,7 @@ namespace BookStack\Entities\Models; +use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Support\Collection; /** @@ -12,6 +13,8 @@ use Illuminate\Support\Collection; */ class Chapter extends BookChild { + use HasFactory; + public $searchFactor = 1.3; protected $fillable = ['name', 'description', 'priority', 'book_id']; diff --git a/app/Entities/Models/Page.php b/app/Entities/Models/Page.php index 452965667..fbe0db41b 100644 --- a/app/Entities/Models/Page.php +++ b/app/Entities/Models/Page.php @@ -6,6 +6,7 @@ use BookStack\Entities\Tools\PageContent; use BookStack\Uploads\Attachment; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Collection; +use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\HasMany; use Permissions; @@ -25,6 +26,8 @@ use Permissions; */ class Page extends BookChild { + use HasFactory; + public static $listAttributes = ['name', 'id', 'slug', 'book_id', 'chapter_id', 'draft', 'template', 'text', 'created_at', 'updated_at', 'priority']; public static $contentAttributes = ['name', 'id', 'slug', 'book_id', 'chapter_id', 'draft', 'template', 'html', 'text', 'created_at', 'updated_at', 'priority']; diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index 63b5cfc5a..3b4ad4a4d 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -28,6 +28,7 @@ class Handler extends ExceptionHandler * @var array */ protected $dontFlash = [ + 'current_password', 'password', 'password_confirmation', ]; diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index 7a09493af..91dbdd963 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -11,7 +11,7 @@ class Kernel extends HttpKernel * These middleware are run during every request to your application. */ protected $middleware = [ - \BookStack\Http\Middleware\CheckForMaintenanceMode::class, + \BookStack\Http\Middleware\PreventRequestsDuringMaintenance::class, \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class, \BookStack\Http\Middleware\TrimStrings::class, \BookStack\Http\Middleware\TrustProxies::class, diff --git a/app/Http/Middleware/CheckForMaintenanceMode.php b/app/Http/Middleware/PreventRequestsDuringMaintenance.php similarity index 58% rename from app/Http/Middleware/CheckForMaintenanceMode.php rename to app/Http/Middleware/PreventRequestsDuringMaintenance.php index 0c7683836..dfb9592e1 100644 --- a/app/Http/Middleware/CheckForMaintenanceMode.php +++ b/app/Http/Middleware/PreventRequestsDuringMaintenance.php @@ -2,9 +2,9 @@ namespace BookStack\Http\Middleware; -use Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode as Middleware; +use Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance as Middleware; -class CheckForMaintenanceMode extends Middleware +class PreventRequestsDuringMaintenance extends Middleware { /** * The URIs that should be reachable while maintenance mode is enabled. diff --git a/app/Http/Middleware/RedirectIfAuthenticated.php b/app/Http/Middleware/RedirectIfAuthenticated.php index 6853809ea..76e64a3b9 100644 --- a/app/Http/Middleware/RedirectIfAuthenticated.php +++ b/app/Http/Middleware/RedirectIfAuthenticated.php @@ -2,45 +2,31 @@ namespace BookStack\Http\Middleware; +use BookStack\Providers\RouteServiceProvider; use Closure; -use Illuminate\Contracts\Auth\Guard; +use Illuminate\Http\Request; +use Illuminate\Support\Facades\Auth; class RedirectIfAuthenticated { - /** - * The Guard implementation. - * - * @var Guard - */ - protected $auth; - - /** - * Create a new filter instance. - * - * @param Guard $auth - * - * @return void - */ - public function __construct(Guard $auth) - { - $this->auth = $auth; - } - /** * Handle an incoming request. * - * @param \Illuminate\Http\Request $request - * @param \Closure $next - * + * @param \Illuminate\Http\Request $request + * @param \Closure $next + * @param string|null ...$guards * @return mixed */ - public function handle($request, Closure $next) + public function handle(Request $request, Closure $next, ...$guards) { - $requireConfirmation = setting('registration-confirmation'); - if ($this->auth->check() && (!$requireConfirmation || ($requireConfirmation && $this->auth->user()->email_confirmed))) { - return redirect('/'); + $guards = empty($guards) ? [null] : $guards; + + foreach ($guards as $guard) { + if (Auth::guard($guard)->check()) { + return redirect(RouteServiceProvider::HOME); + } } return $next($request); } -} +} \ No newline at end of file diff --git a/app/Http/Middleware/TrustHosts.php b/app/Http/Middleware/TrustHosts.php index b0550cfc7..7bd89ee51 100644 --- a/app/Http/Middleware/TrustHosts.php +++ b/app/Http/Middleware/TrustHosts.php @@ -1,6 +1,6 @@ configureRateLimiting(); - /** - * Define the routes for the application. - * - * @return void - */ - public function map() - { - $this->mapWebRoutes(); - $this->mapApiRoutes(); + $this->routes(function () { + $this->mapWebRoutes(); + $this->mapApiRoutes(); + }); } /** @@ -71,4 +76,16 @@ class RouteServiceProvider extends ServiceProvider require base_path('routes/api.php'); }); } + + /** + * Configure the rate limiters for the application. + * + * @return void + */ + protected function configureRateLimiting() + { + RateLimiter::for('api', function (Request $request) { + return Limit::perMinute(60)->by(optional($request->user())->id ?: $request->ip()); + }); + } } diff --git a/app/Uploads/Image.php b/app/Uploads/Image.php index 4e0abc85b..bdf10f080 100644 --- a/app/Uploads/Image.php +++ b/app/Uploads/Image.php @@ -5,6 +5,7 @@ namespace BookStack\Uploads; use BookStack\Entities\Models\Page; use BookStack\Model; use BookStack\Traits\HasCreatorAndUpdater; +use Illuminate\Database\Eloquent\Factories\HasFactory; /** * @property int $id @@ -18,6 +19,7 @@ use BookStack\Traits\HasCreatorAndUpdater; */ class Image extends Model { + use HasFactory; use HasCreatorAndUpdater; protected $fillable = ['name']; diff --git a/composer.json b/composer.json index b50cee762..c1d5c1e4b 100644 --- a/composer.json +++ b/composer.json @@ -20,11 +20,13 @@ "barryvdh/laravel-dompdf": "^0.9.0", "barryvdh/laravel-snappy": "^0.4.8", "doctrine/dbal": "^3.1", - "fideloper/proxy": "^4.4.1", "filp/whoops": "^2.14", + "guzzlehttp/guzzle": "^7.4", "intervention/image": "^2.7", - "laravel/framework": "^7.29", + "laravel/framework": "^8.68", "laravel/socialite": "^5.2", + "laravel/tinker": "^2.5", + "laravel/ui": "^3.3", "league/commonmark": "^1.5", "league/flysystem-aws-s3-v3": "^1.0.29", "league/html-to-markdown": "^5.0.0", @@ -32,33 +34,28 @@ "onelogin/php-saml": "^4.0", "phpseclib/phpseclib": "~3.0", "pragmarx/google2fa": "^8.0", - "predis/predis": "^1.1.6", + "predis/predis": "^1.1", "socialiteproviders/discord": "^4.1", "socialiteproviders/gitlab": "^4.1", "socialiteproviders/microsoft-azure": "^4.1", "socialiteproviders/okta": "^4.1", "socialiteproviders/slack": "^4.1", "socialiteproviders/twitch": "^5.3", - "ssddanbrown/htmldiff": "^1.0.1", - "laravel/ui": "^2.5", - "guzzlehttp/guzzle": "^7.4.0", - "laravel/tinker": "^2.5" + "ssddanbrown/htmldiff": "^1.0.1" }, "require-dev": { "barryvdh/laravel-debugbar": "^3.6", "fakerphp/faker": "^1.13.0", - "mockery/mockery": "^1.3.3", + "mockery/mockery": "^1.4.2", "phpunit/phpunit": "^9.5.3", "symfony/dom-crawler": "^5.3", - "nunomaduro/collision": "^4.3" + "nunomaduro/collision": "^5.0" }, "autoload": { - "classmap": [ - "database/seeds", - "database/factories" - ], "psr-4": { - "BookStack\\": "app/" + "BookStack\\": "app/", + "Database\\Factories\\": "database/factories/", + "Database\\Seeders\\": "database/seeders/" }, "files": [ "app/helpers.php" @@ -70,6 +67,10 @@ } }, "scripts": { + "post-autoload-dump": [ + "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump", + "@php artisan package:discover --ansi" + ], "post-root-package-install": [ "@php -r \"file_exists('.env') || copy('.env.example', '.env');\"" ], @@ -83,10 +84,6 @@ "@php artisan cache:clear", "@php artisan view:clear" ], - "post-autoload-dump": [ - "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump", - "@php artisan package:discover --ansi" - ], "refresh-test-database": [ "@php artisan migrate:refresh --database=mysql_testing", "@php artisan db:seed --class=DummyContentSeeder --database=mysql_testing" diff --git a/composer.lock b/composer.lock index f07d61062..17e57df71 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "491a3de7d49182613d0c81032a7001e1", + "content-hash": "9a5d92382b2955dd7de41de5fa9f86b5", "packages": [ { "name": "aws/aws-crt-php", @@ -58,16 +58,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.199.4", + "version": "3.199.7", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "047f6ce04b1de9320ca00bf393d6f03b9d036fa5" + "reference": "fda176884d2952cffc7e67209470bff49609339c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/047f6ce04b1de9320ca00bf393d6f03b9d036fa5", - "reference": "047f6ce04b1de9320ca00bf393d6f03b9d036fa5", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/fda176884d2952cffc7e67209470bff49609339c", + "reference": "fda176884d2952cffc7e67209470bff49609339c", "shasum": "" }, "require": { @@ -143,9 +143,9 @@ "support": { "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.199.4" + "source": "https://github.com/aws/aws-sdk-php/tree/3.199.7" }, - "time": "2021-10-26T18:14:35+00:00" + "time": "2021-10-29T18:25:02+00:00" }, { "name": "bacon/bacon-qr-code", @@ -1101,30 +1101,32 @@ }, { "name": "dragonmantank/cron-expression", - "version": "v2.3.1", + "version": "v3.1.0", "source": { "type": "git", "url": "https://github.com/dragonmantank/cron-expression.git", - "reference": "65b2d8ee1f10915efb3b55597da3404f096acba2" + "reference": "7a8c6e56ab3ffcc538d05e8155bb42269abf1a0c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/65b2d8ee1f10915efb3b55597da3404f096acba2", - "reference": "65b2d8ee1f10915efb3b55597da3404f096acba2", + "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/7a8c6e56ab3ffcc538d05e8155bb42269abf1a0c", + "reference": "7a8c6e56ab3ffcc538d05e8155bb42269abf1a0c", "shasum": "" }, "require": { - "php": "^7.0|^8.0" + "php": "^7.2|^8.0", + "webmozart/assert": "^1.7.0" + }, + "replace": { + "mtdowling/cron-expression": "^1.0" }, "require-dev": { - "phpunit/phpunit": "^6.4|^7.0|^8.0|^9.0" + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^0.12", + "phpstan/phpstan-webmozart-assert": "^0.12.7", + "phpunit/phpunit": "^7.0|^8.0|^9.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.3-dev" - } - }, "autoload": { "psr-4": { "Cron\\": "src/Cron/" @@ -1135,11 +1137,6 @@ "MIT" ], "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - }, { "name": "Chris Tankersley", "email": "chris@ctankersley.com", @@ -1153,7 +1150,7 @@ ], "support": { "issues": "https://github.com/dragonmantank/cron-expression/issues", - "source": "https://github.com/dragonmantank/cron-expression/tree/v2.3.1" + "source": "https://github.com/dragonmantank/cron-expression/tree/v3.1.0" }, "funding": [ { @@ -1161,7 +1158,7 @@ "type": "github" } ], - "time": "2020-10-13T00:52:37+00:00" + "time": "2020-11-24T19:55:57+00:00" }, { "name": "egulias/email-validator", @@ -1231,64 +1228,6 @@ ], "time": "2020-12-29T14:50:06+00:00" }, - { - "name": "fideloper/proxy", - "version": "4.4.1", - "source": { - "type": "git", - "url": "https://github.com/fideloper/TrustedProxy.git", - "reference": "c073b2bd04d1c90e04dc1b787662b558dd65ade0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/fideloper/TrustedProxy/zipball/c073b2bd04d1c90e04dc1b787662b558dd65ade0", - "reference": "c073b2bd04d1c90e04dc1b787662b558dd65ade0", - "shasum": "" - }, - "require": { - "illuminate/contracts": "^5.0|^6.0|^7.0|^8.0|^9.0", - "php": ">=5.4.0" - }, - "require-dev": { - "illuminate/http": "^5.0|^6.0|^7.0|^8.0|^9.0", - "mockery/mockery": "^1.0", - "phpunit/phpunit": "^6.0" - }, - "type": "library", - "extra": { - "laravel": { - "providers": [ - "Fideloper\\Proxy\\TrustedProxyServiceProvider" - ] - } - }, - "autoload": { - "psr-4": { - "Fideloper\\Proxy\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Chris Fidao", - "email": "fideloper@gmail.com" - } - ], - "description": "Set trusted proxies for Laravel", - "keywords": [ - "load balancing", - "proxy", - "trusted proxy" - ], - "support": { - "issues": "https://github.com/fideloper/TrustedProxy/issues", - "source": "https://github.com/fideloper/TrustedProxy/tree/4.4.1" - }, - "time": "2020-10-22T13:48:01+00:00" - }, { "name": "filp/whoops", "version": "2.14.4", @@ -1360,6 +1299,67 @@ ], "time": "2021-10-03T12:00:00+00:00" }, + { + "name": "graham-campbell/result-type", + "version": "v1.0.3", + "source": { + "type": "git", + "url": "https://github.com/GrahamCampbell/Result-Type.git", + "reference": "296c015dc30ec4322168c5ad3ee5cc11dae827ac" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/296c015dc30ec4322168c5ad3ee5cc11dae827ac", + "reference": "296c015dc30ec4322168c5ad3ee5cc11dae827ac", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0", + "phpoption/phpoption": "^1.8" + }, + "require-dev": { + "phpunit/phpunit": "^6.5.14 || ^7.5.20 || ^8.5.19 || ^9.5.8" + }, + "type": "library", + "autoload": { + "psr-4": { + "GrahamCampbell\\ResultType\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk" + } + ], + "description": "An Implementation Of The Result Type", + "keywords": [ + "Graham Campbell", + "GrahamCampbell", + "Result Type", + "Result-Type", + "result" + ], + "support": { + "issues": "https://github.com/GrahamCampbell/Result-Type/issues", + "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.0.3" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/graham-campbell/result-type", + "type": "tidelift" + } + ], + "time": "2021-10-17T19:48:54+00:00" + }, { "name": "guzzlehttp/guzzle", "version": "7.4.0", @@ -1843,60 +1843,63 @@ }, { "name": "laravel/framework", - "version": "v7.30.4", + "version": "v8.68.1", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "9dd38140dc2924daa1a020a3d7a45f9ceff03df3" + "reference": "abe985ff1fb82dd04aab03bc1dc56e83fe61a59f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/9dd38140dc2924daa1a020a3d7a45f9ceff03df3", - "reference": "9dd38140dc2924daa1a020a3d7a45f9ceff03df3", + "url": "https://api.github.com/repos/laravel/framework/zipball/abe985ff1fb82dd04aab03bc1dc56e83fe61a59f", + "reference": "abe985ff1fb82dd04aab03bc1dc56e83fe61a59f", "shasum": "" }, "require": { "doctrine/inflector": "^1.4|^2.0", - "dragonmantank/cron-expression": "^2.3.1", + "dragonmantank/cron-expression": "^3.0.2", "egulias/email-validator": "^2.1.10", "ext-json": "*", "ext-mbstring": "*", "ext-openssl": "*", - "league/commonmark": "^1.3", + "laravel/serializable-closure": "^1.0", + "league/commonmark": "^1.3|^2.0.2", "league/flysystem": "^1.1", "monolog/monolog": "^2.0", - "nesbot/carbon": "^2.31", + "nesbot/carbon": "^2.53.1", "opis/closure": "^3.6", - "php": "^7.2.5|^8.0", + "php": "^7.3|^8.0", "psr/container": "^1.0", + "psr/log": "^1.0 || ^2.0", "psr/simple-cache": "^1.0", - "ramsey/uuid": "^3.7|^4.0", - "swiftmailer/swiftmailer": "^6.0", - "symfony/console": "^5.0", - "symfony/error-handler": "^5.0", - "symfony/finder": "^5.0", - "symfony/http-foundation": "^5.0", - "symfony/http-kernel": "^5.0", - "symfony/mime": "^5.0", - "symfony/polyfill-php73": "^1.17", - "symfony/process": "^5.0", - "symfony/routing": "^5.0", - "symfony/var-dumper": "^5.0", + "ramsey/uuid": "^4.2.2", + "swiftmailer/swiftmailer": "^6.3", + "symfony/console": "^5.1.4", + "symfony/error-handler": "^5.1.4", + "symfony/finder": "^5.1.4", + "symfony/http-foundation": "^5.1.4", + "symfony/http-kernel": "^5.1.4", + "symfony/mime": "^5.1.4", + "symfony/process": "^5.1.4", + "symfony/routing": "^5.1.4", + "symfony/var-dumper": "^5.1.4", "tijsverkoyen/css-to-inline-styles": "^2.2.2", - "vlucas/phpdotenv": "^4.0", + "vlucas/phpdotenv": "^5.2", "voku/portable-ascii": "^1.4.8" }, "conflict": { "tightenco/collect": "<5.5.33" }, "provide": { - "psr/container-implementation": "1.0" + "psr/container-implementation": "1.0", + "psr/simple-cache-implementation": "1.0" }, "replace": { "illuminate/auth": "self.version", "illuminate/broadcasting": "self.version", "illuminate/bus": "self.version", "illuminate/cache": "self.version", + "illuminate/collections": "self.version", "illuminate/config": "self.version", "illuminate/console": "self.version", "illuminate/container": "self.version", @@ -1909,6 +1912,7 @@ "illuminate/hashing": "self.version", "illuminate/http": "self.version", "illuminate/log": "self.version", + "illuminate/macroable": "self.version", "illuminate/mail": "self.version", "illuminate/notifications": "self.version", "illuminate/pagination": "self.version", @@ -1924,22 +1928,23 @@ "illuminate/view": "self.version" }, "require-dev": { - "aws/aws-sdk-php": "^3.155", - "doctrine/dbal": "^2.6", - "filp/whoops": "^2.8", - "guzzlehttp/guzzle": "^6.3.1|^7.0.1", + "aws/aws-sdk-php": "^3.198.1", + "doctrine/dbal": "^2.13.3|^3.1.2", + "filp/whoops": "^2.14.3", + "guzzlehttp/guzzle": "^6.5.5|^7.0.1", "league/flysystem-cached-adapter": "^1.0", - "mockery/mockery": "~1.3.3|^1.4.2", - "moontoast/math": "^1.1", - "orchestra/testbench-core": "^5.8", + "mockery/mockery": "^1.4.4", + "orchestra/testbench-core": "^6.23", "pda/pheanstalk": "^4.0", - "phpunit/phpunit": "^8.4|^9.3.3", - "predis/predis": "^1.1.1", - "symfony/cache": "^5.0" + "phpunit/phpunit": "^8.5.19|^9.5.8", + "predis/predis": "^1.1.9", + "symfony/cache": "^5.1.4" }, "suggest": { - "aws/aws-sdk-php": "Required to use the SQS queue driver, DynamoDb failed job storage and SES mail driver (^3.155).", - "doctrine/dbal": "Required to rename columns and drop SQLite columns (^2.6).", + "aws/aws-sdk-php": "Required to use the SQS queue driver, DynamoDb failed job storage and SES mail driver (^3.198.1).", + "brianium/paratest": "Required to run tests in parallel (^6.0).", + "doctrine/dbal": "Required to rename columns and drop SQLite columns (^2.13.3|^3.1.2).", + "ext-bcmath": "Required to use the multiple_of validation rule.", "ext-ftp": "Required to use the Flysystem FTP driver.", "ext-gd": "Required to use Illuminate\\Http\\Testing\\FileFactory::image().", "ext-memcached": "Required to use the memcache cache driver.", @@ -1947,38 +1952,43 @@ "ext-posix": "Required to use all features of the queue worker.", "ext-redis": "Required to use the Redis cache and queue drivers (^4.0|^5.0).", "fakerphp/faker": "Required to use the eloquent factory builder (^1.9.1).", - "filp/whoops": "Required for friendly error pages in development (^2.8).", - "guzzlehttp/guzzle": "Required to use the HTTP Client, Mailgun mail driver and the ping methods on schedules (^6.3.1|^7.0.1).", + "filp/whoops": "Required for friendly error pages in development (^2.14.3).", + "guzzlehttp/guzzle": "Required to use the HTTP Client, Mailgun mail driver and the ping methods on schedules (^6.5.5|^7.0.1).", "laravel/tinker": "Required to use the tinker console command (^2.0).", "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^1.0).", "league/flysystem-cached-adapter": "Required to use the Flysystem cache (^1.0).", "league/flysystem-sftp": "Required to use the Flysystem SFTP driver (^1.0).", - "mockery/mockery": "Required to use mocking (~1.3.3|^1.4.2).", - "moontoast/math": "Required to use ordered UUIDs (^1.1).", + "mockery/mockery": "Required to use mocking (^1.4.4).", "nyholm/psr7": "Required to use PSR-7 bridging features (^1.2).", "pda/pheanstalk": "Required to use the beanstalk queue driver (^4.0).", - "phpunit/phpunit": "Required to use assertions and run tests (^8.4|^9.3.3).", - "predis/predis": "Required to use the predis connector (^1.1.2).", + "phpunit/phpunit": "Required to use assertions and run tests (^8.5.19|^9.5.8).", + "predis/predis": "Required to use the predis connector (^1.1.9).", "psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).", - "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^4.0).", - "symfony/cache": "Required to PSR-6 cache bridge (^5.0).", - "symfony/filesystem": "Required to create relative storage directory symbolic links (^5.0).", + "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^4.0|^5.0|^6.0).", + "symfony/cache": "Required to PSR-6 cache bridge (^5.1.4).", + "symfony/filesystem": "Required to enable support for relative symbolic links (^5.1.4).", "symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^2.0).", "wildbit/swiftmailer-postmark": "Required to use Postmark mail driver (^3.0)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "7.x-dev" + "dev-master": "8.x-dev" } }, "autoload": { "files": [ + "src/Illuminate/Collections/helpers.php", + "src/Illuminate/Events/functions.php", "src/Illuminate/Foundation/helpers.php", "src/Illuminate/Support/helpers.php" ], "psr-4": { - "Illuminate\\": "src/Illuminate/" + "Illuminate\\": "src/Illuminate/", + "Illuminate\\Support\\": [ + "src/Illuminate/Macroable/", + "src/Illuminate/Collections/" + ] } }, "notification-url": "https://packagist.org/downloads/", @@ -2001,7 +2011,66 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2021-01-21T14:10:48+00:00" + "time": "2021-10-27T12:31:46+00:00" + }, + { + "name": "laravel/serializable-closure", + "version": "v1.0.3", + "source": { + "type": "git", + "url": "https://github.com/laravel/serializable-closure.git", + "reference": "6cfc678735f22ccedad761b8cae2bab14c3d8e5b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/6cfc678735f22ccedad761b8cae2bab14c3d8e5b", + "reference": "6cfc678735f22ccedad761b8cae2bab14c3d8e5b", + "shasum": "" + }, + "require": { + "php": "^7.3|^8.0" + }, + "require-dev": { + "pestphp/pest": "^1.18", + "phpstan/phpstan": "^0.12.98", + "symfony/var-dumper": "^5.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Laravel\\SerializableClosure\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + }, + { + "name": "Nuno Maduro", + "email": "nuno@laravel.com" + } + ], + "description": "Laravel Serializable Closure provides an easy and secure way to serialize closures in PHP.", + "keywords": [ + "closure", + "laravel", + "serializable" + ], + "support": { + "issues": "https://github.com/laravel/serializable-closure/issues", + "source": "https://github.com/laravel/serializable-closure" + }, + "time": "2021-10-07T14:00:57+00:00" }, { "name": "laravel/socialite", @@ -2142,26 +2211,30 @@ }, { "name": "laravel/ui", - "version": "v2.5.0", + "version": "v3.3.0", "source": { "type": "git", "url": "https://github.com/laravel/ui.git", - "reference": "d01a705763c243b07be795e9d1bb47f89260f73d" + "reference": "07d725813350c695c779382cbd6dac0ab8665537" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/ui/zipball/d01a705763c243b07be795e9d1bb47f89260f73d", - "reference": "d01a705763c243b07be795e9d1bb47f89260f73d", + "url": "https://api.github.com/repos/laravel/ui/zipball/07d725813350c695c779382cbd6dac0ab8665537", + "reference": "07d725813350c695c779382cbd6dac0ab8665537", "shasum": "" }, "require": { - "illuminate/console": "^7.0", - "illuminate/filesystem": "^7.0", - "illuminate/support": "^7.0", - "php": "^7.2.5|^8.0" + "illuminate/console": "^8.42", + "illuminate/filesystem": "^8.42", + "illuminate/support": "^8.42", + "illuminate/validation": "^8.42", + "php": "^7.3|^8.0" }, "type": "library", "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + }, "laravel": { "providers": [ "Laravel\\Ui\\UiServiceProvider" @@ -2190,10 +2263,9 @@ "ui" ], "support": { - "issues": "https://github.com/laravel/ui/issues", - "source": "https://github.com/laravel/ui/tree/v2.5.0" + "source": "https://github.com/laravel/ui/tree/v3.3.0" }, - "time": "2020-11-03T19:45:19+00:00" + "time": "2021-05-25T16:45:33+00:00" }, { "name": "league/commonmark", @@ -3436,16 +3508,16 @@ }, { "name": "phpseclib/phpseclib", - "version": "3.0.10", + "version": "3.0.11", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "62fcc5a94ac83b1506f52d7558d828617fac9187" + "reference": "6e794226a35159eb06f355efe59a0075a16551dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/62fcc5a94ac83b1506f52d7558d828617fac9187", - "reference": "62fcc5a94ac83b1506f52d7558d828617fac9187", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/6e794226a35159eb06f355efe59a0075a16551dd", + "reference": "6e794226a35159eb06f355efe59a0075a16551dd", "shasum": "" }, "require": { @@ -3527,7 +3599,7 @@ ], "support": { "issues": "https://github.com/phpseclib/phpseclib/issues", - "source": "https://github.com/phpseclib/phpseclib/tree/3.0.10" + "source": "https://github.com/phpseclib/phpseclib/tree/3.0.11" }, "funding": [ { @@ -3543,7 +3615,7 @@ "type": "tidelift" } ], - "time": "2021-08-16T04:24:45+00:00" + "time": "2021-10-27T03:01:46+00:00" }, { "name": "pragmarx/google2fa", @@ -4851,16 +4923,16 @@ }, { "name": "symfony/console", - "version": "v5.3.7", + "version": "v5.3.10", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "8b1008344647462ae6ec57559da166c2bfa5e16a" + "reference": "d4e409d9fbcfbf71af0e5a940abb7b0b4bad0bd3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/8b1008344647462ae6ec57559da166c2bfa5e16a", - "reference": "8b1008344647462ae6ec57559da166c2bfa5e16a", + "url": "https://api.github.com/repos/symfony/console/zipball/d4e409d9fbcfbf71af0e5a940abb7b0b4bad0bd3", + "reference": "d4e409d9fbcfbf71af0e5a940abb7b0b4bad0bd3", "shasum": "" }, "require": { @@ -4930,7 +5002,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v5.3.7" + "source": "https://github.com/symfony/console/tree/v5.3.10" }, "funding": [ { @@ -4946,7 +5018,7 @@ "type": "tidelift" } ], - "time": "2021-08-25T20:02:16+00:00" + "time": "2021-10-26T09:30:15+00:00" }, { "name": "symfony/css-selector", @@ -5455,16 +5527,16 @@ }, { "name": "symfony/http-foundation", - "version": "v5.3.7", + "version": "v5.3.10", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "e36c8e5502b4f3f0190c675f1c1f1248a64f04e5" + "reference": "9f34f02e8a5fdc7a56bafe011cea1ce97300e54c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/e36c8e5502b4f3f0190c675f1c1f1248a64f04e5", - "reference": "e36c8e5502b4f3f0190c675f1c1f1248a64f04e5", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/9f34f02e8a5fdc7a56bafe011cea1ce97300e54c", + "reference": "9f34f02e8a5fdc7a56bafe011cea1ce97300e54c", "shasum": "" }, "require": { @@ -5508,7 +5580,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v5.3.7" + "source": "https://github.com/symfony/http-foundation/tree/v5.3.10" }, "funding": [ { @@ -5524,20 +5596,20 @@ "type": "tidelift" } ], - "time": "2021-08-27T11:20:35+00:00" + "time": "2021-10-11T15:41:55+00:00" }, { "name": "symfony/http-kernel", - "version": "v5.3.9", + "version": "v5.3.10", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "ceaf46a992f60e90645e7279825a830f733a17c5" + "reference": "703e4079920468e9522b72cf47fd76ce8d795e86" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/ceaf46a992f60e90645e7279825a830f733a17c5", - "reference": "ceaf46a992f60e90645e7279825a830f733a17c5", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/703e4079920468e9522b72cf47fd76ce8d795e86", + "reference": "703e4079920468e9522b72cf47fd76ce8d795e86", "shasum": "" }, "require": { @@ -5620,7 +5692,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v5.3.9" + "source": "https://github.com/symfony/http-kernel/tree/v5.3.10" }, "funding": [ { @@ -5636,7 +5708,7 @@ "type": "tidelift" } ], - "time": "2021-09-28T10:25:11+00:00" + "time": "2021-10-29T08:36:48+00:00" }, { "name": "symfony/mime", @@ -6762,16 +6834,16 @@ }, { "name": "symfony/string", - "version": "v5.3.7", + "version": "v5.3.10", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "8d224396e28d30f81969f083a58763b8b9ceb0a5" + "reference": "d70c35bb20bbca71fc4ab7921e3c6bda1a82a60c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/8d224396e28d30f81969f083a58763b8b9ceb0a5", - "reference": "8d224396e28d30f81969f083a58763b8b9ceb0a5", + "url": "https://api.github.com/repos/symfony/string/zipball/d70c35bb20bbca71fc4ab7921e3c6bda1a82a60c", + "reference": "d70c35bb20bbca71fc4ab7921e3c6bda1a82a60c", "shasum": "" }, "require": { @@ -6825,7 +6897,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v5.3.7" + "source": "https://github.com/symfony/string/tree/v5.3.10" }, "funding": [ { @@ -6841,20 +6913,20 @@ "type": "tidelift" } ], - "time": "2021-08-26T08:00:08+00:00" + "time": "2021-10-27T18:21:46+00:00" }, { "name": "symfony/translation", - "version": "v5.3.9", + "version": "v5.3.10", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "6e69f3551c1a3356cf6ea8d019bf039a0f8b6886" + "reference": "6ef197aea2ac8b9cd63e0da7522b3771714035aa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/6e69f3551c1a3356cf6ea8d019bf039a0f8b6886", - "reference": "6e69f3551c1a3356cf6ea8d019bf039a0f8b6886", + "url": "https://api.github.com/repos/symfony/translation/zipball/6ef197aea2ac8b9cd63e0da7522b3771714035aa", + "reference": "6ef197aea2ac8b9cd63e0da7522b3771714035aa", "shasum": "" }, "require": { @@ -6920,7 +6992,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v5.3.9" + "source": "https://github.com/symfony/translation/tree/v5.3.10" }, "funding": [ { @@ -6936,7 +7008,7 @@ "type": "tidelift" } ], - "time": "2021-08-26T08:22:53+00:00" + "time": "2021-10-10T06:43:24+00:00" }, { "name": "symfony/translation-contracts", @@ -7018,16 +7090,16 @@ }, { "name": "symfony/var-dumper", - "version": "v5.3.8", + "version": "v5.3.10", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "eaaea4098be1c90c8285543e1356a09c8aa5c8da" + "reference": "875432adb5f5570fff21036fd22aee244636b7d1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/eaaea4098be1c90c8285543e1356a09c8aa5c8da", - "reference": "eaaea4098be1c90c8285543e1356a09c8aa5c8da", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/875432adb5f5570fff21036fd22aee244636b7d1", + "reference": "875432adb5f5570fff21036fd22aee244636b7d1", "shasum": "" }, "require": { @@ -7086,7 +7158,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v5.3.8" + "source": "https://github.com/symfony/var-dumper/tree/v5.3.10" }, "funding": [ { @@ -7102,7 +7174,7 @@ "type": "tidelift" } ], - "time": "2021-09-24T15:59:58+00:00" + "time": "2021-10-26T09:30:15+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", @@ -7159,37 +7231,39 @@ }, { "name": "vlucas/phpdotenv", - "version": "v4.2.1", + "version": "v5.3.1", "source": { "type": "git", "url": "https://github.com/vlucas/phpdotenv.git", - "reference": "d38f4d1edcbe32515a0ad593cbd4c858e337263c" + "reference": "accaddf133651d4b5cf81a119f25296736ffc850" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/d38f4d1edcbe32515a0ad593cbd4c858e337263c", - "reference": "d38f4d1edcbe32515a0ad593cbd4c858e337263c", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/accaddf133651d4b5cf81a119f25296736ffc850", + "reference": "accaddf133651d4b5cf81a119f25296736ffc850", "shasum": "" }, "require": { - "php": "^5.5.9 || ^7.0 || ^8.0", - "phpoption/phpoption": "^1.7.3", - "symfony/polyfill-ctype": "^1.17" + "ext-pcre": "*", + "graham-campbell/result-type": "^1.0.2", + "php": "^7.1.3 || ^8.0", + "phpoption/phpoption": "^1.8", + "symfony/polyfill-ctype": "^1.23", + "symfony/polyfill-mbstring": "^1.23.1", + "symfony/polyfill-php80": "^1.23.1" }, "require-dev": { "bamarni/composer-bin-plugin": "^1.4.1", "ext-filter": "*", - "ext-pcre": "*", - "phpunit/phpunit": "^4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.21" + "phpunit/phpunit": "^7.5.20 || ^8.5.21 || ^9.5.10" }, "suggest": { - "ext-filter": "Required to use the boolean validator.", - "ext-pcre": "Required to use most of the library." + "ext-filter": "Required to use the boolean validator." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.2-dev" + "dev-master": "5.3-dev" } }, "autoload": { @@ -7219,7 +7293,7 @@ ], "support": { "issues": "https://github.com/vlucas/phpdotenv/issues", - "source": "https://github.com/vlucas/phpdotenv/tree/v4.2.1" + "source": "https://github.com/vlucas/phpdotenv/tree/v5.3.1" }, "funding": [ { @@ -7231,7 +7305,7 @@ "type": "tidelift" } ], - "time": "2021-10-02T19:17:08+00:00" + "time": "2021-10-02T19:24:42+00:00" }, { "name": "voku/portable-ascii", @@ -7306,6 +7380,64 @@ } ], "time": "2020-11-12T00:07:28+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.10.0", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/6964c76c7804814a842473e0c8fd15bab0f18e25", + "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<4.6.1 || 4.6.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.13" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.10.0" + }, + "time": "2021-03-09T10:59:23+00:00" } ], "packages-dev": [ @@ -7829,35 +7961,34 @@ }, { "name": "nunomaduro/collision", - "version": "v4.3.0", + "version": "v5.10.0", "source": { "type": "git", "url": "https://github.com/nunomaduro/collision.git", - "reference": "7c125dc2463f3e144ddc7e05e63077109508c94e" + "reference": "3004cfa49c022183395eabc6d0e5207dfe498d00" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/collision/zipball/7c125dc2463f3e144ddc7e05e63077109508c94e", - "reference": "7c125dc2463f3e144ddc7e05e63077109508c94e", + "url": "https://api.github.com/repos/nunomaduro/collision/zipball/3004cfa49c022183395eabc6d0e5207dfe498d00", + "reference": "3004cfa49c022183395eabc6d0e5207dfe498d00", "shasum": "" }, "require": { "facade/ignition-contracts": "^1.0", - "filp/whoops": "^2.4", - "php": "^7.2.5 || ^8.0", + "filp/whoops": "^2.14.3", + "php": "^7.3 || ^8.0", "symfony/console": "^5.0" }, "require-dev": { - "facade/ignition": "^2.0", - "fideloper/proxy": "^4.2", - "friendsofphp/php-cs-fixer": "^2.16", - "fruitcake/laravel-cors": "^1.0", - "laravel/framework": "^7.0", - "laravel/tinker": "^2.0", - "nunomaduro/larastan": "^0.6", - "orchestra/testbench": "^5.0", - "phpstan/phpstan": "^0.12.3", - "phpunit/phpunit": "^8.5.1 || ^9.0" + "brianium/paratest": "^6.1", + "fideloper/proxy": "^4.4.1", + "fruitcake/laravel-cors": "^2.0.3", + "laravel/framework": "8.x-dev", + "nunomaduro/larastan": "^0.6.2", + "nunomaduro/mock-final-classes": "^1.0", + "orchestra/testbench": "^6.0", + "phpstan/phpstan": "^0.12.64", + "phpunit/phpunit": "^9.5.0" }, "type": "library", "extra": { @@ -7913,7 +8044,7 @@ "type": "patreon" } ], - "time": "2020-10-29T15:12:23+00:00" + "time": "2021-09-20T15:06:32+00:00" }, { "name": "phar-io/manifest", @@ -8255,23 +8386,23 @@ }, { "name": "phpunit/php-code-coverage", - "version": "9.2.7", + "version": "9.2.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "d4c798ed8d51506800b441f7a13ecb0f76f12218" + "reference": "cf04e88a2e3c56fc1a65488afd493325b4c1bc3e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/d4c798ed8d51506800b441f7a13ecb0f76f12218", - "reference": "d4c798ed8d51506800b441f7a13ecb0f76f12218", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/cf04e88a2e3c56fc1a65488afd493325b4c1bc3e", + "reference": "cf04e88a2e3c56fc1a65488afd493325b4c1bc3e", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^4.12.0", + "nikic/php-parser": "^4.13.0", "php": ">=7.3", "phpunit/php-file-iterator": "^3.0.3", "phpunit/php-text-template": "^2.0.2", @@ -8320,7 +8451,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.7" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.8" }, "funding": [ { @@ -8328,7 +8459,7 @@ "type": "github" } ], - "time": "2021-09-17T05:39:03+00:00" + "time": "2021-10-30T08:01:38+00:00" }, { "name": "phpunit/php-file-iterator", @@ -9830,64 +9961,6 @@ } ], "time": "2021-07-28T10:34:58+00:00" - }, - { - "name": "webmozart/assert", - "version": "1.10.0", - "source": { - "type": "git", - "url": "https://github.com/webmozarts/assert.git", - "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/6964c76c7804814a842473e0c8fd15bab0f18e25", - "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0", - "symfony/polyfill-ctype": "^1.8" - }, - "conflict": { - "phpstan/phpstan": "<0.12.20", - "vimeo/psalm": "<4.6.1 || 4.6.2" - }, - "require-dev": { - "phpunit/phpunit": "^8.5.13" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.10-dev" - } - }, - "autoload": { - "psr-4": { - "Webmozart\\Assert\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Assertions to validate method input/output with nice error messages.", - "keywords": [ - "assert", - "check", - "validate" - ], - "support": { - "issues": "https://github.com/webmozarts/assert/issues", - "source": "https://github.com/webmozarts/assert/tree/1.10.0" - }, - "time": "2021-03-09T10:59:23+00:00" } ], "aliases": [], diff --git a/database/factories/Actions/CommentFactory.php b/database/factories/Actions/CommentFactory.php new file mode 100644 index 000000000..e81f3fe2c --- /dev/null +++ b/database/factories/Actions/CommentFactory.php @@ -0,0 +1,32 @@ +faker->paragraph(1); + $html = '

' . $text . '

'; + + return [ + 'html' => $html, + 'text' => $text, + 'parent_id' => null, + ]; + } +} diff --git a/database/factories/Actions/TagFactory.php b/database/factories/Actions/TagFactory.php new file mode 100644 index 000000000..8d5c77e09 --- /dev/null +++ b/database/factories/Actions/TagFactory.php @@ -0,0 +1,28 @@ + $this->faker->city, + 'value' => $this->faker->sentence(3), + ]; + } +} diff --git a/database/factories/Auth/RoleFactory.php b/database/factories/Auth/RoleFactory.php new file mode 100644 index 000000000..a952e0487 --- /dev/null +++ b/database/factories/Auth/RoleFactory.php @@ -0,0 +1,28 @@ + $this->faker->sentence(3), + 'description' => $this->faker->sentence(10), + ]; + } +} diff --git a/database/factories/Auth/UserFactory.php b/database/factories/Auth/UserFactory.php new file mode 100644 index 000000000..77d63ac68 --- /dev/null +++ b/database/factories/Auth/UserFactory.php @@ -0,0 +1,35 @@ +faker->name; + + return [ + 'name' => $name, + 'email' => $this->faker->email, + 'slug' => \Illuminate\Support\Str::slug($name . '-' . \Illuminate\Support\Str::random(5)), + 'password' => Str::random(10), + 'remember_token' => Str::random(10), + 'email_confirmed' => 1, + ]; + } +} diff --git a/database/factories/Entities/Models/BookFactory.php b/database/factories/Entities/Models/BookFactory.php new file mode 100644 index 000000000..0613800a1 --- /dev/null +++ b/database/factories/Entities/Models/BookFactory.php @@ -0,0 +1,30 @@ + $this->faker->sentence, + 'slug' => Str::random(10), + 'description' => $this->faker->paragraph, + ]; + } +} diff --git a/database/factories/Entities/Models/BookshelfFactory.php b/database/factories/Entities/Models/BookshelfFactory.php new file mode 100644 index 000000000..66dd1c111 --- /dev/null +++ b/database/factories/Entities/Models/BookshelfFactory.php @@ -0,0 +1,30 @@ + $this->faker->sentence, + 'slug' => Str::random(10), + 'description' => $this->faker->paragraph, + ]; + } +} diff --git a/database/factories/Entities/Models/ChapterFactory.php b/database/factories/Entities/Models/ChapterFactory.php new file mode 100644 index 000000000..4fcd69c39 --- /dev/null +++ b/database/factories/Entities/Models/ChapterFactory.php @@ -0,0 +1,30 @@ + $this->faker->sentence, + 'slug' => Str::random(10), + 'description' => $this->faker->paragraph, + ]; + } +} diff --git a/database/factories/Entities/Models/PageFactory.php b/database/factories/Entities/Models/PageFactory.php new file mode 100644 index 000000000..c83e0f828 --- /dev/null +++ b/database/factories/Entities/Models/PageFactory.php @@ -0,0 +1,34 @@ +' . implode('

', $this->faker->paragraphs(5)) . '

'; + + return [ + 'name' => $this->faker->sentence, + 'slug' => Str::random(10), + 'html' => $html, + 'text' => strip_tags($html), + 'revision_count' => 1, + ]; + } +} diff --git a/database/factories/ModelFactory.php b/database/factories/ModelFactory.php deleted file mode 100644 index dc0645540..000000000 --- a/database/factories/ModelFactory.php +++ /dev/null @@ -1,96 +0,0 @@ -define(\BookStack\Auth\User::class, function ($faker) { - $name = $faker->name; - - return [ - 'name' => $name, - 'email' => $faker->email, - 'slug' => \Illuminate\Support\Str::slug($name . '-' . \Illuminate\Support\Str::random(5)), - 'password' => Str::random(10), - 'remember_token' => Str::random(10), - 'email_confirmed' => 1, - ]; -}); - -$factory->define(\BookStack\Entities\Models\Bookshelf::class, function ($faker) { - return [ - 'name' => $faker->sentence, - 'slug' => Str::random(10), - 'description' => $faker->paragraph, - ]; -}); - -$factory->define(\BookStack\Entities\Models\Book::class, function ($faker) { - return [ - 'name' => $faker->sentence, - 'slug' => Str::random(10), - 'description' => $faker->paragraph, - ]; -}); - -$factory->define(\BookStack\Entities\Models\Chapter::class, function ($faker) { - return [ - 'name' => $faker->sentence, - 'slug' => Str::random(10), - 'description' => $faker->paragraph, - ]; -}); - -$factory->define(\BookStack\Entities\Models\Page::class, function ($faker) { - $html = '

' . implode('

', $faker->paragraphs(5)) . '

'; - - return [ - 'name' => $faker->sentence, - 'slug' => Str::random(10), - 'html' => $html, - 'text' => strip_tags($html), - 'revision_count' => 1, - ]; -}); - -$factory->define(\BookStack\Auth\Role::class, function ($faker) { - return [ - 'display_name' => $faker->sentence(3), - 'description' => $faker->sentence(10), - ]; -}); - -$factory->define(\BookStack\Actions\Tag::class, function ($faker) { - return [ - 'name' => $faker->city, - 'value' => $faker->sentence(3), - ]; -}); - -$factory->define(\BookStack\Uploads\Image::class, function ($faker) { - return [ - 'name' => $faker->slug . '.jpg', - 'url' => $faker->url, - 'path' => $faker->url, - 'type' => 'gallery', - 'uploaded_to' => 0, - ]; -}); - -$factory->define(\BookStack\Actions\Comment::class, function ($faker) { - $text = $faker->paragraph(1); - $html = '

' . $text . '

'; - - return [ - 'html' => $html, - 'text' => $text, - 'parent_id' => null, - ]; -}); diff --git a/database/factories/Uploads/ImageFactory.php b/database/factories/Uploads/ImageFactory.php new file mode 100644 index 000000000..c6d0e0801 --- /dev/null +++ b/database/factories/Uploads/ImageFactory.php @@ -0,0 +1,31 @@ + $this->faker->slug . '.jpg', + 'url' => $this->faker->url, + 'path' => $this->faker->url, + 'type' => 'gallery', + 'uploaded_to' => 0, + ]; + } +} diff --git a/database/seeds/.gitkeep b/database/seeders/.gitkeep similarity index 100% rename from database/seeds/.gitkeep rename to database/seeders/.gitkeep diff --git a/database/seeds/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php similarity index 92% rename from database/seeds/DatabaseSeeder.php rename to database/seeders/DatabaseSeeder.php index 069765eb4..21eaefb19 100644 --- a/database/seeds/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -1,5 +1,7 @@ create(); + $editorUser = User::factory()->create(); $editorRole = Role::getRole('editor'); $editorUser->attachRole($editorRole); // Create a viewer user - $viewerUser = factory(User::class)->create(); + $viewerUser = User::factory()->create(); $role = Role::getRole('viewer'); $viewerUser->attachRole($role); $byData = ['created_by' => $editorUser->id, 'updated_by' => $editorUser->id, 'owned_by' => $editorUser->id]; - factory(\BookStack\Entities\Models\Book::class, 5)->create($byData) + \BookStack\Entities\Models\Book::factory()->count(5)->create($byData) ->each(function ($book) use ($byData) { - $chapters = factory(Chapter::class, 3)->create($byData) + $chapters = Chapter::factory()->count(3)->create($byData) ->each(function ($chapter) use ($book, $byData) { - $pages = factory(Page::class, 3)->make(array_merge($byData, ['book_id' => $book->id])); + $pages = Page::factory()->count(3)->make(array_merge($byData, ['book_id' => $book->id])); $chapter->pages()->saveMany($pages); }); - $pages = factory(Page::class, 3)->make($byData); + $pages = Page::factory()->count(3)->make($byData); $book->chapters()->saveMany($chapters); $book->pages()->saveMany($pages); }); - $largeBook = factory(\BookStack\Entities\Models\Book::class)->create(array_merge($byData, ['name' => 'Large book' . Str::random(10)])); - $pages = factory(Page::class, 200)->make($byData); - $chapters = factory(Chapter::class, 50)->make($byData); + $largeBook = \BookStack\Entities\Models\Book::factory()->create(array_merge($byData, ['name' => 'Large book' . Str::random(10)])); + $pages = Page::factory()->count(200)->make($byData); + $chapters = Chapter::factory()->count(50)->make($byData); $largeBook->pages()->saveMany($pages); $largeBook->chapters()->saveMany($chapters); - $shelves = factory(Bookshelf::class, 10)->create($byData); + $shelves = Bookshelf::factory()->count(10)->create($byData); $largeBook->shelves()->attach($shelves->pluck('id')); // Assign API permission to editor role and create an API key diff --git a/database/seeds/LargeContentSeeder.php b/database/seeders/LargeContentSeeder.php similarity index 60% rename from database/seeds/LargeContentSeeder.php rename to database/seeders/LargeContentSeeder.php index 535626b8f..2fbf4a5c9 100644 --- a/database/seeds/LargeContentSeeder.php +++ b/database/seeders/LargeContentSeeder.php @@ -1,5 +1,7 @@ create(); + $editorUser = User::factory()->create(); $editorRole = Role::getRole('editor'); $editorUser->attachRole($editorRole); - $largeBook = factory(\BookStack\Entities\Models\Book::class)->create(['name' => 'Large book' . Str::random(10), 'created_by' => $editorUser->id, 'updated_by' => $editorUser->id]); - $pages = factory(Page::class, 200)->make(['created_by' => $editorUser->id, 'updated_by' => $editorUser->id]); - $chapters = factory(Chapter::class, 50)->make(['created_by' => $editorUser->id, 'updated_by' => $editorUser->id]); + $largeBook = \BookStack\Entities\Models\Book::factory()->create(['name' => 'Large book' . Str::random(10), 'created_by' => $editorUser->id, 'updated_by' => $editorUser->id]); + $pages = Page::factory()->count(200)->make(['created_by' => $editorUser->id, 'updated_by' => $editorUser->id]); + $chapters = Chapter::factory()->count(50)->make(['created_by' => $editorUser->id, 'updated_by' => $editorUser->id]); $largeBook->pages()->saveMany($pages); $largeBook->chapters()->saveMany($chapters); app(PermissionService::class)->buildJointPermissions(); diff --git a/public/index.php b/public/index.php index 7e4ef97c7..c2f34d4bf 100644 --- a/public/index.php +++ b/public/index.php @@ -1,21 +1,33 @@ - */ +use Illuminate\Contracts\Http\Kernel; +use BookStack\Http\Request; + 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. +| +*/ + +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 -| our application. We just need to utilize it! We'll simply require it -| into the script here so that we don't have to worry about manual -| loading any of our classes later on. It feels great to relax. +| 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. | */ @@ -23,37 +35,22 @@ require __DIR__ . '/../vendor/autoload.php'; /* |-------------------------------------------------------------------------- -| Turn On The Lights +| Run The Application |-------------------------------------------------------------------------- | -| We need to illuminate PHP development, so let us turn on the lights. -| This bootstraps the framework and gets it ready for use, then it -| will load up this application so that we can run it and send -| the responses back to the browser and delight our users. +| 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. | */ $app = require_once __DIR__ . '/../bootstrap/app.php'; -$app->alias('request', \BookStack\Http\Request::class); +$app->alias('request', Request::class); -/* -|-------------------------------------------------------------------------- -| Run The Application -|-------------------------------------------------------------------------- -| -| Once we have the application, we can handle the incoming request -| through the kernel, and send the associated response back to -| the client's browser allowing them to enjoy the creative -| and wonderful application we have prepared for them. -| -*/ +$kernel = $app->make(Kernel::class); -$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class); +$response = tap($kernel->handle( + $request = Request::capture() +))->send(); -$response = $kernel->handle( - $request = \BookStack\Http\Request::capture() -); - -$response->send(); - -$kernel->terminate($request, $response); +$kernel->terminate($request, $response); \ No newline at end of file diff --git a/routes/api.php b/routes/api.php index 49521bb89..4ba499462 100644 --- a/routes/api.php +++ b/routes/api.php @@ -1,53 +1,64 @@ comment(Inspiring::quote()); +})->purpose('Display an inspiring quote'); diff --git a/routes/web.php b/routes/web.php index a5f35fb8a..419a1e7f5 100644 --- a/routes/web.php +++ b/routes/web.php @@ -1,287 +1,318 @@ 'auth'], function () { +Route::middleware('auth')->group(function () { // Secure images routing - Route::get('/uploads/images/{path}', 'Images\ImageController@showImage') + Route::get('/uploads/images/{path}', [Images\ImageController::class, 'showImage']) ->where('path', '.*$'); // API docs routes - Route::get('/api/docs', 'Api\ApiDocsController@display'); + Route::get('/api/docs', [Api\ApiDocsController::class, 'display']); - Route::get('/pages/recently-updated', 'PageController@showRecentlyUpdated'); + Route::get('/pages/recently-updated', [PageController::class, 'showRecentlyUpdated']); // Shelves - Route::get('/create-shelf', 'BookshelfController@create'); - Route::group(['prefix' => 'shelves'], function () { - Route::get('/', 'BookshelfController@index'); - Route::post('/', 'BookshelfController@store'); - Route::get('/{slug}/edit', 'BookshelfController@edit'); - Route::get('/{slug}/delete', 'BookshelfController@showDelete'); - Route::get('/{slug}', 'BookshelfController@show'); - Route::put('/{slug}', 'BookshelfController@update'); - Route::delete('/{slug}', 'BookshelfController@destroy'); - Route::get('/{slug}/permissions', 'BookshelfController@showPermissions'); - Route::put('/{slug}/permissions', 'BookshelfController@permissions'); - Route::post('/{slug}/copy-permissions', 'BookshelfController@copyPermissions'); + Route::get('/create-shelf', [BookshelfController::class, 'create']); + Route::prefix('shelves')->group(function () { + Route::get('/', [BookshelfController::class, 'index']); + Route::post('/', [BookshelfController::class, 'store']); + Route::get('/{slug}/edit', [BookshelfController::class, 'edit']); + Route::get('/{slug}/delete', [BookshelfController::class, 'showDelete']); + Route::get('/{slug}', [BookshelfController::class, 'show']); + Route::put('/{slug}', [BookshelfController::class, 'update']); + Route::delete('/{slug}', [BookshelfController::class, 'destroy']); + Route::get('/{slug}/permissions', [BookshelfController::class, 'showPermissions']); + Route::put('/{slug}/permissions', [BookshelfController::class, 'permissions']); + Route::post('/{slug}/copy-permissions', [BookshelfController::class, 'copyPermissions']); - Route::get('/{shelfSlug}/create-book', 'BookController@create'); - Route::post('/{shelfSlug}/create-book', 'BookController@store'); + Route::get('/{shelfSlug}/create-book', [BookController::class, 'create']); + Route::post('/{shelfSlug}/create-book', [BookController::class, 'store']); }); - Route::get('/create-book', 'BookController@create'); - Route::group(['prefix' => 'books'], function () { + Route::get('/create-book', [BookController::class, 'create']); + Route::prefix('books')->group(function () { // Books - Route::get('/', 'BookController@index'); - Route::post('/', 'BookController@store'); - Route::get('/{slug}/edit', 'BookController@edit'); - Route::put('/{slug}', 'BookController@update'); - Route::delete('/{id}', 'BookController@destroy'); - Route::get('/{slug}/sort-item', 'BookSortController@showItem'); - Route::get('/{slug}', 'BookController@show'); - Route::get('/{bookSlug}/permissions', 'BookController@showPermissions'); - Route::put('/{bookSlug}/permissions', 'BookController@permissions'); - Route::get('/{slug}/delete', 'BookController@showDelete'); - Route::get('/{bookSlug}/sort', 'BookSortController@show'); - Route::put('/{bookSlug}/sort', 'BookSortController@update'); - Route::get('/{bookSlug}/export/html', 'BookExportController@html'); - Route::get('/{bookSlug}/export/pdf', 'BookExportController@pdf'); - Route::get('/{bookSlug}/export/markdown', 'BookExportController@markdown'); - Route::get('/{bookSlug}/export/zip', 'BookExportController@zip'); - Route::get('/{bookSlug}/export/plaintext', 'BookExportController@plainText'); + Route::get('/', [BookController::class, 'index']); + Route::post('/', [BookController::class, 'store']); + Route::get('/{slug}/edit', [BookController::class, 'edit']); + Route::put('/{slug}', [BookController::class, 'update']); + Route::delete('/{id}', [BookController::class, 'destroy']); + Route::get('/{slug}/sort-item', [BookSortController::class, 'showItem']); + Route::get('/{slug}', [BookController::class, 'show']); + Route::get('/{bookSlug}/permissions', [BookController::class, 'showPermissions']); + Route::put('/{bookSlug}/permissions', [BookController::class, 'permissions']); + Route::get('/{slug}/delete', [BookController::class, 'showDelete']); + Route::get('/{bookSlug}/sort', [BookSortController::class, 'show']); + Route::put('/{bookSlug}/sort', [BookSortController::class, 'update']); + Route::get('/{bookSlug}/export/html', [BookExportController::class, 'html']); + Route::get('/{bookSlug}/export/pdf', [BookExportController::class, 'pdf']); + Route::get('/{bookSlug}/export/markdown', [BookExportController::class, 'markdown']); + Route::get('/{bookSlug}/export/zip', [BookExportController::class, 'zip']); + Route::get('/{bookSlug}/export/plaintext', [BookExportController::class, 'plainText']); // Pages - Route::get('/{bookSlug}/create-page', 'PageController@create'); - Route::post('/{bookSlug}/create-guest-page', 'PageController@createAsGuest'); - Route::get('/{bookSlug}/draft/{pageId}', 'PageController@editDraft'); - Route::post('/{bookSlug}/draft/{pageId}', 'PageController@store'); - Route::get('/{bookSlug}/page/{pageSlug}', 'PageController@show'); - Route::get('/{bookSlug}/page/{pageSlug}/export/pdf', 'PageExportController@pdf'); - Route::get('/{bookSlug}/page/{pageSlug}/export/html', 'PageExportController@html'); - Route::get('/{bookSlug}/page/{pageSlug}/export/markdown', 'PageExportController@markdown'); - Route::get('/{bookSlug}/page/{pageSlug}/export/plaintext', 'PageExportController@plainText'); - Route::get('/{bookSlug}/page/{pageSlug}/edit', 'PageController@edit'); - Route::get('/{bookSlug}/page/{pageSlug}/move', 'PageController@showMove'); - Route::put('/{bookSlug}/page/{pageSlug}/move', 'PageController@move'); - Route::get('/{bookSlug}/page/{pageSlug}/copy', 'PageController@showCopy'); - Route::post('/{bookSlug}/page/{pageSlug}/copy', 'PageController@copy'); - Route::get('/{bookSlug}/page/{pageSlug}/delete', 'PageController@showDelete'); - Route::get('/{bookSlug}/draft/{pageId}/delete', 'PageController@showDeleteDraft'); - Route::get('/{bookSlug}/page/{pageSlug}/permissions', 'PageController@showPermissions'); - Route::put('/{bookSlug}/page/{pageSlug}/permissions', 'PageController@permissions'); - Route::put('/{bookSlug}/page/{pageSlug}', 'PageController@update'); - Route::delete('/{bookSlug}/page/{pageSlug}', 'PageController@destroy'); - Route::delete('/{bookSlug}/draft/{pageId}', 'PageController@destroyDraft'); + Route::get('/{bookSlug}/create-page', [PageController::class, 'create']); + Route::post('/{bookSlug}/create-guest-page', [PageController::class, 'createAsGuest']); + Route::get('/{bookSlug}/draft/{pageId}', [PageController::class, 'editDraft']); + Route::post('/{bookSlug}/draft/{pageId}', [PageController::class, 'store']); + Route::get('/{bookSlug}/page/{pageSlug}', [PageController::class, 'show']); + Route::get('/{bookSlug}/page/{pageSlug}/export/pdf', [PageExportController::class, 'pdf']); + Route::get('/{bookSlug}/page/{pageSlug}/export/html', [PageExportController::class, 'html']); + Route::get('/{bookSlug}/page/{pageSlug}/export/markdown', [PageExportController::class, 'markdown']); + Route::get('/{bookSlug}/page/{pageSlug}/export/plaintext', [PageExportController::class, 'plainText']); + Route::get('/{bookSlug}/page/{pageSlug}/edit', [PageController::class, 'edit']); + Route::get('/{bookSlug}/page/{pageSlug}/move', [PageController::class, 'showMove']); + Route::put('/{bookSlug}/page/{pageSlug}/move', [PageController::class, 'move']); + Route::get('/{bookSlug}/page/{pageSlug}/copy', [PageController::class, 'showCopy']); + Route::post('/{bookSlug}/page/{pageSlug}/copy', [PageController::class, 'copy']); + Route::get('/{bookSlug}/page/{pageSlug}/delete', [PageController::class, 'showDelete']); + Route::get('/{bookSlug}/draft/{pageId}/delete', [PageController::class, 'showDeleteDraft']); + Route::get('/{bookSlug}/page/{pageSlug}/permissions', [PageController::class, 'showPermissions']); + Route::put('/{bookSlug}/page/{pageSlug}/permissions', [PageController::class, 'permissions']); + Route::put('/{bookSlug}/page/{pageSlug}', [PageController::class, 'update']); + Route::delete('/{bookSlug}/page/{pageSlug}', [PageController::class, 'destroy']); + Route::delete('/{bookSlug}/draft/{pageId}', [PageController::class, 'destroyDraft']); // Revisions - Route::get('/{bookSlug}/page/{pageSlug}/revisions', 'PageRevisionController@index'); - Route::get('/{bookSlug}/page/{pageSlug}/revisions/{revId}', 'PageRevisionController@show'); - Route::get('/{bookSlug}/page/{pageSlug}/revisions/{revId}/changes', 'PageRevisionController@changes'); - Route::put('/{bookSlug}/page/{pageSlug}/revisions/{revId}/restore', 'PageRevisionController@restore'); - Route::delete('/{bookSlug}/page/{pageSlug}/revisions/{revId}/delete', 'PageRevisionController@destroy'); + Route::get('/{bookSlug}/page/{pageSlug}/revisions', [PageRevisionController::class, 'index']); + Route::get('/{bookSlug}/page/{pageSlug}/revisions/{revId}', [PageRevisionController::class, 'show']); + Route::get('/{bookSlug}/page/{pageSlug}/revisions/{revId}/changes', [PageRevisionController::class, 'changes']); + Route::put('/{bookSlug}/page/{pageSlug}/revisions/{revId}/restore', [PageRevisionController::class, 'restore']); + Route::delete('/{bookSlug}/page/{pageSlug}/revisions/{revId}/delete', [PageRevisionController::class, 'destroy']); // Chapters - Route::get('/{bookSlug}/chapter/{chapterSlug}/create-page', 'PageController@create'); - Route::post('/{bookSlug}/chapter/{chapterSlug}/create-guest-page', 'PageController@createAsGuest'); - Route::get('/{bookSlug}/create-chapter', 'ChapterController@create'); - Route::post('/{bookSlug}/create-chapter', 'ChapterController@store'); - Route::get('/{bookSlug}/chapter/{chapterSlug}', 'ChapterController@show'); - Route::put('/{bookSlug}/chapter/{chapterSlug}', 'ChapterController@update'); - Route::get('/{bookSlug}/chapter/{chapterSlug}/move', 'ChapterController@showMove'); - Route::put('/{bookSlug}/chapter/{chapterSlug}/move', 'ChapterController@move'); - Route::get('/{bookSlug}/chapter/{chapterSlug}/edit', 'ChapterController@edit'); - Route::get('/{bookSlug}/chapter/{chapterSlug}/permissions', 'ChapterController@showPermissions'); - Route::get('/{bookSlug}/chapter/{chapterSlug}/export/pdf', 'ChapterExportController@pdf'); - Route::get('/{bookSlug}/chapter/{chapterSlug}/export/html', 'ChapterExportController@html'); - Route::get('/{bookSlug}/chapter/{chapterSlug}/export/markdown', 'ChapterExportController@markdown'); - Route::get('/{bookSlug}/chapter/{chapterSlug}/export/plaintext', 'ChapterExportController@plainText'); - Route::put('/{bookSlug}/chapter/{chapterSlug}/permissions', 'ChapterController@permissions'); - Route::get('/{bookSlug}/chapter/{chapterSlug}/delete', 'ChapterController@showDelete'); - Route::delete('/{bookSlug}/chapter/{chapterSlug}', 'ChapterController@destroy'); + Route::get('/{bookSlug}/chapter/{chapterSlug}/create-page', [PageController::class, 'create']); + Route::post('/{bookSlug}/chapter/{chapterSlug}/create-guest-page', [PageController::class, 'createAsGuest']); + Route::get('/{bookSlug}/create-chapter', [ChapterController::class, 'create']); + Route::post('/{bookSlug}/create-chapter', [ChapterController::class, 'store']); + Route::get('/{bookSlug}/chapter/{chapterSlug}', [ChapterController::class, 'show']); + Route::put('/{bookSlug}/chapter/{chapterSlug}', [ChapterController::class, 'update']); + Route::get('/{bookSlug}/chapter/{chapterSlug}/move', [ChapterController::class, 'showMove']); + Route::put('/{bookSlug}/chapter/{chapterSlug}/move', [ChapterController::class, 'move']); + Route::get('/{bookSlug}/chapter/{chapterSlug}/edit', [ChapterController::class, 'edit']); + Route::get('/{bookSlug}/chapter/{chapterSlug}/permissions', [ChapterController::class, 'showPermissions']); + Route::get('/{bookSlug}/chapter/{chapterSlug}/export/pdf', [ChapterExportController::class, 'pdf']); + Route::get('/{bookSlug}/chapter/{chapterSlug}/export/html', [ChapterExportController::class, 'html']); + Route::get('/{bookSlug}/chapter/{chapterSlug}/export/markdown', [ChapterExportController::class, 'markdown']); + Route::get('/{bookSlug}/chapter/{chapterSlug}/export/plaintext', [ChapterExportController::class, 'plainText']); + Route::put('/{bookSlug}/chapter/{chapterSlug}/permissions', [ChapterController::class, 'permissions']); + Route::get('/{bookSlug}/chapter/{chapterSlug}/delete', [ChapterController::class, 'showDelete']); + Route::delete('/{bookSlug}/chapter/{chapterSlug}', [ChapterController::class, 'destroy']); }); // User Profile routes - Route::get('/user/{slug}', 'UserProfileController@show'); + Route::get('/user/{slug}', [UserProfileController::class, 'show']); // Image routes - Route::get('/images/gallery', 'Images\GalleryImageController@list'); - Route::post('/images/gallery', 'Images\GalleryImageController@create'); - Route::get('/images/drawio', 'Images\DrawioImageController@list'); - Route::get('/images/drawio/base64/{id}', 'Images\DrawioImageController@getAsBase64'); - Route::post('/images/drawio', 'Images\DrawioImageController@create'); - Route::get('/images/edit/{id}', 'Images\ImageController@edit'); - Route::put('/images/{id}', 'Images\ImageController@update'); - Route::delete('/images/{id}', 'Images\ImageController@destroy'); + Route::get('/images/gallery', [Images\GalleryImageController::class, 'list']); + Route::post('/images/gallery', [Images\GalleryImageController::class, 'create']); + Route::get('/images/drawio', [Images\DrawioImageController::class, 'list']); + Route::get('/images/drawio/base64/{id}', [Images\DrawioImageController::class, 'getAsBase64']); + Route::post('/images/drawio', [Images\DrawioImageController::class, 'create']); + Route::get('/images/edit/{id}', [Images\ImageController::class, 'edit']); + Route::put('/images/{id}', [Images\ImageController::class, 'update']); + Route::delete('/images/{id}', [Images\ImageController::class, 'destroy']); // Attachments routes - Route::get('/attachments/{id}', 'AttachmentController@get'); - Route::post('/attachments/upload', 'AttachmentController@upload'); - Route::post('/attachments/upload/{id}', 'AttachmentController@uploadUpdate'); - Route::post('/attachments/link', 'AttachmentController@attachLink'); - Route::put('/attachments/{id}', 'AttachmentController@update'); - Route::get('/attachments/edit/{id}', 'AttachmentController@getUpdateForm'); - Route::get('/attachments/get/page/{pageId}', 'AttachmentController@listForPage'); - Route::put('/attachments/sort/page/{pageId}', 'AttachmentController@sortForPage'); - Route::delete('/attachments/{id}', 'AttachmentController@delete'); + Route::get('/attachments/{id}', [AttachmentController::class, 'get']); + Route::post('/attachments/upload', [AttachmentController::class, 'upload']); + Route::post('/attachments/upload/{id}', [AttachmentController::class, 'uploadUpdate']); + Route::post('/attachments/link', [AttachmentController::class, 'attachLink']); + Route::put('/attachments/{id}', [AttachmentController::class, 'update']); + Route::get('/attachments/edit/{id}', [AttachmentController::class, 'getUpdateForm']); + Route::get('/attachments/get/page/{pageId}', [AttachmentController::class, 'listForPage']); + Route::put('/attachments/sort/page/{pageId}', [AttachmentController::class, 'sortForPage']); + Route::delete('/attachments/{id}', [AttachmentController::class, 'delete']); // AJAX routes - Route::put('/ajax/page/{id}/save-draft', 'PageController@saveDraft'); - Route::get('/ajax/page/{id}', 'PageController@getPageAjax'); - Route::delete('/ajax/page/{id}', 'PageController@ajaxDestroy'); + Route::put('/ajax/page/{id}/save-draft', [PageController::class, 'saveDraft']); + Route::get('/ajax/page/{id}', [PageController::class, 'getPageAjax']); + Route::delete('/ajax/page/{id}', [PageController::class, 'ajaxDestroy']); // Tag routes (AJAX) - Route::group(['prefix' => 'ajax/tags'], function () { - Route::get('/suggest/names', 'TagController@getNameSuggestions'); - Route::get('/suggest/values', 'TagController@getValueSuggestions'); + Route::prefix('ajax/tags')->group(function () { + Route::get('/suggest/names', [TagController::class, 'getNameSuggestions']); + Route::get('/suggest/values', [TagController::class, 'getValueSuggestions']); }); - Route::get('/ajax/search/entities', 'SearchController@searchEntitiesAjax'); + Route::get('/ajax/search/entities', [SearchController::class, 'searchEntitiesAjax']); // Comments - Route::post('/comment/{pageId}', 'CommentController@savePageComment'); - Route::put('/comment/{id}', 'CommentController@update'); - Route::delete('/comment/{id}', 'CommentController@destroy'); + Route::post('/comment/{pageId}', [CommentController::class, 'savePageComment']); + Route::put('/comment/{id}', [CommentController::class, 'update']); + Route::delete('/comment/{id}', [CommentController::class, 'destroy']); // Links - Route::get('/link/{id}', 'PageController@redirectFromLink'); + Route::get('/link/{id}', [PageController::class, 'redirectFromLink']); // Search - Route::get('/search', 'SearchController@search'); - Route::get('/search/book/{bookId}', 'SearchController@searchBook'); - Route::get('/search/chapter/{bookId}', 'SearchController@searchChapter'); - Route::get('/search/entity/siblings', 'SearchController@searchSiblings'); + Route::get('/search', [SearchController::class, 'search']); + Route::get('/search/book/{bookId}', [SearchController::class, 'searchBook']); + Route::get('/search/chapter/{bookId}', [SearchController::class, 'searchChapter']); + Route::get('/search/entity/siblings', [SearchController::class, 'searchSiblings']); // User Search - Route::get('/search/users/select', 'UserSearchController@forSelect'); + Route::get('/search/users/select', [UserSearchController::class, 'forSelect']); // Template System - Route::get('/templates', 'PageTemplateController@list'); - Route::get('/templates/{templateId}', 'PageTemplateController@get'); + Route::get('/templates', [PageTemplateController::class, 'list']); + Route::get('/templates/{templateId}', [PageTemplateController::class, 'get']); // Favourites - Route::get('/favourites', 'FavouriteController@index'); - Route::post('/favourites/add', 'FavouriteController@add'); - Route::post('/favourites/remove', 'FavouriteController@remove'); + Route::get('/favourites', [FavouriteController::class, 'index']); + Route::post('/favourites/add', [FavouriteController::class, 'add']); + Route::post('/favourites/remove', [FavouriteController::class, 'remove']); // Other Pages - Route::get('/', 'HomeController@index'); - Route::get('/home', 'HomeController@index'); - Route::get('/custom-head-content', 'HomeController@customHeadContent'); + Route::get('/', [HomeController::class, 'index']); + Route::get('/home', [HomeController::class, 'index']); + Route::get('/custom-head-content', [HomeController::class, 'customHeadContent']); // Settings - Route::group(['prefix' => 'settings'], function () { - Route::get('/', 'SettingController@index')->name('settings'); - Route::post('/', 'SettingController@update'); + Route::prefix('settings')->group(function () { + Route::get('/', [SettingController::class, 'index'])->name('settings'); + Route::post('/', [SettingController::class, 'update']); // Maintenance - Route::get('/maintenance', 'MaintenanceController@index'); - Route::delete('/maintenance/cleanup-images', 'MaintenanceController@cleanupImages'); - Route::post('/maintenance/send-test-email', 'MaintenanceController@sendTestEmail'); + Route::get('/maintenance', [MaintenanceController::class, 'index']); + Route::delete('/maintenance/cleanup-images', [MaintenanceController::class, 'cleanupImages']); + Route::post('/maintenance/send-test-email', [MaintenanceController::class, 'sendTestEmail']); // Recycle Bin - Route::get('/recycle-bin', 'RecycleBinController@index'); - Route::post('/recycle-bin/empty', 'RecycleBinController@empty'); - Route::get('/recycle-bin/{id}/destroy', 'RecycleBinController@showDestroy'); - Route::delete('/recycle-bin/{id}', 'RecycleBinController@destroy'); - Route::get('/recycle-bin/{id}/restore', 'RecycleBinController@showRestore'); - Route::post('/recycle-bin/{id}/restore', 'RecycleBinController@restore'); + Route::get('/recycle-bin', [RecycleBinController::class, 'index']); + Route::post('/recycle-bin/empty', [RecycleBinController::class, 'empty']); + Route::get('/recycle-bin/{id}/destroy', [RecycleBinController::class, 'showDestroy']); + Route::delete('/recycle-bin/{id}', [RecycleBinController::class, 'destroy']); + Route::get('/recycle-bin/{id}/restore', [RecycleBinController::class, 'showRestore']); + Route::post('/recycle-bin/{id}/restore', [RecycleBinController::class, 'restore']); // Audit Log - Route::get('/audit', 'AuditLogController@index'); + Route::get('/audit', [AuditLogController::class, 'index']); // Users - Route::get('/users', 'UserController@index'); - Route::get('/users/create', 'UserController@create'); - Route::get('/users/{id}/delete', 'UserController@delete'); - Route::patch('/users/{id}/switch-books-view', 'UserController@switchBooksView'); - Route::patch('/users/{id}/switch-shelves-view', 'UserController@switchShelvesView'); - Route::patch('/users/{id}/switch-shelf-view', 'UserController@switchShelfView'); - Route::patch('/users/{id}/change-sort/{type}', 'UserController@changeSort'); - Route::patch('/users/{id}/update-expansion-preference/{key}', 'UserController@updateExpansionPreference'); - Route::patch('/users/toggle-dark-mode', 'UserController@toggleDarkMode'); - Route::post('/users/create', 'UserController@store'); - Route::get('/users/{id}', 'UserController@edit'); - Route::put('/users/{id}', 'UserController@update'); - Route::delete('/users/{id}', 'UserController@destroy'); + Route::get('/users', [UserController::class, 'index']); + Route::get('/users/create', [UserController::class, 'create']); + Route::get('/users/{id}/delete', [UserController::class, 'delete']); + Route::patch('/users/{id}/switch-books-view', [UserController::class, 'switchBooksView']); + Route::patch('/users/{id}/switch-shelves-view', [UserController::class, 'switchShelvesView']); + Route::patch('/users/{id}/switch-shelf-view', [UserController::class, 'switchShelfView']); + Route::patch('/users/{id}/change-sort/{type}', [UserController::class, 'changeSort']); + Route::patch('/users/{id}/update-expansion-preference/{key}', [UserController::class, 'updateExpansionPreference']); + Route::patch('/users/toggle-dark-mode', [UserController::class, 'toggleDarkMode']); + Route::post('/users/create', [UserController::class, 'store']); + Route::get('/users/{id}', [UserController::class, 'edit']); + Route::put('/users/{id}', [UserController::class, 'update']); + Route::delete('/users/{id}', [UserController::class, 'destroy']); // User API Tokens - Route::get('/users/{userId}/create-api-token', 'UserApiTokenController@create'); - Route::post('/users/{userId}/create-api-token', 'UserApiTokenController@store'); - Route::get('/users/{userId}/api-tokens/{tokenId}', 'UserApiTokenController@edit'); - Route::put('/users/{userId}/api-tokens/{tokenId}', 'UserApiTokenController@update'); - Route::get('/users/{userId}/api-tokens/{tokenId}/delete', 'UserApiTokenController@delete'); - Route::delete('/users/{userId}/api-tokens/{tokenId}', 'UserApiTokenController@destroy'); + Route::get('/users/{userId}/create-api-token', [UserApiTokenController::class, 'create']); + Route::post('/users/{userId}/create-api-token', [UserApiTokenController::class, 'store']); + Route::get('/users/{userId}/api-tokens/{tokenId}', [UserApiTokenController::class, 'edit']); + Route::put('/users/{userId}/api-tokens/{tokenId}', [UserApiTokenController::class, 'update']); + Route::get('/users/{userId}/api-tokens/{tokenId}/delete', [UserApiTokenController::class, 'delete']); + Route::delete('/users/{userId}/api-tokens/{tokenId}', [UserApiTokenController::class, 'destroy']); // Roles - Route::get('/roles', 'RoleController@list'); - Route::get('/roles/new', 'RoleController@create'); - Route::post('/roles/new', 'RoleController@store'); - Route::get('/roles/delete/{id}', 'RoleController@showDelete'); - Route::delete('/roles/delete/{id}', 'RoleController@delete'); - Route::get('/roles/{id}', 'RoleController@edit'); - Route::put('/roles/{id}', 'RoleController@update'); + Route::get('/roles', [RoleController::class, 'list']); + Route::get('/roles/new', [RoleController::class, 'create']); + Route::post('/roles/new', [RoleController::class, 'store']); + Route::get('/roles/delete/{id}', [RoleController::class, 'showDelete']); + Route::delete('/roles/delete/{id}', [RoleController::class, 'delete']); + Route::get('/roles/{id}', [RoleController::class, 'edit']); + Route::put('/roles/{id}', [RoleController::class, 'update']); }); }); // MFA routes -Route::group(['middleware' => 'mfa-setup'], function () { - Route::get('/mfa/setup', 'Auth\MfaController@setup'); - Route::get('/mfa/totp/generate', 'Auth\MfaTotpController@generate'); - Route::post('/mfa/totp/confirm', 'Auth\MfaTotpController@confirm'); - Route::get('/mfa/backup_codes/generate', 'Auth\MfaBackupCodesController@generate'); - Route::post('/mfa/backup_codes/confirm', 'Auth\MfaBackupCodesController@confirm'); +Route::middleware('mfa-setup')->group(function () { + Route::get('/mfa/setup', [Auth\MfaController::class, 'setup']); + Route::get('/mfa/totp/generate', [Auth\MfaTotpController::class, 'generate']); + Route::post('/mfa/totp/confirm', [Auth\MfaTotpController::class, 'confirm']); + Route::get('/mfa/backup_codes/generate', [Auth\MfaBackupCodesController::class, 'generate']); + Route::post('/mfa/backup_codes/confirm', [Auth\MfaBackupCodesController::class, 'confirm']); }); -Route::group(['middleware' => 'guest'], function () { - Route::get('/mfa/verify', 'Auth\MfaController@verify'); - Route::post('/mfa/totp/verify', 'Auth\MfaTotpController@verify'); - Route::post('/mfa/backup_codes/verify', 'Auth\MfaBackupCodesController@verify'); +Route::middleware('guest')->group(function () { + Route::get('/mfa/verify', [Auth\MfaController::class, 'verify']); + Route::post('/mfa/totp/verify', [Auth\MfaTotpController::class, 'verify']); + Route::post('/mfa/backup_codes/verify', [Auth\MfaBackupCodesController::class, 'verify']); }); -Route::delete('/mfa/{method}/remove', 'Auth\MfaController@remove')->middleware('auth'); +Route::delete('/mfa/{method}/remove', [Auth\MfaController::class, 'remove'])->middleware('auth'); // Social auth routes -Route::get('/login/service/{socialDriver}', 'Auth\SocialController@login'); -Route::get('/login/service/{socialDriver}/callback', 'Auth\SocialController@callback'); -Route::post('/login/service/{socialDriver}/detach', 'Auth\SocialController@detach')->middleware('auth'); -Route::get('/register/service/{socialDriver}', 'Auth\SocialController@register'); +Route::get('/login/service/{socialDriver}', [Auth\SocialController::class, 'login']); +Route::get('/login/service/{socialDriver}/callback', [Auth\SocialController::class, 'callback']); +Route::post('/login/service/{socialDriver}/detach', [Auth\SocialController::class, 'detach'])->middleware('auth'); +Route::get('/register/service/{socialDriver}', [Auth\SocialController::class, 'register']); // Login/Logout routes -Route::get('/login', 'Auth\LoginController@getLogin'); -Route::post('/login', 'Auth\LoginController@login'); -Route::get('/logout', 'Auth\LoginController@logout'); -Route::get('/register', 'Auth\RegisterController@getRegister'); -Route::get('/register/confirm', 'Auth\ConfirmEmailController@show'); -Route::get('/register/confirm/awaiting', 'Auth\ConfirmEmailController@showAwaiting'); -Route::post('/register/confirm/resend', 'Auth\ConfirmEmailController@resend'); -Route::get('/register/confirm/{token}', 'Auth\ConfirmEmailController@confirm'); -Route::post('/register', 'Auth\RegisterController@postRegister'); +Route::get('/login', [Auth\LoginController::class, 'getLogin']); +Route::post('/login', [Auth\LoginController::class, 'login']); +Route::get('/logout', [Auth\LoginController::class, 'logout']); +Route::get('/register', [Auth\RegisterController::class, 'getRegister']); +Route::get('/register/confirm', [Auth\ConfirmEmailController::class, 'show']); +Route::get('/register/confirm/awaiting', [Auth\ConfirmEmailController::class, 'showAwaiting']); +Route::post('/register/confirm/resend', [Auth\ConfirmEmailController::class, 'resend']); +Route::get('/register/confirm/{token}', [Auth\ConfirmEmailController::class, 'confirm']); +Route::post('/register', [Auth\RegisterController::class, 'postRegister']); // SAML routes -Route::post('/saml2/login', 'Auth\Saml2Controller@login'); -Route::get('/saml2/logout', 'Auth\Saml2Controller@logout'); -Route::get('/saml2/metadata', 'Auth\Saml2Controller@metadata'); -Route::get('/saml2/sls', 'Auth\Saml2Controller@sls'); -Route::post('/saml2/acs', 'Auth\Saml2Controller@startAcs'); -Route::get('/saml2/acs', 'Auth\Saml2Controller@processAcs'); +Route::post('/saml2/login', [Auth\Saml2Controller::class, 'login']); +Route::get('/saml2/logout', [Auth\Saml2Controller::class, 'logout']); +Route::get('/saml2/metadata', [Auth\Saml2Controller::class, 'metadata']); +Route::get('/saml2/sls', [Auth\Saml2Controller::class, 'sls']); +Route::post('/saml2/acs', [Auth\Saml2Controller::class, 'startAcs']); +Route::get('/saml2/acs', [Auth\Saml2Controller::class, 'processAcs']); // OIDC routes -Route::post('/oidc/login', 'Auth\OidcController@login'); -Route::get('/oidc/callback', 'Auth\OidcController@callback'); +Route::post('/oidc/login', [Auth\OidcController::class, 'login']); +Route::get('/oidc/callback', [Auth\OidcController::class, 'callback']); // User invitation routes -Route::get('/register/invite/{token}', 'Auth\UserInviteController@showSetPassword'); -Route::post('/register/invite/{token}', 'Auth\UserInviteController@setPassword'); +Route::get('/register/invite/{token}', [Auth\UserInviteController::class, 'showSetPassword']); +Route::post('/register/invite/{token}', [Auth\UserInviteController::class, 'setPassword']); // Password reset link request routes... -Route::get('/password/email', 'Auth\ForgotPasswordController@showLinkRequestForm'); -Route::post('/password/email', 'Auth\ForgotPasswordController@sendResetLinkEmail'); +Route::get('/password/email', [Auth\ForgotPasswordController::class, 'showLinkRequestForm']); +Route::post('/password/email', [Auth\ForgotPasswordController::class, 'sendResetLinkEmail']); // Password reset routes... -Route::get('/password/reset/{token}', 'Auth\ResetPasswordController@showResetForm'); -Route::post('/password/reset', 'Auth\ResetPasswordController@reset'); +Route::get('/password/reset/{token}', [Auth\ResetPasswordController::class, 'showResetForm']); +Route::post('/password/reset', [Auth\ResetPasswordController::class, 'reset']); -Route::fallback('HomeController@notFound')->name('fallback'); +Route::fallback([HomeController::class, 'notFound'])->name('fallback'); diff --git a/storage/framework/.gitignore b/storage/framework/.gitignore index 953edb7a9..05c4471f2 100755 --- a/storage/framework/.gitignore +++ b/storage/framework/.gitignore @@ -1,7 +1,9 @@ -config.php -routes.php compiled.php -services.json -events.scanned.php -routes.scanned.php +config.php down +events.scanned.php +maintenance.php +routes.php +routes.scanned.php +schedule-* +services.json diff --git a/tests/AuditLogTest.php b/tests/AuditLogTest.php index 8d13670ca..f909cd79a 100644 --- a/tests/AuditLogTest.php +++ b/tests/AuditLogTest.php @@ -17,7 +17,7 @@ class AuditLogTest extends TestCase /** @var ActivityService */ protected $activityService; - public function setUp(): void + protected function setUp(): void { parent::setUp(); $this->activityService = app(ActivityService::class); diff --git a/tests/Auth/AuthTest.php b/tests/Auth/AuthTest.php index 79f00bed0..66ab09d3c 100644 --- a/tests/Auth/AuthTest.php +++ b/tests/Auth/AuthTest.php @@ -44,7 +44,7 @@ class AuthTest extends TestCase { // Set settings and get user instance $this->setSettings(['registration-enabled' => 'true']); - $user = factory(User::class)->make(); + $user = User::factory()->make(); // Test form and ensure user is created $this->get('/register') @@ -102,7 +102,7 @@ class AuthTest extends TestCase // Set settings and get user instance $this->setSettings(['registration-enabled' => 'true', 'registration-confirmation' => 'true']); - $user = factory(User::class)->make(); + $user = User::factory()->make(); // Go through registration process $resp = $this->post('/register', $user->only('name', 'email', 'password')); @@ -140,7 +140,7 @@ class AuthTest extends TestCase public function test_restricted_registration() { $this->setSettings(['registration-enabled' => 'true', 'registration-confirmation' => 'true', 'registration-restrict' => 'example.com']); - $user = factory(User::class)->make(); + $user = User::factory()->make(); // Go through registration process $this->post('/register', $user->only('name', 'email', 'password')) @@ -166,7 +166,7 @@ class AuthTest extends TestCase public function test_restricted_registration_with_confirmation_disabled() { $this->setSettings(['registration-enabled' => 'true', 'registration-confirmation' => 'false', 'registration-restrict' => 'example.com']); - $user = factory(User::class)->make(); + $user = User::factory()->make(); // Go through registration process $this->post('/register', $user->only('name', 'email', 'password')) diff --git a/tests/Auth/LdapTest.php b/tests/Auth/LdapTest.php index 9e0729a8e..d00e8cf15 100644 --- a/tests/Auth/LdapTest.php +++ b/tests/Auth/LdapTest.php @@ -20,7 +20,7 @@ class LdapTest extends TestCase protected $mockUser; protected $resourceId = 'resource-test'; - public function setUp(): void + protected function setUp(): void { parent::setUp(); if (!defined('LDAP_OPT_REFERRALS')) { @@ -42,7 +42,7 @@ class LdapTest extends TestCase ]); $this->mockLdap = \Mockery::mock(Ldap::class); $this->app[Ldap::class] = $this->mockLdap; - $this->mockUser = factory(User::class)->make(); + $this->mockUser = User::factory()->make(); } protected function runFailedAuthLogin() @@ -264,9 +264,9 @@ class LdapTest extends TestCase public function test_login_maps_roles_and_retains_existing_roles() { - $roleToReceive = factory(Role::class)->create(['display_name' => 'LdapTester']); - $roleToReceive2 = factory(Role::class)->create(['display_name' => 'LdapTester Second']); - $existingRole = factory(Role::class)->create(['display_name' => 'ldaptester-existing']); + $roleToReceive = Role::factory()->create(['display_name' => 'LdapTester']); + $roleToReceive2 = Role::factory()->create(['display_name' => 'LdapTester Second']); + $existingRole = Role::factory()->create(['display_name' => 'ldaptester-existing']); $this->mockUser->forceFill(['external_auth_id' => $this->mockUser->name])->save(); $this->mockUser->attachRole($existingRole); @@ -310,8 +310,8 @@ class LdapTest extends TestCase public function test_login_maps_roles_and_removes_old_roles_if_set() { - $roleToReceive = factory(Role::class)->create(['display_name' => 'LdapTester']); - $existingRole = factory(Role::class)->create(['display_name' => 'ldaptester-existing']); + $roleToReceive = Role::factory()->create(['display_name' => 'LdapTester']); + $existingRole = Role::factory()->create(['display_name' => 'ldaptester-existing']); $this->mockUser->forceFill(['external_auth_id' => $this->mockUser->name])->save(); $this->mockUser->attachRole($existingRole); @@ -350,15 +350,15 @@ class LdapTest extends TestCase public function test_external_auth_id_visible_in_roles_page_when_ldap_active() { - $role = factory(Role::class)->create(['display_name' => 'ldaptester', 'external_auth_id' => 'ex-auth-a, test-second-param']); + $role = Role::factory()->create(['display_name' => 'ldaptester', 'external_auth_id' => 'ex-auth-a, test-second-param']); $this->asAdmin()->get('/settings/roles/' . $role->id) ->assertSee('ex-auth-a'); } public function test_login_maps_roles_using_external_auth_ids_if_set() { - $roleToReceive = factory(Role::class)->create(['display_name' => 'ldaptester', 'external_auth_id' => 'test-second-param, ex-auth-a']); - $roleToNotReceive = factory(Role::class)->create(['display_name' => 'ex-auth-a', 'external_auth_id' => 'test-second-param']); + $roleToReceive = Role::factory()->create(['display_name' => 'ldaptester', 'external_auth_id' => 'test-second-param, ex-auth-a']); + $roleToNotReceive = Role::factory()->create(['display_name' => 'ex-auth-a', 'external_auth_id' => 'test-second-param']); app('config')->set([ 'services.ldap.user_to_groups' => true, @@ -395,8 +395,8 @@ class LdapTest extends TestCase public function test_login_group_mapping_does_not_conflict_with_default_role() { - $roleToReceive = factory(Role::class)->create(['display_name' => 'LdapTester']); - $roleToReceive2 = factory(Role::class)->create(['display_name' => 'LdapTester Second']); + $roleToReceive = Role::factory()->create(['display_name' => 'LdapTester']); + $roleToReceive2 = Role::factory()->create(['display_name' => 'LdapTester Second']); $this->mockUser->forceFill(['external_auth_id' => $this->mockUser->name])->save(); setting()->put('registration-role', $roleToReceive->id); @@ -641,8 +641,8 @@ class LdapTest extends TestCase public function test_login_with_email_confirmation_required_maps_groups_but_shows_confirmation_screen() { - $roleToReceive = factory(Role::class)->create(['display_name' => 'LdapTester']); - $user = factory(User::class)->make(); + $roleToReceive = Role::factory()->create(['display_name' => 'LdapTester']); + $user = User::factory()->make(); setting()->put('registration-confirmation', 'true'); app('config')->set([ diff --git a/tests/Auth/OidcTest.php b/tests/Auth/OidcTest.php index 6c806aa8e..e7665a679 100644 --- a/tests/Auth/OidcTest.php +++ b/tests/Auth/OidcTest.php @@ -16,7 +16,7 @@ class OidcTest extends TestCase protected $keyFilePath; protected $keyFile; - public function setUp(): void + protected function setUp(): void { parent::setUp(); // Set default config for OpenID Connect @@ -41,7 +41,7 @@ class OidcTest extends TestCase ]); } - public function tearDown(): void + protected function tearDown(): void { parent::tearDown(); if (file_exists($this->keyFilePath)) { diff --git a/tests/Auth/Saml2Test.php b/tests/Auth/Saml2Test.php index c534b2d78..aac2710a8 100644 --- a/tests/Auth/Saml2Test.php +++ b/tests/Auth/Saml2Test.php @@ -8,7 +8,7 @@ use Tests\TestCase; class Saml2Test extends TestCase { - public function setUp(): void + protected function setUp(): void { parent::setUp(); // Set default config for SAML2 @@ -119,7 +119,7 @@ class Saml2Test extends TestCase 'saml2.remove_from_groups' => false, ]); - $memberRole = factory(Role::class)->create(['external_auth_id' => 'member']); + $memberRole = Role::factory()->create(['external_auth_id' => 'member']); $adminRole = Role::getSystemRole('admin'); $this->followingRedirects()->post('/saml2/acs', ['SAMLResponse' => $this->acsPostData]); @@ -141,7 +141,7 @@ class Saml2Test extends TestCase $acsPost = $this->followingRedirects()->post('/saml2/acs', ['SAMLResponse' => $this->acsPostData]); $user = User::query()->where('external_auth_id', '=', 'user')->first(); - $randomRole = factory(Role::class)->create(['external_auth_id' => 'random']); + $randomRole = Role::factory()->create(['external_auth_id' => 'random']); $user->attachRole($randomRole); $this->assertContains($randomRole->id, $user->roles()->pluck('id')); @@ -295,7 +295,7 @@ class Saml2Test extends TestCase 'saml2.remove_from_groups' => false, ]); - $memberRole = factory(Role::class)->create(['external_auth_id' => 'member']); + $memberRole = Role::factory()->create(['external_auth_id' => 'member']); $adminRole = Role::getSystemRole('admin'); $acsPost = $this->followingRedirects()->post('/saml2/acs', ['SAMLResponse' => $this->acsPostData]); diff --git a/tests/Auth/SocialAuthTest.php b/tests/Auth/SocialAuthTest.php index f70263dd2..90d7e37aa 100644 --- a/tests/Auth/SocialAuthTest.php +++ b/tests/Auth/SocialAuthTest.php @@ -15,7 +15,7 @@ class SocialAuthTest extends TestCase { public function test_social_registration() { - $user = factory(User::class)->make(); + $user = User::factory()->make(); $this->setSettings(['registration-enabled' => 'true']); config(['GOOGLE_APP_ID' => 'abc123', 'GOOGLE_APP_SECRET' => '123abc', 'APP_URL' => 'http://localhost']); @@ -118,7 +118,7 @@ class SocialAuthTest extends TestCase 'APP_URL' => 'http://localhost', ]); - $user = factory(User::class)->make(); + $user = User::factory()->make(); $mockSocialite = $this->mock(Factory::class); $mockSocialDriver = Mockery::mock(Provider::class); $mockSocialUser = Mockery::mock(\Laravel\Socialite\Contracts\User::class); @@ -156,7 +156,7 @@ class SocialAuthTest extends TestCase 'APP_URL' => 'http://localhost', 'services.google.auto_register' => true, 'services.google.auto_confirm' => true, ]); - $user = factory(User::class)->make(); + $user = User::factory()->make(); $mockSocialite = $this->mock(Factory::class); $mockSocialDriver = Mockery::mock(Provider::class); $mockSocialUser = Mockery::mock(\Laravel\Socialite\Contracts\User::class); @@ -188,7 +188,7 @@ class SocialAuthTest extends TestCase public function test_social_registration_with_no_name_uses_email_as_name() { - $user = factory(User::class)->make(['email' => 'nonameuser@example.com']); + $user = User::factory()->make(['email' => 'nonameuser@example.com']); $this->setSettings(['registration-enabled' => 'true']); config(['GITHUB_APP_ID' => 'abc123', 'GITHUB_APP_SECRET' => '123abc', 'APP_URL' => 'http://localhost']); diff --git a/tests/Entity/BookShelfTest.php b/tests/Entity/BookShelfTest.php index afd6a1a06..fcbc17ea9 100644 --- a/tests/Entity/BookShelfTest.php +++ b/tests/Entity/BookShelfTest.php @@ -37,7 +37,7 @@ class BookShelfTest extends TestCase public function test_shelves_shows_in_header_if_have_any_shelve_view_permission() { - $user = factory(User::class)->create(); + $user = User::factory()->create(); $this->giveUserPermissions($user, ['image-create-all']); $shelf = Bookshelf::first(); $userRole = $user->roles()->first(); diff --git a/tests/Entity/BookTest.php b/tests/Entity/BookTest.php index 53ee6faf9..2894fbb98 100644 --- a/tests/Entity/BookTest.php +++ b/tests/Entity/BookTest.php @@ -9,7 +9,7 @@ class BookTest extends TestCase { public function test_create() { - $book = factory(Book::class)->make([ + $book = Book::factory()->make([ 'name' => 'My First Book', ]); @@ -29,7 +29,7 @@ class BookTest extends TestCase public function test_create_uses_different_slugs_when_name_reused() { - $book = factory(Book::class)->make([ + $book = Book::factory()->make([ 'name' => 'My First Book', ]); diff --git a/tests/Entity/ChapterTest.php b/tests/Entity/ChapterTest.php index ea29ece5d..9868dc030 100644 --- a/tests/Entity/ChapterTest.php +++ b/tests/Entity/ChapterTest.php @@ -13,7 +13,7 @@ class ChapterTest extends TestCase /** @var Book $book */ $book = Book::query()->first(); - $chapter = factory(Chapter::class)->make([ + $chapter = Chapter::factory()->make([ 'name' => 'My First Chapter', ]); diff --git a/tests/Entity/CommentSettingTest.php b/tests/Entity/CommentSettingTest.php index d8caa7358..23607f5a7 100644 --- a/tests/Entity/CommentSettingTest.php +++ b/tests/Entity/CommentSettingTest.php @@ -9,7 +9,7 @@ class CommentSettingTest extends TestCase { protected $page; - public function setUp(): void + protected function setUp(): void { parent::setUp(); $this->page = Page::query()->first(); diff --git a/tests/Entity/CommentTest.php b/tests/Entity/CommentTest.php index b613f80a1..1e8ecbcac 100644 --- a/tests/Entity/CommentTest.php +++ b/tests/Entity/CommentTest.php @@ -13,7 +13,7 @@ class CommentTest extends TestCase $this->asAdmin(); $page = Page::first(); - $comment = factory(Comment::class)->make(['parent_id' => 2]); + $comment = Comment::factory()->make(['parent_id' => 2]); $resp = $this->postJson("/comment/$page->id", $comment->getAttributes()); $resp->assertStatus(200); @@ -36,7 +36,7 @@ class CommentTest extends TestCase $this->asAdmin(); $page = Page::first(); - $comment = factory(Comment::class)->make(); + $comment = Comment::factory()->make(); $this->postJson("/comment/$page->id", $comment->getAttributes()); $comment = $page->comments()->first(); @@ -60,7 +60,7 @@ class CommentTest extends TestCase $this->asAdmin(); $page = Page::first(); - $comment = factory(Comment::class)->make(); + $comment = Comment::factory()->make(); $this->postJson("/comment/$page->id", $comment->getAttributes()); $comment = $page->comments()->first(); diff --git a/tests/Entity/PageDraftTest.php b/tests/Entity/PageDraftTest.php index 4fb7d7ab6..9e2ceff51 100644 --- a/tests/Entity/PageDraftTest.php +++ b/tests/Entity/PageDraftTest.php @@ -20,7 +20,7 @@ class PageDraftTest extends TestCase */ protected $pageRepo; - public function setUp(): void + protected function setUp(): void { parent::setUp(); $this->page = Page::query()->first(); diff --git a/tests/Entity/PageEditorTest.php b/tests/Entity/PageEditorTest.php index 9b0a8f188..652bc1336 100644 --- a/tests/Entity/PageEditorTest.php +++ b/tests/Entity/PageEditorTest.php @@ -11,7 +11,7 @@ class PageEditorTest extends TestCase /** @var Page */ protected $page; - public function setUp(): void + protected function setUp(): void { parent::setUp(); $this->page = Page::query()->first(); diff --git a/tests/Entity/PageTest.php b/tests/Entity/PageTest.php index 313fc77f0..32459a84a 100644 --- a/tests/Entity/PageTest.php +++ b/tests/Entity/PageTest.php @@ -14,7 +14,7 @@ class PageTest extends TestCase { /** @var Chapter $chapter */ $chapter = Chapter::query()->first(); - $page = factory(Page::class)->make([ + $page = Page::factory()->make([ 'name' => 'My First Page', ]); diff --git a/tests/Entity/SortTest.php b/tests/Entity/SortTest.php index 5cfc5c3c5..89279bfcf 100644 --- a/tests/Entity/SortTest.php +++ b/tests/Entity/SortTest.php @@ -12,7 +12,7 @@ class SortTest extends TestCase { protected $book; - public function setUp(): void + protected function setUp(): void { parent::setUp(); $this->book = Book::first(); diff --git a/tests/Entity/TagTest.php b/tests/Entity/TagTest.php index 74da37f4a..9b3fb1532 100644 --- a/tests/Entity/TagTest.php +++ b/tests/Entity/TagTest.php @@ -19,7 +19,7 @@ class TagTest extends TestCase $entity = $class::first(); if (is_null($tags)) { - $tags = factory(Tag::class, $this->defaultTagCount)->make(); + $tags = Tag::factory()->count($this->defaultTagCount)->make(); } $entity->tags()->saveMany($tags); @@ -31,63 +31,63 @@ class TagTest extends TestCase { // Create some tags with similar names to test with $attrs = collect(); - $attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'country'])); - $attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'color'])); - $attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'city'])); - $attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'county'])); - $attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'planet'])); - $attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'plans'])); + $attrs = $attrs->merge(Tag::factory()->count(5)->make(['name' => 'country'])); + $attrs = $attrs->merge(Tag::factory()->count(5)->make(['name' => 'color'])); + $attrs = $attrs->merge(Tag::factory()->count(5)->make(['name' => 'city'])); + $attrs = $attrs->merge(Tag::factory()->count(5)->make(['name' => 'county'])); + $attrs = $attrs->merge(Tag::factory()->count(5)->make(['name' => 'planet'])); + $attrs = $attrs->merge(Tag::factory()->count(5)->make(['name' => 'plans'])); $page = $this->getEntityWithTags(Page::class, $attrs->all()); - $this->asAdmin()->get('/ajax/tags/suggest/names?search=dog')->assertExactJson([]); - $this->get('/ajax/tags/suggest/names?search=co')->assertExactJson(['color', 'country', 'county']); - $this->get('/ajax/tags/suggest/names?search=cou')->assertExactJson(['country', 'county']); - $this->get('/ajax/tags/suggest/names?search=pla')->assertExactJson(['planet', 'plans']); + $this->asAdmin()->get('/ajax/tags/suggest/names?search=dog')->assertSimilarJson([]); + $this->get('/ajax/tags/suggest/names?search=co')->assertSimilarJson(['color', 'country', 'county']); + $this->get('/ajax/tags/suggest/names?search=cou')->assertSimilarJson(['country', 'county']); + $this->get('/ajax/tags/suggest/names?search=pla')->assertSimilarJson(['planet', 'plans']); } public function test_tag_value_suggestions() { // Create some tags with similar values to test with $attrs = collect(); - $attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'country', 'value' => 'cats'])); - $attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'color', 'value' => 'cattery'])); - $attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'city', 'value' => 'castle'])); - $attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'county', 'value' => 'dog'])); - $attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'planet', 'value' => 'catapult'])); - $attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'plans', 'value' => 'dodgy'])); + $attrs = $attrs->merge(Tag::factory()->count(5)->make(['name' => 'country', 'value' => 'cats'])); + $attrs = $attrs->merge(Tag::factory()->count(5)->make(['name' => 'color', 'value' => 'cattery'])); + $attrs = $attrs->merge(Tag::factory()->count(5)->make(['name' => 'city', 'value' => 'castle'])); + $attrs = $attrs->merge(Tag::factory()->count(5)->make(['name' => 'county', 'value' => 'dog'])); + $attrs = $attrs->merge(Tag::factory()->count(5)->make(['name' => 'planet', 'value' => 'catapult'])); + $attrs = $attrs->merge(Tag::factory()->count(5)->make(['name' => 'plans', 'value' => 'dodgy'])); $page = $this->getEntityWithTags(Page::class, $attrs->all()); - $this->asAdmin()->get('/ajax/tags/suggest/values?search=ora')->assertExactJson([]); - $this->get('/ajax/tags/suggest/values?search=cat')->assertExactJson(['cats', 'cattery', 'catapult']); - $this->get('/ajax/tags/suggest/values?search=do')->assertExactJson(['dog', 'dodgy']); - $this->get('/ajax/tags/suggest/values?search=cas')->assertExactJson(['castle']); + $this->asAdmin()->get('/ajax/tags/suggest/values?search=ora')->assertSimilarJson([]); + $this->get('/ajax/tags/suggest/values?search=cat')->assertSimilarJson(['cats', 'cattery', 'catapult']); + $this->get('/ajax/tags/suggest/values?search=do')->assertSimilarJson(['dog', 'dodgy']); + $this->get('/ajax/tags/suggest/values?search=cas')->assertSimilarJson(['castle']); } public function test_entity_permissions_effect_tag_suggestions() { // Create some tags with similar names to test with and save to a page $attrs = collect(); - $attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'country'])); - $attrs = $attrs->merge(factory(Tag::class, 5)->make(['name' => 'color'])); + $attrs = $attrs->merge(Tag::factory()->count(5)->make(['name' => 'country'])); + $attrs = $attrs->merge(Tag::factory()->count(5)->make(['name' => 'color'])); $page = $this->getEntityWithTags(Page::class, $attrs->all()); - $this->asAdmin()->get('/ajax/tags/suggest/names?search=co')->assertExactJson(['color', 'country']); - $this->asEditor()->get('/ajax/tags/suggest/names?search=co')->assertExactJson(['color', 'country']); + $this->asAdmin()->get('/ajax/tags/suggest/names?search=co')->assertSimilarJson(['color', 'country']); + $this->asEditor()->get('/ajax/tags/suggest/names?search=co')->assertSimilarJson(['color', 'country']); // Set restricted permission the page $page->restricted = true; $page->save(); $page->rebuildPermissions(); - $this->asAdmin()->get('/ajax/tags/suggest/names?search=co')->assertExactJson(['color', 'country']); - $this->asEditor()->get('/ajax/tags/suggest/names?search=co')->assertExactJson([]); + $this->asAdmin()->get('/ajax/tags/suggest/names?search=co')->assertSimilarJson(['color', 'country']); + $this->asEditor()->get('/ajax/tags/suggest/names?search=co')->assertSimilarJson([]); } public function test_tags_shown_on_search_listing() { $tags = [ - factory(Tag::class)->make(['name' => 'category', 'value' => 'buckets']), - factory(Tag::class)->make(['name' => 'color', 'value' => 'red']), + Tag::factory()->make(['name' => 'category', 'value' => 'buckets']), + Tag::factory()->make(['name' => 'color', 'value' => 'red']), ]; $page = $this->getEntityWithTags(Page::class, $tags); diff --git a/tests/HomepageTest.php b/tests/HomepageTest.php index e27b78774..dc1b22779 100644 --- a/tests/HomepageTest.php +++ b/tests/HomepageTest.php @@ -167,7 +167,7 @@ class HomepageTest extends TestCase public function test_new_users_dont_have_any_recently_viewed() { - $user = factory(User::class)->create(); + $user = User::factory()->create(); $viewRole = Role::getRole('Viewer'); $user->attachRole($viewRole); diff --git a/tests/LanguageTest.php b/tests/LanguageTest.php index a9070248e..ef44af0ee 100644 --- a/tests/LanguageTest.php +++ b/tests/LanguageTest.php @@ -9,7 +9,7 @@ class LanguageTest extends TestCase /** * LanguageTest constructor. */ - public function setUp(): void + protected function setUp(): void { parent::setUp(); $this->langs = array_diff(scandir(resource_path('lang')), ['..', '.']); diff --git a/tests/Permissions/EntityPermissionsTest.php b/tests/Permissions/EntityPermissionsTest.php index bb011cfc6..96d4792b9 100644 --- a/tests/Permissions/EntityPermissionsTest.php +++ b/tests/Permissions/EntityPermissionsTest.php @@ -23,7 +23,7 @@ class EntityPermissionsTest extends TestCase */ protected $viewer; - public function setUp(): void + protected function setUp(): void { parent::setUp(); $this->user = $this->getEditor(); diff --git a/tests/Permissions/RolesTest.php b/tests/Permissions/RolesTest.php index 3178bd8ce..c880bdd00 100644 --- a/tests/Permissions/RolesTest.php +++ b/tests/Permissions/RolesTest.php @@ -19,7 +19,7 @@ class RolesTest extends TestCase { protected $user; - public function setUp(): void + protected function setUp(): void { parent::setUp(); $this->user = $this->getViewer(); @@ -769,7 +769,7 @@ class RolesTest extends TestCase $this->giveUserPermissions($this->user, ['image-update-all']); /** @var Page $page */ $page = Page::query()->first(); - $image = factory(Image::class)->create([ + $image = Image::factory()->create([ 'uploaded_to' => $page->id, 'created_by' => $this->user->id, 'updated_by' => $this->user->id, @@ -789,7 +789,7 @@ class RolesTest extends TestCase $admin = $this->getAdmin(); /** @var Page $page */ $page = Page::query()->first(); - $image = factory(Image::class)->create(['uploaded_to' => $page->id, 'created_by' => $admin->id, 'updated_by' => $admin->id]); + $image = Image::factory()->create(['uploaded_to' => $page->id, 'created_by' => $admin->id, 'updated_by' => $admin->id]); $this->actingAs($this->user)->json('delete', '/images/' . $image->id)->assertStatus(403); @@ -825,14 +825,14 @@ class RolesTest extends TestCase { $admin = $this->getAdmin(); // Book links - $book = factory(Book::class)->create(['created_by' => $admin->id, 'updated_by' => $admin->id]); + $book = Book::factory()->create(['created_by' => $admin->id, 'updated_by' => $admin->id]); $this->regenEntityPermissions($book); $this->actingAs($this->getViewer())->get($book->getUrl()) ->assertDontSee('Create a new page') ->assertDontSee('Add a chapter'); // Chapter links - $chapter = factory(Chapter::class)->create(['created_by' => $admin->id, 'updated_by' => $admin->id, 'book_id' => $book->id]); + $chapter = Chapter::factory()->create(['created_by' => $admin->id, 'updated_by' => $admin->id, 'book_id' => $book->id]); $this->regenEntityPermissions($chapter); $this->actingAs($this->getViewer())->get($chapter->getUrl()) ->assertDontSee('Create a new page') @@ -926,14 +926,14 @@ class RolesTest extends TestCase private function addComment(Page $page): TestResponse { - $comment = factory(Comment::class)->make(); + $comment = Comment::factory()->make(); return $this->postJson("/comment/$page->id", $comment->only('text', 'html')); } private function updateComment(Comment $comment): TestResponse { - $commentData = factory(Comment::class)->make(); + $commentData = Comment::factory()->make(); return $this->putJson("/comment/{$comment->id}", $commentData->only('text', 'html')); } diff --git a/tests/SharedTestHelpers.php b/tests/SharedTestHelpers.php index d96fcb710..cbf49bf71 100644 --- a/tests/SharedTestHelpers.php +++ b/tests/SharedTestHelpers.php @@ -210,7 +210,7 @@ trait SharedTestHelpers protected function createNewRole(array $permissions = []): Role { $permissionRepo = app(PermissionsRepo::class); - $roleData = factory(Role::class)->make()->toArray(); + $roleData = Role::factory()->make()->toArray(); $roleData['permissions'] = array_flip($permissions); return $permissionRepo->saveNewRole($roleData); @@ -228,9 +228,9 @@ trait SharedTestHelpers } $userAttrs = ['created_by' => $creatorUser->id, 'owned_by' => $creatorUser->id, 'updated_by' => $updaterUser->id]; - $book = factory(Book::class)->create($userAttrs); - $chapter = factory(Chapter::class)->create(array_merge(['book_id' => $book->id], $userAttrs)); - $page = factory(Page::class)->create(array_merge(['book_id' => $book->id, 'chapter_id' => $chapter->id], $userAttrs)); + $book = Book::factory()->create($userAttrs); + $chapter = Chapter::factory()->create(array_merge(['book_id' => $book->id], $userAttrs)); + $page = Page::factory()->create(array_merge(['book_id' => $book->id, 'chapter_id' => $chapter->id], $userAttrs)); $restrictionService = $this->app[PermissionService::class]; $restrictionService->buildJointPermissionsForEntity($book); diff --git a/tests/ThemeTest.php b/tests/ThemeTest.php index 2cab765ae..9aa7873b0 100644 --- a/tests/ThemeTest.php +++ b/tests/ThemeTest.php @@ -150,7 +150,7 @@ class ThemeTest extends TestCase Theme::listen(ThemeEvents::AUTH_REGISTER, $callback); $this->setSettings(['registration-enabled' => 'true']); - $user = factory(User::class)->make(); + $user = User::factory()->make(); $this->post('/register', ['email' => $user->email, 'name' => $user->name, 'password' => 'password']); $this->assertCount(2, $args); diff --git a/tests/Uploads/AvatarTest.php b/tests/Uploads/AvatarTest.php index cf568d07c..d10b5cfc6 100644 --- a/tests/Uploads/AvatarTest.php +++ b/tests/Uploads/AvatarTest.php @@ -42,7 +42,7 @@ class AvatarTest extends TestCase config()->set([ 'services.disable_services' => false, ]); - $user = factory(User::class)->make(); + $user = User::factory()->make(); $this->assertImageFetchFrom('https://www.gravatar.com/avatar/' . md5(strtolower($user->email)) . '?s=500&d=identicon'); $user = $this->createUserRequest($user); @@ -60,7 +60,7 @@ class AvatarTest extends TestCase 'services.avatar_url' => 'https://example.com/${email}/${hash}/${size}', ]); - $user = factory(User::class)->make(); + $user = User::factory()->make(); $url = 'https://example.com/' . urlencode(strtolower($user->email)) . '/' . md5(strtolower($user->email)) . '/500'; $this->assertImageFetchFrom($url); @@ -74,7 +74,7 @@ class AvatarTest extends TestCase 'services.disable_services' => true, ]); - $user = factory(User::class)->make(); + $user = User::factory()->make(); $http = $this->mock(HttpFetcher::class); $http->shouldNotReceive('fetch'); @@ -93,7 +93,7 @@ class AvatarTest extends TestCase $logger = $this->withTestLogger(); - $user = factory(User::class)->make(); + $user = User::factory()->make(); $this->createUserRequest($user); $this->assertTrue($logger->hasError('Failed to save user avatar image')); } diff --git a/tests/User/UserManagementTest.php b/tests/User/UserManagementTest.php index ed2fb5f04..5a36b85df 100644 --- a/tests/User/UserManagementTest.php +++ b/tests/User/UserManagementTest.php @@ -15,7 +15,7 @@ class UserManagementTest extends TestCase public function test_user_creation() { /** @var User $user */ - $user = factory(User::class)->make(); + $user = User::factory()->make(); $adminRole = Role::getRole('admin'); $resp = $this->asAdmin()->get('/settings/users'); diff --git a/tests/User/UserProfileTest.php b/tests/User/UserProfileTest.php index 3942efa8e..c3888f8c5 100644 --- a/tests/User/UserProfileTest.php +++ b/tests/User/UserProfileTest.php @@ -14,7 +14,7 @@ class UserProfileTest extends TestCase */ protected $user; - public function setUp(): void + protected function setUp(): void { parent::setUp(); $this->user = User::all()->last(); @@ -42,7 +42,7 @@ class UserProfileTest extends TestCase public function test_profile_page_shows_created_content_counts() { - $newUser = factory(User::class)->create(); + $newUser = User::factory()->create(); $this->asAdmin()->get('/user/' . $newUser->slug) ->assertSee($newUser->name) @@ -61,7 +61,7 @@ class UserProfileTest extends TestCase public function test_profile_page_shows_recent_activity() { - $newUser = factory(User::class)->create(); + $newUser = User::factory()->create(); $this->actingAs($newUser); $entities = $this->createEntityChainBelongingToUser($newUser, $newUser); Activity::addForEntity($entities['book'], ActivityType::BOOK_UPDATE); @@ -75,7 +75,7 @@ class UserProfileTest extends TestCase public function test_user_activity_has_link_leading_to_profile() { - $newUser = factory(User::class)->create(); + $newUser = User::factory()->create(); $this->actingAs($newUser); $entities = $this->createEntityChainBelongingToUser($newUser, $newUser); Activity::addForEntity($entities['book'], ActivityType::BOOK_UPDATE); From 98b23fd7ab98008319f461cafc829cc6f48d1b07 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 30 Oct 2021 22:03:36 +0100 Subject: [PATCH 03/59] Moved from debugbar to clockwork --- app/Config/clockwork.php | 415 +++++++++++++++++++++++++++++++++++ composer.json | 2 +- composer.lock | 227 ++++--------------- readme.md | 10 +- storage/clockwork/.gitignore | 3 + 5 files changed, 462 insertions(+), 195 deletions(-) create mode 100644 app/Config/clockwork.php create mode 100644 storage/clockwork/.gitignore diff --git a/app/Config/clockwork.php b/app/Config/clockwork.php new file mode 100644 index 000000000..ff9929d52 --- /dev/null +++ b/app/Config/clockwork.php @@ -0,0 +1,415 @@ + env('CLOCKWORK_ENABLE', false), + + /* + |------------------------------------------------------------------------------------------------------------------ + | Features + |------------------------------------------------------------------------------------------------------------------ + | + | You can enable or disable various Clockwork features here. Some features have additional settings (eg. slow query + | threshold for database queries). + | + */ + + 'features' => [ + + // Cache usage stats and cache queries including results + 'cache' => [ + 'enabled' => true, + + // Collect cache queries + 'collect_queries' => true, + + // Collect values from cache queries (high performance impact with a very high number of queries) + 'collect_values' => false + ], + + // Database usage stats and queries + 'database' => [ + 'enabled' => true, + + // Collect database queries (high performance impact with a very high number of queries) + 'collect_queries' => true, + + // Collect details of models updates (high performance impact with a lot of model updates) + 'collect_models_actions' => true, + + // Collect details of retrieved models (very high performance impact with a lot of models retrieved) + 'collect_models_retrieved' => false, + + // Query execution time threshold in miliseconds after which the query will be marked as slow + 'slow_threshold' => null, + + // Collect only slow database queries + 'slow_only' => false, + + // Detect and report duplicate (N+1) queries + 'detect_duplicate_queries' => false + ], + + // Dispatched events + 'events' => [ + 'enabled' => true, + + // Ignored events (framework events are ignored by default) + 'ignored_events' => [ + // App\Events\UserRegistered::class, + // 'user.registered' + ], + ], + + // Laravel log (you can still log directly to Clockwork with laravel log disabled) + 'log' => [ + 'enabled' => true + ], + + // Sent notifications + 'notifications' => [ + 'enabled' => true, + ], + + // Performance metrics + 'performance' => [ + // Allow collecting of client metrics. Requires separate clockwork-browser npm package. + 'client_metrics' => true + ], + + // Dispatched queue jobs + 'queue' => [ + 'enabled' => true + ], + + // Redis commands + 'redis' => [ + 'enabled' => true + ], + + // Routes list + 'routes' => [ + 'enabled' => false, + + // Collect only routes from particular namespaces (only application routes by default) + 'only_namespaces' => [ 'App' ] + ], + + // Rendered views + 'views' => [ + 'enabled' => true, + + // Collect views including view data (high performance impact with a high number of views) + 'collect_data' => false, + + // Use Twig profiler instead of Laravel events for apps using laravel-twigbridge (more precise, but does + // not support collecting view data) + 'use_twig_profiler' => false + ] + + ], + + /* + |------------------------------------------------------------------------------------------------------------------ + | Enable web UI + |------------------------------------------------------------------------------------------------------------------ + | + | Clockwork comes with a web UI accessibla via http://your.app/clockwork. Here you can enable or disable this + | feature. You can also set a custom path for the web UI. + | + */ + + 'web' => true, + + /* + |------------------------------------------------------------------------------------------------------------------ + | Enable toolbar + |------------------------------------------------------------------------------------------------------------------ + | + | Clockwork can show a toolbar with basic metrics on all responses. Here you can enable or disable this feature. + | Requires a separate clockwork-browser npm library. + | For installation instructions see https://underground.works/clockwork/#docs-viewing-data + | + */ + + 'toolbar' => true, + + /* + |------------------------------------------------------------------------------------------------------------------ + | HTTP requests collection + |------------------------------------------------------------------------------------------------------------------ + | + | Clockwork collects data about HTTP requests to your app. Here you can choose which requests should be collected. + | + */ + + 'requests' => [ + // With on-demand mode enabled, Clockwork will only profile requests when the browser extension is open or you + // manually pass a "clockwork-profile" cookie or get/post data key. + // Optionally you can specify a "secret" that has to be passed as the value to enable profiling. + 'on_demand' => false, + + // Collect only errors (requests with HTTP 4xx and 5xx responses) + 'errors_only' => false, + + // Response time threshold in miliseconds after which the request will be marked as slow + 'slow_threshold' => null, + + // Collect only slow requests + 'slow_only' => false, + + // Sample the collected requests (eg. set to 100 to collect only 1 in 100 requests) + 'sample' => false, + + // List of URIs that should not be collected + 'except' => [ + '/horizon/.*', // Laravel Horizon requests + '/telescope/.*', // Laravel Telescope requests + '/_debugbar/.*', // Laravel DebugBar requests + ], + + // List of URIs that should be collected, any other URI will not be collected if not empty + 'only' => [ + // '/api/.*' + ], + + // Don't collect OPTIONS requests, mostly used in the CSRF pre-flight requests and are rarely of interest + 'except_preflight' => true + ], + + /* + |------------------------------------------------------------------------------------------------------------------ + | Artisan commands collection + |------------------------------------------------------------------------------------------------------------------ + | + | Clockwork can collect data about executed artisan commands. Here you can enable and configure which commands + | should be collected. + | + */ + + 'artisan' => [ + // Enable or disable collection of executed Artisan commands + 'collect' => false, + + // List of commands that should not be collected (built-in commands are not collected by default) + 'except' => [ + // 'inspire' + ], + + // List of commands that should be collected, any other command will not be collected if not empty + 'only' => [ + // 'inspire' + ], + + // Enable or disable collection of command output + 'collect_output' => false, + + // Enable or disable collection of built-in Laravel commands + 'except_laravel_commands' => true + ], + + /* + |------------------------------------------------------------------------------------------------------------------ + | Queue jobs collection + |------------------------------------------------------------------------------------------------------------------ + | + | Clockwork can collect data about executed queue jobs. Here you can enable and configure which queue jobs should + | be collected. + | + */ + + 'queue' => [ + // Enable or disable collection of executed queue jobs + 'collect' => false, + + // List of queue jobs that should not be collected + 'except' => [ + // App\Jobs\ExpensiveJob::class + ], + + // List of queue jobs that should be collected, any other queue job will not be collected if not empty + 'only' => [ + // App\Jobs\BuggyJob::class + ] + ], + + /* + |------------------------------------------------------------------------------------------------------------------ + | Tests collection + |------------------------------------------------------------------------------------------------------------------ + | + | Clockwork can collect data about executed tests. Here you can enable and configure which tests should be + | collected. + | + */ + + 'tests' => [ + // Enable or disable collection of ran tests + 'collect' => false, + + // List of tests that should not be collected + 'except' => [ + // Tests\Unit\ExampleTest::class + ] + ], + + /* + |------------------------------------------------------------------------------------------------------------------ + | Enable data collection when Clockwork is disabled + |------------------------------------------------------------------------------------------------------------------ + | + | You can enable this setting to collect data even when Clockwork is disabled. Eg. for future analysis. + | + */ + + 'collect_data_always' => false, + + /* + |------------------------------------------------------------------------------------------------------------------ + | Metadata storage + |------------------------------------------------------------------------------------------------------------------ + | + | Configure how is the metadata collected by Clockwork stored. Two options are available: + | - files - A simple fast storage implementation storing data in one-per-request files. + | - sql - Stores requests in a sql database. Supports MySQL, Postgresql, Sqlite and requires PDO. + | + */ + + 'storage' => 'files', + + // Path where the Clockwork metadata is stored + 'storage_files_path' => storage_path('clockwork'), + + // Compress the metadata files using gzip, trading a little bit of performance for lower disk usage + 'storage_files_compress' => false, + + // SQL database to use, can be a name of database configured in database.php or a path to a sqlite file + 'storage_sql_database' => storage_path('clockwork.sqlite'), + + // SQL table name to use, the table is automatically created and udpated when needed + 'storage_sql_table' => 'clockwork', + + // Maximum lifetime of collected metadata in minutes, older requests will automatically be deleted, false to disable + 'storage_expiration' => 60 * 24 * 7, + + /* + |------------------------------------------------------------------------------------------------------------------ + | Authentication + |------------------------------------------------------------------------------------------------------------------ + | + | Clockwork can be configured to require authentication before allowing access to the collected data. This might be + | useful when the application is publicly accessible. Setting to true will enable a simple authentication with a + | pre-configured password. You can also pass a class name of a custom implementation. + | + */ + + 'authentication' => false, + + // Password for the simple authentication + 'authentication_password' => 'VerySecretPassword', + + /* + |------------------------------------------------------------------------------------------------------------------ + | Stack traces collection + |------------------------------------------------------------------------------------------------------------------ + | + | Clockwork can collect stack traces for log messages and certain data like database queries. Here you can set + | whether to collect stack traces, limit the number of collected frames and set further configuration. Collecting + | long stack traces considerably increases metadata size. + | + */ + + 'stack_traces' => [ + // Enable or disable collecting of stack traces + 'enabled' => true, + + // Limit the number of frames to be collected + 'limit' => 10, + + // List of vendor names to skip when determining caller, common vendors are automatically added + 'skip_vendors' => [ + // 'phpunit' + ], + + // List of namespaces to skip when determining caller + 'skip_namespaces' => [ + // 'Laravel' + ], + + // List of class names to skip when determining caller + 'skip_classes' => [ + // App\CustomLog::class + ] + + ], + + /* + |------------------------------------------------------------------------------------------------------------------ + | Serialization + |------------------------------------------------------------------------------------------------------------------ + | + | Clockwork serializes the collected data to json for storage and transfer. Here you can configure certain aspects + | of serialization. Serialization has a large effect on the cpu time and memory usage. + | + */ + + // Maximum depth of serialized multi-level arrays and objects + 'serialization_depth' => 10, + + // A list of classes that will never be serialized (eg. a common service container class) + 'serialization_blackbox' => [ + \Illuminate\Container\Container::class, + \Illuminate\Foundation\Application::class, + ], + + /* + |------------------------------------------------------------------------------------------------------------------ + | Register helpers + |------------------------------------------------------------------------------------------------------------------ + | + | Clockwork comes with a "clock" global helper function. You can use this helper to quickly log something and to + | access the Clockwork instance. + | + */ + + 'register_helpers' => true, + + /* + |------------------------------------------------------------------------------------------------------------------ + | Send Headers for AJAX request + |------------------------------------------------------------------------------------------------------------------ + | + | When trying to collect data the AJAX method can sometimes fail if it is missing required headers. For example, an + | API might require a version number using Accept headers to route the HTTP request to the correct codebase. + | + */ + + 'headers' => [ + // 'Accept' => 'application/vnd.com.whatever.v1+json', + ], + + /* + |------------------------------------------------------------------------------------------------------------------ + | Server-Timing + |------------------------------------------------------------------------------------------------------------------ + | + | Clockwork supports the W3C Server Timing specification, which allows for collecting a simple performance metrics + | in a cross-browser way. Eg. in Chrome, your app, database and timeline event timings will be shown in the Dev + | Tools network tab. This setting specifies the max number of timeline events that will be sent. Setting to false + | will disable the feature. + | + */ + + 'server_timing' => 10 + +]; diff --git a/composer.json b/composer.json index c1d5c1e4b..c4d9cd904 100644 --- a/composer.json +++ b/composer.json @@ -44,8 +44,8 @@ "ssddanbrown/htmldiff": "^1.0.1" }, "require-dev": { - "barryvdh/laravel-debugbar": "^3.6", "fakerphp/faker": "^1.13.0", + "itsgoingd/clockwork": "^5.1", "mockery/mockery": "^1.4.2", "phpunit/phpunit": "^9.5.3", "symfony/dom-crawler": "^5.3", diff --git a/composer.lock b/composer.lock index 17e57df71..7231c82c4 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "9a5d92382b2955dd7de41de5fa9f86b5", + "content-hash": "0dfe612653577a14906a0bb031c67a97", "packages": [ { "name": "aws/aws-crt-php", @@ -7441,91 +7441,6 @@ } ], "packages-dev": [ - { - "name": "barryvdh/laravel-debugbar", - "version": "v3.6.4", - "source": { - "type": "git", - "url": "https://github.com/barryvdh/laravel-debugbar.git", - "reference": "3c2d678269ba60e178bcd93e36f6a91c36b727f1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/3c2d678269ba60e178bcd93e36f6a91c36b727f1", - "reference": "3c2d678269ba60e178bcd93e36f6a91c36b727f1", - "shasum": "" - }, - "require": { - "illuminate/routing": "^6|^7|^8", - "illuminate/session": "^6|^7|^8", - "illuminate/support": "^6|^7|^8", - "maximebf/debugbar": "^1.17.2", - "php": ">=7.2", - "symfony/debug": "^4.3|^5", - "symfony/finder": "^4.3|^5" - }, - "require-dev": { - "mockery/mockery": "^1.3.3", - "orchestra/testbench-dusk": "^4|^5|^6", - "phpunit/phpunit": "^8.5|^9.0", - "squizlabs/php_codesniffer": "^3.5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.6-dev" - }, - "laravel": { - "providers": [ - "Barryvdh\\Debugbar\\ServiceProvider" - ], - "aliases": { - "Debugbar": "Barryvdh\\Debugbar\\Facade" - } - } - }, - "autoload": { - "psr-4": { - "Barryvdh\\Debugbar\\": "src/" - }, - "files": [ - "src/helpers.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Barry vd. Heuvel", - "email": "barryvdh@gmail.com" - } - ], - "description": "PHP Debugbar integration for Laravel", - "keywords": [ - "debug", - "debugbar", - "laravel", - "profiler", - "webprofiler" - ], - "support": { - "issues": "https://github.com/barryvdh/laravel-debugbar/issues", - "source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.6.4" - }, - "funding": [ - { - "url": "https://fruitcake.nl", - "type": "custom" - }, - { - "url": "https://github.com/barryvdh", - "type": "github" - } - ], - "time": "2021-10-21T10:57:31+00:00" - }, { "name": "doctrine/instantiator", "version": "1.4.0", @@ -7765,41 +7680,38 @@ "time": "2020-07-09T08:09:16+00:00" }, { - "name": "maximebf/debugbar", - "version": "v1.17.2", + "name": "itsgoingd/clockwork", + "version": "v5.1.0", "source": { "type": "git", - "url": "https://github.com/maximebf/php-debugbar.git", - "reference": "3541f09f09c003c4a9ff7ddb0eb3361a7f14d418" + "url": "https://github.com/itsgoingd/clockwork.git", + "reference": "b963dee47429a49c9669981cfa9a8362ce209278" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/3541f09f09c003c4a9ff7ddb0eb3361a7f14d418", - "reference": "3541f09f09c003c4a9ff7ddb0eb3361a7f14d418", + "url": "https://api.github.com/repos/itsgoingd/clockwork/zipball/b963dee47429a49c9669981cfa9a8362ce209278", + "reference": "b963dee47429a49c9669981cfa9a8362ce209278", "shasum": "" }, "require": { - "php": "^7.1|^8", - "psr/log": "^1|^2|^3", - "symfony/var-dumper": "^2.6|^3|^4|^5" - }, - "require-dev": { - "phpunit/phpunit": "^7.5.20 || ^9.4.2" - }, - "suggest": { - "kriswallsmith/assetic": "The best way to manage assets", - "monolog/monolog": "Log using Monolog", - "predis/predis": "Redis storage" + "ext-json": "*", + "php": ">=5.6", + "psr/log": "1.*" }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "1.17-dev" + "laravel": { + "providers": [ + "Clockwork\\Support\\Laravel\\ClockworkServiceProvider" + ], + "aliases": { + "Clockwork": "Clockwork\\Support\\Laravel\\Facade" + } } }, "autoload": { "psr-4": { - "DebugBar\\": "src/DebugBar/" + "Clockwork\\": "Clockwork/" } }, "notification-url": "https://packagist.org/downloads/", @@ -7808,26 +7720,33 @@ ], "authors": [ { - "name": "Maxime Bouroumeau-Fuseau", - "email": "maxime.bouroumeau@gmail.com", - "homepage": "http://maximebf.com" - }, - { - "name": "Barry vd. Heuvel", - "email": "barryvdh@gmail.com" + "name": "itsgoingd", + "email": "itsgoingd@luzer.sk", + "homepage": "https://twitter.com/itsgoingd" } ], - "description": "Debug bar in the browser for php application", - "homepage": "https://github.com/maximebf/php-debugbar", + "description": "php dev tools in your browser", + "homepage": "https://underground.works/clockwork", "keywords": [ - "debug", - "debugbar" + "Devtools", + "debugging", + "laravel", + "logging", + "lumen", + "profiling", + "slim" ], "support": { - "issues": "https://github.com/maximebf/php-debugbar/issues", - "source": "https://github.com/maximebf/php-debugbar/tree/v1.17.2" + "issues": "https://github.com/itsgoingd/clockwork/issues", + "source": "https://github.com/itsgoingd/clockwork/tree/v5.1.0" }, - "time": "2021-10-18T09:39:00+00:00" + "funding": [ + { + "url": "https://github.com/itsgoingd", + "type": "github" + } + ], + "time": "2021-08-07T23:04:17+00:00" }, { "name": "mockery/mockery", @@ -9769,74 +9688,6 @@ ], "time": "2020-09-28T06:39:44+00:00" }, - { - "name": "symfony/debug", - "version": "v4.4.31", - "source": { - "type": "git", - "url": "https://github.com/symfony/debug.git", - "reference": "43ede438d4cb52cd589ae5dc070e9323866ba8e0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/43ede438d4cb52cd589ae5dc070e9323866ba8e0", - "reference": "43ede438d4cb52cd589ae5dc070e9323866ba8e0", - "shasum": "" - }, - "require": { - "php": ">=7.1.3", - "psr/log": "^1|^2|^3" - }, - "conflict": { - "symfony/http-kernel": "<3.4" - }, - "require-dev": { - "symfony/http-kernel": "^3.4|^4.0|^5.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Debug\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides tools to ease debugging PHP code", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/debug/tree/v4.4.31" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2021-09-24T13:30:14+00:00" - }, { "name": "symfony/dom-crawler", "version": "v5.3.7", diff --git a/readme.md b/readme.md index 17ac9641b..0c9cf66e9 100644 --- a/readme.md +++ b/readme.md @@ -187,11 +187,8 @@ These are the great open-source projects used to help build BookStack: * [Dropzone.js](http://www.dropzonejs.com/) * [clipboard.js](https://clipboardjs.com/) * [markdown-it](https://github.com/markdown-it/markdown-it) and [markdown-it-task-lists](https://github.com/revin/markdown-it-task-lists) -* [BarryVD](https://github.com/barryvdh) - * [Debugbar](https://github.com/barryvdh/laravel-debugbar) - * [Dompdf](https://github.com/barryvdh/laravel-dompdf) - * [Snappy (WKHTML2PDF)](https://github.com/barryvdh/laravel-snappy) - * [Laravel IDE helper](https://github.com/barryvdh/laravel-ide-helper) +* [BarryVD/Dompdf](https://github.com/barryvdh/laravel-dompdf) +* [BarryVD/Snappy (WKHTML2PDF)](https://github.com/barryvdh/laravel-snappy) * [WKHTMLtoPDF](http://wkhtmltopdf.org/index.html) * [diagrams.net](https://github.com/jgraph/drawio) * [OneLogin's SAML PHP Toolkit](https://github.com/onelogin/php-saml) @@ -200,4 +197,5 @@ These are the great open-source projects used to help build BookStack: * [StyleCI](https://styleci.io/) * [pragmarx/google2fa](https://github.com/antonioribeiro/google2fa) * [Bacon/BaconQrCode](https://github.com/Bacon/BaconQrCode) -* [phpseclib](https://github.com/phpseclib/phpseclib) \ No newline at end of file +* [phpseclib](https://github.com/phpseclib/phpseclib) +* [Clockwork](https://github.com/itsgoingd/clockwork) \ No newline at end of file diff --git a/storage/clockwork/.gitignore b/storage/clockwork/.gitignore new file mode 100644 index 000000000..3fac1bff8 --- /dev/null +++ b/storage/clockwork/.gitignore @@ -0,0 +1,3 @@ +*.json +*.json.gz +index From 7e2c1b31a14e3409cdb7213b4058d8589761f660 Mon Sep 17 00:00:00 2001 From: na3shkw <48012204+na3shkw@users.noreply.github.com> Date: Mon, 1 Nov 2021 12:41:23 +0000 Subject: [PATCH 04/59] Modernize third party services' logos --- resources/icons/auth/facebook.svg | 2 +- resources/icons/auth/slack.svg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/icons/auth/facebook.svg b/resources/icons/auth/facebook.svg index 7bfafd226..4c1c5a271 100644 --- a/resources/icons/auth/facebook.svg +++ b/resources/icons/auth/facebook.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/resources/icons/auth/slack.svg b/resources/icons/auth/slack.svg index 5280f971f..98e5a32f5 100644 --- a/resources/icons/auth/slack.svg +++ b/resources/icons/auth/slack.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file From cccee0808f6a9c67e11da14368fc1ed917b6cd96 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Thu, 4 Nov 2021 22:02:21 +0000 Subject: [PATCH 05/59] Updated API examples with date format changes Updated to full ISO-8601 to reflect change in Laravel 7. --- dev/api/responses/attachments-create.json | 4 ++-- dev/api/responses/attachments-list.json | 8 ++++---- dev/api/responses/attachments-read.json | 4 ++-- dev/api/responses/attachments-update.json | 4 ++-- dev/api/responses/books-create.json | 4 ++-- dev/api/responses/books-list.json | 8 ++++---- dev/api/responses/books-read.json | 8 ++++---- dev/api/responses/books-update.json | 4 ++-- dev/api/responses/chapters-create.json | 16 ++++++++-------- dev/api/responses/chapters-list.json | 8 ++++---- dev/api/responses/chapters-read.json | 12 ++++++------ dev/api/responses/chapters-update.json | 16 ++++++++-------- dev/api/responses/pages-create.json | 4 ++-- dev/api/responses/pages-list.json | 12 ++++++------ dev/api/responses/pages-read.json | 4 ++-- dev/api/responses/pages-update.json | 4 ++-- dev/api/responses/shelves-create.json | 4 ++-- dev/api/responses/shelves-list.json | 12 ++++++------ dev/api/responses/shelves-read.json | 8 ++++---- dev/api/responses/shelves-update.json | 4 ++-- 20 files changed, 74 insertions(+), 74 deletions(-) diff --git a/dev/api/responses/attachments-create.json b/dev/api/responses/attachments-create.json index 5af524e1a..ee1b21ac0 100644 --- a/dev/api/responses/attachments-create.json +++ b/dev/api/responses/attachments-create.json @@ -7,6 +7,6 @@ "order": 2, "created_by": 1, "updated_by": 1, - "created_at": "2021-10-20 06:35:46", - "updated_at": "2021-10-20 06:35:46" + "created_at": "2021-10-20T06:35:46.000000Z", + "updated_at": "2021-10-20T06:35:46.000000Z" } \ No newline at end of file diff --git a/dev/api/responses/attachments-list.json b/dev/api/responses/attachments-list.json index 946dd542a..af652d5ed 100644 --- a/dev/api/responses/attachments-list.json +++ b/dev/api/responses/attachments-list.json @@ -7,8 +7,8 @@ "uploaded_to": 8, "external": false, "order": 1, - "created_at": "2021-10-11 06:18:49", - "updated_at": "2021-10-20 06:31:10", + "created_at": "2021-10-11T06:18:49.000000Z", + "updated_at": "2021-10-20T06:31:10.000000Z", "created_by": 1, "updated_by": 1 }, @@ -19,8 +19,8 @@ "uploaded_to": 9, "external": true, "order": 1, - "created_at": "2021-10-20 06:30:11", - "updated_at": "2021-10-20 06:30:11", + "created_at": "2021-10-20T06:30:11.000000Z", + "updated_at": "2021-10-20T06:30:11.000000Z", "created_by": 1, "updated_by": 1 } diff --git a/dev/api/responses/attachments-read.json b/dev/api/responses/attachments-read.json index e22f4e5fe..48d6f72e6 100644 --- a/dev/api/responses/attachments-read.json +++ b/dev/api/responses/attachments-read.json @@ -15,8 +15,8 @@ "name": "Admin", "slug": "admin" }, - "created_at": "2021-10-20 06:35:46", - "updated_at": "2021-10-20 06:37:11", + "created_at": "2021-10-20T06:35:46.000000Z", + "updated_at": "2021-10-20T06:37:11.000000Z", "links": { "html": "My updated attachment", "markdown": "[My updated attachment](https://bookstack.local/attachments/5)" diff --git a/dev/api/responses/attachments-update.json b/dev/api/responses/attachments-update.json index 8054b0e48..43689eb61 100644 --- a/dev/api/responses/attachments-update.json +++ b/dev/api/responses/attachments-update.json @@ -7,6 +7,6 @@ "order": 2, "created_by": 1, "updated_by": 1, - "created_at": "2021-10-20 06:35:46", - "updated_at": "2021-10-20 06:37:11" + "created_at": "2021-10-20T06:35:46.000000Z", + "updated_at": "2021-10-20T06:37:11.000000Z" } \ No newline at end of file diff --git a/dev/api/responses/books-create.json b/dev/api/responses/books-create.json index 124305c8c..ede6fcc8e 100644 --- a/dev/api/responses/books-create.json +++ b/dev/api/responses/books-create.json @@ -5,7 +5,7 @@ "updated_by": 1, "owned_by": 1, "slug": "my-new-book", - "updated_at": "2020-01-12 14:05:11", - "created_at": "2020-01-12 14:05:11", + "updated_at": "2020-01-12T14:05:11.000000Z", + "created_at": "2020-01-12T14:05:11.000000Z", "id": 15 } \ No newline at end of file diff --git a/dev/api/responses/books-list.json b/dev/api/responses/books-list.json index 9900b5b04..45a8c542f 100644 --- a/dev/api/responses/books-list.json +++ b/dev/api/responses/books-list.json @@ -5,8 +5,8 @@ "name": "BookStack User Guide", "slug": "bookstack-user-guide", "description": "This is a general guide on using BookStack on a day-to-day basis.", - "created_at": "2019-05-05 21:48:46", - "updated_at": "2019-12-11 20:57:31", + "created_at": "2019-05-05T21:48:46.000000Z", + "updated_at": "2019-12-11T20:57:31.000000Z", "created_by": 1, "updated_by": 1, "owned_by": 1, @@ -17,8 +17,8 @@ "name": "Inventore inventore quia voluptatem.", "slug": "inventore-inventore-quia-voluptatem", "description": "Veniam nihil voluptas enim laborum corporis quos sint. Ab rerum voluptas ut iste voluptas magni quibusdam ut. Amet omnis enim voluptate neque facilis.", - "created_at": "2019-05-05 22:10:14", - "updated_at": "2019-12-11 20:57:23", + "created_at": "2019-05-05T22:10:14.000000Z", + "updated_at": "2019-12-11T20:57:23.000000Z", "created_by": 4, "updated_by": 3, "owned_by": 3, diff --git a/dev/api/responses/books-read.json b/dev/api/responses/books-read.json index 0b0bce4e8..7de85addc 100644 --- a/dev/api/responses/books-read.json +++ b/dev/api/responses/books-read.json @@ -3,8 +3,8 @@ "name": "My own book", "slug": "my-own-book", "description": "This is my own little book", - "created_at": "2020-01-12 14:09:59", - "updated_at": "2020-01-12 14:11:51", + "created_at": "2020-01-12T14:09:59.000000Z", + "updated_at": "2020-01-12T14:11:51.000000Z", "created_by": { "id": 1, "name": "Admin" @@ -29,8 +29,8 @@ "id": 452, "name": "sjovall_m117hUWMu40.jpg", "url": "http:\/\/bookstack.local\/uploads\/images\/cover_book\/2020-01\/sjovall_m117hUWMu40.jpg", - "created_at": "2020-01-12 14:11:51", - "updated_at": "2020-01-12 14:11:51", + "created_at": "2020-01-12T14:11:51.000000Z", + "updated_at": "2020-01-12T14:11:51.000000Z", "created_by": 1, "updated_by": 1, "path": "\/uploads\/images\/cover_book\/2020-01\/sjovall_m117hUWMu40.jpg", diff --git a/dev/api/responses/books-update.json b/dev/api/responses/books-update.json index fd93dc9ae..30c910aa3 100644 --- a/dev/api/responses/books-update.json +++ b/dev/api/responses/books-update.json @@ -3,8 +3,8 @@ "name": "My own book", "slug": "my-own-book", "description": "This is my own little book - updated", - "created_at": "2020-01-12 14:09:59", - "updated_at": "2020-01-12 14:16:10", + "created_at": "2020-01-12T14:09:59.000000Z", + "updated_at": "2020-01-12T14:16:10.000000Z", "created_by": 1, "updated_by": 1, "owned_by": 1, diff --git a/dev/api/responses/chapters-create.json b/dev/api/responses/chapters-create.json index a990f278b..81b422c25 100644 --- a/dev/api/responses/chapters-create.json +++ b/dev/api/responses/chapters-create.json @@ -7,16 +7,16 @@ "updated_by": 1, "owned_by": 1, "slug": "my-fantastic-new-chapter", - "updated_at": "2020-05-22 22:59:55", - "created_at": "2020-05-22 22:59:55", + "updated_at": "2020-05-22T22:59:55.000000Z", + "created_at": "2020-05-22T22:59:55.000000Z", "id": 74, "book": { "id": 1, "name": "BookStack User Guide", "slug": "bookstack-user-guide", "description": "This is a general guide on using BookStack on a day-to-day basis.", - "created_at": "2019-05-05 21:48:46", - "updated_at": "2019-12-11 20:57:31", + "created_at": "2019-05-05T21:48:46.000000Z", + "updated_at": "2019-12-11T20:57:31.000000Z", "created_by": 1, "updated_by": 1 }, @@ -25,15 +25,15 @@ "name": "Category", "value": "Top Content", "order": 0, - "created_at": "2020-05-22 22:59:55", - "updated_at": "2020-05-22 22:59:55" + "created_at": "2020-05-22T22:59:55.000000Z", + "updated_at": "2020-05-22T22:59:55.000000Z" }, { "name": "Rating", "value": "Highest", "order": 0, - "created_at": "2020-05-22 22:59:55", - "updated_at": "2020-05-22 22:59:55" + "created_at": "2020-05-22T22:59:55.000000Z", + "updated_at": "2020-05-22T22:59:55.000000Z" } ] } \ No newline at end of file diff --git a/dev/api/responses/chapters-list.json b/dev/api/responses/chapters-list.json index 72ed7534d..9790286b0 100644 --- a/dev/api/responses/chapters-list.json +++ b/dev/api/responses/chapters-list.json @@ -7,8 +7,8 @@ "slug": "content-creation", "description": "How to create documentation on whatever subject you need to write about.", "priority": 3, - "created_at": "2019-05-05 21:49:56", - "updated_at": "2019-09-28 11:24:23", + "created_at": "2019-05-05:", + "updated_at": "2019-09-28T11:24:23.000000Z", "created_by": 1, "updated_by": 1, "owned_by": 1 @@ -20,8 +20,8 @@ "slug": "managing-content", "description": "How to keep things organised and orderly in the system for easier navigation and better user experience.", "priority": 5, - "created_at": "2019-05-05 21:58:07", - "updated_at": "2019-10-17 15:05:34", + "created_at": "2019-05-05T21:58:07.000000Z", + "updated_at": "2019-10-17T15:05:34.000000Z", "created_by": 3, "updated_by": 3, "owned_by": 3 diff --git a/dev/api/responses/chapters-read.json b/dev/api/responses/chapters-read.json index 41fed80ef..a51b406c7 100644 --- a/dev/api/responses/chapters-read.json +++ b/dev/api/responses/chapters-read.json @@ -5,8 +5,8 @@ "name": "Content Creation", "description": "How to create documentation on whatever subject you need to write about.", "priority": 3, - "created_at": "2019-05-05 21:49:56", - "updated_at": "2019-09-28 11:24:23", + "created_at": "2019-05-05T21:49:56.000000Z", + "updated_at": "2019-09-28T11:24:23.000000Z", "created_by": { "id": 1, "name": "Admin" @@ -34,8 +34,8 @@ "name": "How to create page content", "slug": "how-to-create-page-content", "priority": 0, - "created_at": "2019-05-05 21:49:58", - "updated_at": "2019-08-26 14:32:59", + "created_at": "2019-05-05T21:49:58.000000Z", + "updated_at": "2019-08-26T14:32:59.000000Z", "created_by": 1, "updated_by": 1, "draft": false, @@ -49,8 +49,8 @@ "name": "Good book structure", "slug": "good-book-structure", "priority": 1, - "created_at": "2019-05-05 22:01:55", - "updated_at": "2019-06-06 12:03:04", + "created_at": "2019-05-05T22:01:55.000000Z", + "updated_at": "2019-06-06T12:03:04.000000Z", "created_by": 3, "updated_by": 3, "draft": false, diff --git a/dev/api/responses/chapters-update.json b/dev/api/responses/chapters-update.json index 11dedd0ca..9ce88dab2 100644 --- a/dev/api/responses/chapters-update.json +++ b/dev/api/responses/chapters-update.json @@ -5,8 +5,8 @@ "name": "My fantastic updated chapter", "description": "This is an updated chapter that I've altered via the API", "priority": 7, - "created_at": "2020-05-22 23:03:35", - "updated_at": "2020-05-22 23:07:20", + "created_at": "2020-05-22T23:03:35.000000Z", + "updated_at": "2020-05-22T23:07:20.000000Z", "created_by": 1, "updated_by": 1, "owned_by": 1, @@ -15,8 +15,8 @@ "name": "BookStack User Guide", "slug": "bookstack-user-guide", "description": "This is a general guide on using BookStack on a day-to-day basis.", - "created_at": "2019-05-05 21:48:46", - "updated_at": "2019-12-11 20:57:31", + "created_at": "2019-05-05T21:48:46.000000Z", + "updated_at": "2019-12-11T20:57:31.000000Z", "created_by": 1, "updated_by": 1 }, @@ -25,15 +25,15 @@ "name": "Category", "value": "Kinda Good Content", "order": 0, - "created_at": "2020-05-22 23:07:20", - "updated_at": "2020-05-22 23:07:20" + "created_at": "2020-05-22T23:07:20.000000Z", + "updated_at": "2020-05-22T23:07:20.000000Z" }, { "name": "Rating", "value": "Medium", "order": 0, - "created_at": "2020-05-22 23:07:20", - "updated_at": "2020-05-22 23:07:20" + "created_at": "2020-05-22T23:07:20.000000Z", + "updated_at": "2020-05-22T23:07:20.000000Z" } ] } \ No newline at end of file diff --git a/dev/api/responses/pages-create.json b/dev/api/responses/pages-create.json index 0b19fb473..eeaa5303a 100644 --- a/dev/api/responses/pages-create.json +++ b/dev/api/responses/pages-create.json @@ -6,8 +6,8 @@ "slug": "my-api-page", "html": "

my new API page

", "priority": 14, - "created_at": "2020-11-28 15:01:39", - "updated_at": "2020-11-28 15:01:39", + "created_at": "2020-11-28T15:01:39.000000Z", + "updated_at": "2020-11-28T15:01:39.000000Z", "created_by": { "id": 1, "name": "Admin" diff --git a/dev/api/responses/pages-list.json b/dev/api/responses/pages-list.json index 9c162c6b6..2ff4aeb3a 100644 --- a/dev/api/responses/pages-list.json +++ b/dev/api/responses/pages-list.json @@ -9,8 +9,8 @@ "priority": 0, "draft": false, "template": false, - "created_at": "2019-05-05 21:49:58", - "updated_at": "2020-07-04 15:50:58", + "created_at": "2019-05-05T21:49:58.000000Z", + "updated_at": "2020-07-04T15:50:58.000000Z", "created_by": 1, "updated_by": 1, "owned_by": 1 @@ -24,8 +24,8 @@ "priority": 2, "draft": false, "template": false, - "created_at": "2019-05-05 21:53:30", - "updated_at": "2019-06-06 12:03:04", + "created_at": "2019-05-05T21:53:30.000000Z", + "updated_at": "2019-06-06T12:03:04.000000Z", "created_by": 1, "updated_by": 1, "owned_by": 1 @@ -39,8 +39,8 @@ "priority": 3, "draft": false, "template": false, - "created_at": "2019-05-05 21:53:49", - "updated_at": "2019-12-18 21:56:52", + "created_at": "2019-05-05T21:53:49.000000Z", + "updated_at": "2019-12-18T21:56:52.000000Z", "created_by": 1, "updated_by": 1, "owned_by": 1 diff --git a/dev/api/responses/pages-read.json b/dev/api/responses/pages-read.json index 93f7770ac..9a21cd44c 100644 --- a/dev/api/responses/pages-read.json +++ b/dev/api/responses/pages-read.json @@ -6,8 +6,8 @@ "slug": "a-page-written-in-markdown", "html": "

How this is built

\r\n

This page is written in markdown. BookStack stores the page data in HTML.

\r\n

Here's a cute picture of my cat:

\r\n

\"yXSrubes.jpg\"

", "priority": 13, - "created_at": "2020-02-02 21:40:38", - "updated_at": "2020-11-28 14:43:20", + "created_at": "2020-02-02T21:40:38.000000Z", + "updated_at": "2020-11-28T14:43:20.000000Z", "created_by": { "id": 1, "name": "Admin" diff --git a/dev/api/responses/pages-update.json b/dev/api/responses/pages-update.json index ae5c0ea3f..0b8b2374c 100644 --- a/dev/api/responses/pages-update.json +++ b/dev/api/responses/pages-update.json @@ -6,8 +6,8 @@ "slug": "my-updated-api-page", "html": "

my new API page - Updated

", "priority": 16, - "created_at": "2020-11-28 15:10:54", - "updated_at": "2020-11-28 15:13:03", + "created_at": "2020-11-28T15:10:54.000000Z", + "updated_at": "2020-11-28T15:13:03.000000Z", "created_by": { "id": 1, "name": "Admin" diff --git a/dev/api/responses/shelves-create.json b/dev/api/responses/shelves-create.json index fafa4c9cd..9988c782c 100644 --- a/dev/api/responses/shelves-create.json +++ b/dev/api/responses/shelves-create.json @@ -5,7 +5,7 @@ "updated_by": 1, "owned_by": 1, "slug": "my-shelf", - "updated_at": "2020-04-10 13:24:09", - "created_at": "2020-04-10 13:24:09", + "updated_at": "2020-04-10T13:24:09.000000Z", + "created_at": "2020-04-10T13:24:09.000000Z", "id": 14 } \ No newline at end of file diff --git a/dev/api/responses/shelves-list.json b/dev/api/responses/shelves-list.json index f5e9d03bb..82ead7d93 100644 --- a/dev/api/responses/shelves-list.json +++ b/dev/api/responses/shelves-list.json @@ -5,8 +5,8 @@ "name": "Qui qui aspernatur autem molestiae libero necessitatibus molestias.", "slug": "qui-qui-aspernatur-autem-molestiae-libero-necessitatibus-molestias", "description": "Enim dolor ut quia error dolores est. Aut distinctio consequuntur non nisi nostrum. Labore cupiditate error labore aliquid provident impedit voluptatibus. Quaerat impedit excepturi eius qui eius voluptatem reiciendis.", - "created_at": "2019-05-05 22:10:16", - "updated_at": "2020-04-10 13:00:45", + "created_at": "2019-05-05T22:10:16.000000Z", + "updated_at": "2020-04-10T13:00:45.000000Z", "created_by": 4, "updated_by": 1, "owned_by": 1, @@ -17,8 +17,8 @@ "name": "Ipsum aut inventore fuga libero non facilis.", "slug": "ipsum-aut-inventore-fuga-libero-non-facilis", "description": "Labore culpa modi perspiciatis harum sit. Maxime non et nam est. Quae ut laboriosam repellendus sunt quisquam. Velit at est perspiciatis nesciunt adipisci nobis illo. Sed possimus odit optio officiis nisi voluptates officiis dolor.", - "created_at": "2019-05-05 22:10:16", - "updated_at": "2020-04-10 13:00:58", + "created_at": "2019-05-05T22:10:16.000000Z", + "updated_at": "2020-04-10T13:00:58.000000Z", "created_by": 4, "updated_by": 1, "owned_by": 1, @@ -29,8 +29,8 @@ "name": "Omnis reiciendis aut molestias sint accusantium.", "slug": "omnis-reiciendis-aut-molestias-sint-accusantium", "description": "Qui ea occaecati alias est dolores voluptatem doloribus. Ad reiciendis corporis vero nostrum omnis et. Non doloribus ut eaque ut quos dolores.", - "created_at": "2019-05-05 22:10:16", - "updated_at": "2020-04-10 13:00:53", + "created_at": "2019-05-05T22:10:16.000000Z", + "updated_at": "2020-04-10T13:00:53.000000Z", "created_by": 4, "updated_by": 1, "owned_by": 4, diff --git a/dev/api/responses/shelves-read.json b/dev/api/responses/shelves-read.json index d663e82c5..f2afcdac0 100644 --- a/dev/api/responses/shelves-read.json +++ b/dev/api/responses/shelves-read.json @@ -15,8 +15,8 @@ "id": 1, "name": "Admin" }, - "created_at": "2020-04-10 13:24:09", - "updated_at": "2020-04-10 13:31:04", + "created_at": "2020-04-10T13:24:09.000000Z", + "updated_at": "2020-04-10T13:31:04.000000Z", "tags": [ { "id": 16, @@ -29,8 +29,8 @@ "id": 501, "name": "anafrancisconi_Sp04AfFCPNM.jpg", "url": "http://bookstack.local/uploads/images/cover_book/2020-04/anafrancisconi_Sp04AfFCPNM.jpg", - "created_at": "2020-04-10 13:31:04", - "updated_at": "2020-04-10 13:31:04", + "created_at": "2020-04-10T13:31:04.000000Z", + "updated_at": "2020-04-10T13:31:04.000000Z", "created_by": 1, "updated_by": 1, "path": "/uploads/images/cover_book/2020-04/anafrancisconi_Sp04AfFCPNM.jpg", diff --git a/dev/api/responses/shelves-update.json b/dev/api/responses/shelves-update.json index 4bde44b54..551dacb1f 100644 --- a/dev/api/responses/shelves-update.json +++ b/dev/api/responses/shelves-update.json @@ -7,6 +7,6 @@ "updated_by": 1, "owned_by": 1, "image_id": 501, - "created_at": "2020-04-10 13:24:09", - "updated_at": "2020-04-10 13:48:22" + "created_at": "2020-04-10T13:24:09.000000Z", + "updated_at": "2020-04-10T13:48:22.000000Z" } \ No newline at end of file From 9c680efaad1e116be926968f6f329e97d00b4c47 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Thu, 4 Nov 2021 22:29:36 +0000 Subject: [PATCH 06/59] Updated php packages, Added php8.1 to GH actions --- .github/workflows/phpunit.yml | 4 +- .github/workflows/test-migrations.yml | 4 +- composer.json | 12 ++--- composer.lock | 73 ++++++++++++++------------- 4 files changed, 47 insertions(+), 46 deletions(-) diff --git a/.github/workflows/phpunit.yml b/.github/workflows/phpunit.yml index f12de6436..7cb1307a1 100644 --- a/.github/workflows/phpunit.yml +++ b/.github/workflows/phpunit.yml @@ -13,12 +13,12 @@ jobs: runs-on: ubuntu-20.04 strategy: matrix: - php: ['7.3', '7.4', '8.0'] + php: ['7.3', '7.4', '8.0', '8.1'] steps: - uses: actions/checkout@v1 - name: Setup PHP - uses: shivammathur/setup-php@b7d1d9c9a92d8d8463ce36d7f60da34d461724f8 + uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} extensions: gd, mbstring, json, curl, xml, mysql, ldap diff --git a/.github/workflows/test-migrations.yml b/.github/workflows/test-migrations.yml index c24a01984..846992e7b 100644 --- a/.github/workflows/test-migrations.yml +++ b/.github/workflows/test-migrations.yml @@ -13,12 +13,12 @@ jobs: runs-on: ubuntu-20.04 strategy: matrix: - php: ['7.3', '7.4', '8.0'] + php: ['7.3', '7.4', '8.0', '8.1'] steps: - uses: actions/checkout@v1 - name: Setup PHP - uses: shivammathur/setup-php@b7d1d9c9a92d8d8463ce36d7f60da34d461724f8 + uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} extensions: gd, mbstring, json, curl, xml, mysql, ldap diff --git a/composer.json b/composer.json index c4d9cd904..23ce97cd4 100644 --- a/composer.json +++ b/composer.json @@ -25,9 +25,9 @@ "intervention/image": "^2.7", "laravel/framework": "^8.68", "laravel/socialite": "^5.2", - "laravel/tinker": "^2.5", + "laravel/tinker": "^2.6", "laravel/ui": "^3.3", - "league/commonmark": "^1.5", + "league/commonmark": "^1.6", "league/flysystem-aws-s3-v3": "^1.0.29", "league/html-to-markdown": "^5.0.0", "league/oauth2-client": "^2.6", @@ -44,12 +44,12 @@ "ssddanbrown/htmldiff": "^1.0.1" }, "require-dev": { - "fakerphp/faker": "^1.13.0", + "fakerphp/faker": "^1.16", "itsgoingd/clockwork": "^5.1", - "mockery/mockery": "^1.4.2", - "phpunit/phpunit": "^9.5.3", + "mockery/mockery": "^1.4", + "phpunit/phpunit": "^9.5", "symfony/dom-crawler": "^5.3", - "nunomaduro/collision": "^5.0" + "nunomaduro/collision": "^5.10" }, "autoload": { "psr-4": { diff --git a/composer.lock b/composer.lock index 7231c82c4..005f30fa3 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "0dfe612653577a14906a0bb031c67a97", + "content-hash": "48be80b0326176faa9775dca18a00fa2", "packages": [ { "name": "aws/aws-crt-php", @@ -58,16 +58,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.199.7", + "version": "3.200.0", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "fda176884d2952cffc7e67209470bff49609339c" + "reference": "9b3f45c51fe1d07845446675109bb0a8a98c806e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/fda176884d2952cffc7e67209470bff49609339c", - "reference": "fda176884d2952cffc7e67209470bff49609339c", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/9b3f45c51fe1d07845446675109bb0a8a98c806e", + "reference": "9b3f45c51fe1d07845446675109bb0a8a98c806e", "shasum": "" }, "require": { @@ -143,9 +143,9 @@ "support": { "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.199.7" + "source": "https://github.com/aws/aws-sdk-php/tree/3.200.0" }, - "time": "2021-10-29T18:25:02+00:00" + "time": "2021-11-04T18:42:25+00:00" }, { "name": "bacon/bacon-qr-code", @@ -1843,16 +1843,16 @@ }, { "name": "laravel/framework", - "version": "v8.68.1", + "version": "v8.69.0", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "abe985ff1fb82dd04aab03bc1dc56e83fe61a59f" + "reference": "545181da688db64fed6d8427e55f630a90ca0d32" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/abe985ff1fb82dd04aab03bc1dc56e83fe61a59f", - "reference": "abe985ff1fb82dd04aab03bc1dc56e83fe61a59f", + "url": "https://api.github.com/repos/laravel/framework/zipball/545181da688db64fed6d8427e55f630a90ca0d32", + "reference": "545181da688db64fed6d8427e55f630a90ca0d32", "shasum": "" }, "require": { @@ -2011,7 +2011,7 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2021-10-27T12:31:46+00:00" + "time": "2021-11-02T13:53:22+00:00" }, { "name": "laravel/serializable-closure", @@ -2211,16 +2211,16 @@ }, { "name": "laravel/ui", - "version": "v3.3.0", + "version": "v3.3.1", "source": { "type": "git", "url": "https://github.com/laravel/ui.git", - "reference": "07d725813350c695c779382cbd6dac0ab8665537" + "reference": "a449e3364d9780a80a49894a3af9795c85af806f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/ui/zipball/07d725813350c695c779382cbd6dac0ab8665537", - "reference": "07d725813350c695c779382cbd6dac0ab8665537", + "url": "https://api.github.com/repos/laravel/ui/zipball/a449e3364d9780a80a49894a3af9795c85af806f", + "reference": "a449e3364d9780a80a49894a3af9795c85af806f", "shasum": "" }, "require": { @@ -2263,9 +2263,9 @@ "ui" ], "support": { - "source": "https://github.com/laravel/ui/tree/v3.3.0" + "source": "https://github.com/laravel/ui/tree/v3.3.1" }, - "time": "2021-05-25T16:45:33+00:00" + "time": "2021-11-02T17:04:20+00:00" }, { "name": "league/commonmark", @@ -2966,16 +2966,16 @@ }, { "name": "nesbot/carbon", - "version": "2.53.1", + "version": "2.54.0", "source": { "type": "git", "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "f4655858a784988f880c1b8c7feabbf02dfdf045" + "reference": "eed83939f1aed3eee517d03a33f5ec587ac529b5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/f4655858a784988f880c1b8c7feabbf02dfdf045", - "reference": "f4655858a784988f880c1b8c7feabbf02dfdf045", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/eed83939f1aed3eee517d03a33f5ec587ac529b5", + "reference": "eed83939f1aed3eee517d03a33f5ec587ac529b5", "shasum": "" }, "require": { @@ -2986,6 +2986,7 @@ "symfony/translation": "^3.4 || ^4.0 || ^5.0" }, "require-dev": { + "doctrine/dbal": "^2.0 || ^3.0", "doctrine/orm": "^2.7", "friendsofphp/php-cs-fixer": "^3.0", "kylekatarnls/multi-tester": "^2.0", @@ -3056,20 +3057,20 @@ "type": "tidelift" } ], - "time": "2021-09-06T09:29:23+00:00" + "time": "2021-11-01T21:22:20+00:00" }, { "name": "nikic/php-parser", - "version": "v4.13.0", + "version": "v4.13.1", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "50953a2691a922aa1769461637869a0a2faa3f53" + "reference": "63a79e8daa781cac14e5195e63ed8ae231dd10fd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/50953a2691a922aa1769461637869a0a2faa3f53", - "reference": "50953a2691a922aa1769461637869a0a2faa3f53", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/63a79e8daa781cac14e5195e63ed8ae231dd10fd", + "reference": "63a79e8daa781cac14e5195e63ed8ae231dd10fd", "shasum": "" }, "require": { @@ -3110,9 +3111,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.13.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.13.1" }, - "time": "2021-09-20T12:20:58+00:00" + "time": "2021-11-03T20:52:16+00:00" }, { "name": "onelogin/php-saml", @@ -7681,22 +7682,22 @@ }, { "name": "itsgoingd/clockwork", - "version": "v5.1.0", + "version": "v5.1.1", "source": { "type": "git", "url": "https://github.com/itsgoingd/clockwork.git", - "reference": "b963dee47429a49c9669981cfa9a8362ce209278" + "reference": "2daf30fa6dfc5a1ccfdb2142df59243a72c473d8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/itsgoingd/clockwork/zipball/b963dee47429a49c9669981cfa9a8362ce209278", - "reference": "b963dee47429a49c9669981cfa9a8362ce209278", + "url": "https://api.github.com/repos/itsgoingd/clockwork/zipball/2daf30fa6dfc5a1ccfdb2142df59243a72c473d8", + "reference": "2daf30fa6dfc5a1ccfdb2142df59243a72c473d8", "shasum": "" }, "require": { "ext-json": "*", "php": ">=5.6", - "psr/log": "1.*" + "psr/log": "1.* || ^2.0" }, "type": "library", "extra": { @@ -7738,7 +7739,7 @@ ], "support": { "issues": "https://github.com/itsgoingd/clockwork/issues", - "source": "https://github.com/itsgoingd/clockwork/tree/v5.1.0" + "source": "https://github.com/itsgoingd/clockwork/tree/v5.1.1" }, "funding": [ { @@ -7746,7 +7747,7 @@ "type": "github" } ], - "time": "2021-08-07T23:04:17+00:00" + "time": "2021-11-01T17:38:35+00:00" }, { "name": "mockery/mockery", From 6f75aa9cdcf419ad9046b7d93596204d80fe75b3 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Thu, 4 Nov 2021 22:38:55 +0000 Subject: [PATCH 07/59] Reverted shift change to old migration --- .../2018_08_04_115700_create_bookshelves_table.php | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/database/migrations/2018_08_04_115700_create_bookshelves_table.php b/database/migrations/2018_08_04_115700_create_bookshelves_table.php index 8dc2a72e9..bb1aec95b 100644 --- a/database/migrations/2018_08_04_115700_create_bookshelves_table.php +++ b/database/migrations/2018_08_04_115700_create_bookshelves_table.php @@ -2,6 +2,7 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Schema; class CreateBookshelvesTable extends Migration @@ -120,11 +121,11 @@ class CreateBookshelvesTable extends Migration Schema::dropIfExists('bookshelves'); // Drop related polymorphic items - DB::table('activities')->where('entity_type', '=', \BookStack\Entities\Models\Bookshelf::class)->delete(); - DB::table('views')->where('viewable_type', '=', \BookStack\Entities\Models\Bookshelf::class)->delete(); - DB::table('entity_permissions')->where('restrictable_type', '=', \BookStack\Entities\Models\Bookshelf::class)->delete(); - DB::table('tags')->where('entity_type', '=', \BookStack\Entities\Models\Bookshelf::class)->delete(); - DB::table('search_terms')->where('entity_type', '=', \BookStack\Entities\Models\Bookshelf::class)->delete(); - DB::table('comments')->where('entity_type', '=', \BookStack\Entities\Models\Bookshelf::class)->delete(); + DB::table('activities')->where('entity_type', '=', 'BookStack\Entities\Models\Bookshelf')->delete(); + DB::table('views')->where('viewable_type', '=', 'BookStack\Entities\Models\Bookshelf')->delete(); + DB::table('entity_permissions')->where('restrictable_type', '=', 'BookStack\Entities\Models\Bookshelf')->delete(); + DB::table('tags')->where('entity_type', '=', 'BookStack\Entities\Models\Bookshelf')->delete(); + DB::table('search_terms')->where('entity_type', '=', 'BookStack\Entities\Models\Bookshelf')->delete(); + DB::table('comments')->where('entity_type', '=', 'BookStack\Entities\Models\Bookshelf')->delete(); } } From 1eed8d6325bf98579689773bf8e9448bec674977 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Thu, 4 Nov 2021 22:52:35 +0000 Subject: [PATCH 08/59] Removed style in discord logo to prevent clash with twitter logo Both were using the same class names causing a quadrant of the slack logo to be the discord brand color. Related to #3032 --- resources/icons/auth/discord.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/icons/auth/discord.svg b/resources/icons/auth/discord.svg index 65c9fccff..7fbbeb792 100644 --- a/resources/icons/auth/discord.svg +++ b/resources/icons/auth/discord.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file From 9542509584c16b179b8675f3b31939c134b1448c Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Thu, 4 Nov 2021 22:57:04 +0000 Subject: [PATCH 09/59] New Crowdin updates (#3038) Just crowdin aligning string quote styles --- resources/lang/ar/passwords.php | 2 +- resources/lang/ar/settings.php | 2 +- resources/lang/bg/passwords.php | 2 +- resources/lang/bg/settings.php | 2 +- resources/lang/bs/passwords.php | 2 +- resources/lang/ca/settings.php | 4 ++-- resources/lang/cs/entities.php | 2 +- resources/lang/cs/passwords.php | 2 +- resources/lang/cs/settings.php | 2 +- resources/lang/da/passwords.php | 2 +- resources/lang/da/settings.php | 2 +- resources/lang/de/passwords.php | 2 +- resources/lang/de/settings.php | 2 +- resources/lang/de_informal/passwords.php | 2 +- resources/lang/de_informal/settings.php | 2 +- resources/lang/es/passwords.php | 2 +- resources/lang/es/settings.php | 2 +- resources/lang/es_AR/passwords.php | 2 +- resources/lang/es_AR/settings.php | 2 +- resources/lang/et/passwords.php | 2 +- resources/lang/et/settings.php | 2 +- resources/lang/fa/passwords.php | 2 +- resources/lang/fr/entities.php | 2 +- resources/lang/fr/settings.php | 4 ++-- resources/lang/he/entities.php | 2 +- resources/lang/he/passwords.php | 2 +- resources/lang/he/settings.php | 2 +- resources/lang/hu/passwords.php | 2 +- resources/lang/hu/settings.php | 2 +- resources/lang/id/passwords.php | 2 +- resources/lang/id/settings.php | 2 +- resources/lang/it/passwords.php | 2 +- resources/lang/it/settings.php | 2 +- resources/lang/ja/entities.php | 2 +- resources/lang/ja/passwords.php | 2 +- resources/lang/ja/settings.php | 2 +- resources/lang/ko/entities.php | 4 ++-- resources/lang/ko/errors.php | 2 +- resources/lang/ko/passwords.php | 2 +- resources/lang/ko/settings.php | 2 +- resources/lang/lv/entities.php | 2 +- resources/lang/lv/passwords.php | 2 +- resources/lang/lv/settings.php | 2 +- resources/lang/nb/passwords.php | 2 +- resources/lang/nb/settings.php | 2 +- resources/lang/nl/passwords.php | 2 +- resources/lang/nl/settings.php | 2 +- resources/lang/pl/passwords.php | 2 +- resources/lang/pl/settings.php | 2 +- resources/lang/pt/passwords.php | 2 +- resources/lang/pt/settings.php | 2 +- resources/lang/pt_BR/passwords.php | 2 +- resources/lang/pt_BR/settings.php | 2 +- resources/lang/ru/entities.php | 2 +- resources/lang/ru/errors.php | 2 +- resources/lang/ru/passwords.php | 2 +- resources/lang/ru/settings.php | 2 +- resources/lang/sk/passwords.php | 2 +- resources/lang/sk/settings.php | 2 +- resources/lang/sl/passwords.php | 2 +- resources/lang/sl/settings.php | 2 +- resources/lang/sv/passwords.php | 2 +- resources/lang/sv/settings.php | 2 +- resources/lang/tr/entities.php | 2 +- resources/lang/tr/passwords.php | 2 +- resources/lang/tr/settings.php | 2 +- resources/lang/uk/passwords.php | 2 +- resources/lang/uk/settings.php | 2 +- resources/lang/vi/passwords.php | 2 +- resources/lang/vi/settings.php | 2 +- resources/lang/zh_CN/passwords.php | 2 +- resources/lang/zh_CN/settings.php | 2 +- resources/lang/zh_TW/entities.php | 2 +- resources/lang/zh_TW/passwords.php | 2 +- resources/lang/zh_TW/settings.php | 2 +- 75 files changed, 78 insertions(+), 78 deletions(-) diff --git a/resources/lang/ar/passwords.php b/resources/lang/ar/passwords.php index 33b8e9c3e..4ab447d5d 100644 --- a/resources/lang/ar/passwords.php +++ b/resources/lang/ar/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'يجب أن تتكون كلمة المرور من ستة أحرف على الأقل وأن تطابق التأكيد.', - 'user' => 'لم يتم العثور على مستخدم بعنوان البريد الإلكتروني المعطى.', + 'user' => "لم يتم العثور على مستخدم بعنوان البريد الإلكتروني المعطى.", 'token' => 'رمز إعادة تعيين كلمة المرور غير صالح لعنوان هذا البريد الإلكتروني.', 'sent' => 'تم إرسال رابط تجديد كلمة المرور إلى بريدكم الإلكتروني!', 'reset' => 'تم تجديد كلمة المرور الخاصة بكم!', diff --git a/resources/lang/ar/settings.php b/resources/lang/ar/settings.php index 7456fbc99..be69aa46e 100755 --- a/resources/lang/ar/settings.php +++ b/resources/lang/ar/settings.php @@ -132,7 +132,7 @@ return [ 'role_delete' => 'حذف الدور', 'role_delete_confirm' => 'سيتم حذف الدور المسمى \':roleName\'.', 'role_delete_users_assigned' => 'هذا الدور له: عدد المستخدمين المعينين له. إذا كنت ترغب في ترحيل المستخدمين من هذا الدور ، فحدد دورًا جديدًا أدناه.', - 'role_delete_no_migration' => 'لا تقم بترجيل المستخدمين', + 'role_delete_no_migration' => "لا تقم بترجيل المستخدمين", 'role_delete_sure' => 'تأكيد حذف الدور؟', 'role_delete_success' => 'تم حذف الدور بنجاح', 'role_edit' => 'تعديل الدور', diff --git a/resources/lang/bg/passwords.php b/resources/lang/bg/passwords.php index 5fb192a44..871fdeea8 100644 --- a/resources/lang/bg/passwords.php +++ b/resources/lang/bg/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'Паролите трябва да имат поне 8 символа и да съвпадат с потвърждението.', - 'user' => 'Не можем да намерим потребител с този имейл адрес.', + 'user' => "Не можем да намерим потребител с този имейл адрес.", 'token' => 'Кодът за зануляване на паролата е невалиден за този емейл адрес.', 'sent' => 'Пратихме връзка за нулиране на паролата до имейла ви!', 'reset' => 'Вашата парола е нулирана!', diff --git a/resources/lang/bg/settings.php b/resources/lang/bg/settings.php index 76b925f58..c10fb7556 100644 --- a/resources/lang/bg/settings.php +++ b/resources/lang/bg/settings.php @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Изтрий роля', 'role_delete_confirm' => 'Това ще изтрие ролята \':roleName\'.', 'role_delete_users_assigned' => 'В тази роля се намират :userCount потребители. Ако искате да преместите тези потребители в друга роля, моля изберете нова роля отдолу.', - 'role_delete_no_migration' => 'Не премествай потребителите в нова роля', + 'role_delete_no_migration' => "Не премествай потребителите в нова роля", 'role_delete_sure' => 'Сигурни ли сте, че искате да изтриете тази роля?', 'role_delete_success' => 'Ролята беше успешно изтрита', 'role_edit' => 'Редактиране на роля', diff --git a/resources/lang/bs/passwords.php b/resources/lang/bs/passwords.php index 54880f4b5..0383e8af0 100644 --- a/resources/lang/bs/passwords.php +++ b/resources/lang/bs/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'Lozinke moraju sadržavati najmanje osam karaktera i podudarati se sa potvrdom lozinke.', - 'user' => 'Ne možemo naći korisnika sa tom e-mail adresom.', + 'user' => "Ne možemo naći korisnika sa tom e-mail adresom.", 'token' => 'Token za poništavanje lozinke nije validan za ovu e-mail adresu.', 'sent' => 'Poslali smo link za poništavanje vaše lozinke na e-mail!', 'reset' => 'Vaša lozinka je resetovana!', diff --git a/resources/lang/ca/settings.php b/resources/lang/ca/settings.php index 30d937b60..b5b48053a 100755 --- a/resources/lang/ca/settings.php +++ b/resources/lang/ca/settings.php @@ -72,7 +72,7 @@ return [ // Maintenance settings 'maint' => 'Manteniment', 'maint_image_cleanup' => 'Neteja les imatges', - 'maint_image_cleanup_desc' => "Escaneja el contingut de les pàgines i les revisions per a comprovar quines imatges i diagrames estan en ús actualment i quines imatges són redundants. Assegureu-vos de crear una còpia de seguretat completa de la base de dades i de les imatges abans d'executar això.", + 'maint_image_cleanup_desc' => 'Escaneja el contingut de les pàgines i les revisions per a comprovar quines imatges i diagrames estan en ús actualment i quines imatges són redundants. Assegureu-vos de crear una còpia de seguretat completa de la base de dades i de les imatges abans d\'executar això.', 'maint_delete_images_only_in_revisions' => 'Suprimeix també les imatges que només existeixin en revisions antigues de pàgines', 'maint_image_cleanup_run' => 'Executa la neteja', 'maint_image_cleanup_warning' => 'S\'han trobat :count imatges potencialment no utilitzades. Segur que voleu suprimir aquestes imatges?', @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Suprimeix el rol', 'role_delete_confirm' => 'Se suprimirà el rol amb el nom \':roleName\'.', 'role_delete_users_assigned' => 'Aquest rol té :userCount usuaris assignats. Si voleu migrar els usuaris d\'aquest rol, seleccioneu un rol nou a continuació.', - 'role_delete_no_migration' => 'No migris els usuaris', + 'role_delete_no_migration' => "No migris els usuaris", 'role_delete_sure' => 'Segur que voleu suprimir aquest rol?', 'role_delete_success' => 'Rol suprimit correctament', 'role_edit' => 'Edita el rol', diff --git a/resources/lang/cs/entities.php b/resources/lang/cs/entities.php index 548c01a84..5d79c441f 100644 --- a/resources/lang/cs/entities.php +++ b/resources/lang/cs/entities.php @@ -94,7 +94,7 @@ return [ 'shelves_edit' => 'Upravit knihovnu', 'shelves_delete' => 'Odstranit knihovnu', 'shelves_delete_named' => 'Odstranit knihovnu :name', - 'shelves_delete_explain' => 'Toto odstraní knihovnu ‚:name‘. Vložené knihy nebudou odstraněny.', + 'shelves_delete_explain' => "Toto odstraní knihovnu ‚:name‘. Vložené knihy nebudou odstraněny.", 'shelves_delete_confirmation' => 'Opravdu chcete odstranit tuto knihovnu?', 'shelves_permissions' => 'Oprávnění knihovny', 'shelves_permissions_updated' => 'Oprávnění knihovny byla aktualizována', diff --git a/resources/lang/cs/passwords.php b/resources/lang/cs/passwords.php index b25e24f3c..40b12b607 100644 --- a/resources/lang/cs/passwords.php +++ b/resources/lang/cs/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'Heslo musí mít alespoň osm znaků a musí odpovídat potvrzení hesla.', - 'user' => 'Nemůžeme nalézt uživatele s touto e-mailovou adresou.', + 'user' => "Nemůžeme nalézt uživatele s touto e-mailovou adresou.", 'token' => 'Token pro obnovení hesla není platný pro tuto e-mailovou adresu.', 'sent' => 'Poslali jsme Vám e-mail s odkazem pro obnovení hesla!', 'reset' => 'Vaše heslo bylo obnoveno!', diff --git a/resources/lang/cs/settings.php b/resources/lang/cs/settings.php index 149a04753..3f5d2e174 100644 --- a/resources/lang/cs/settings.php +++ b/resources/lang/cs/settings.php @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Odstranit roli', 'role_delete_confirm' => 'Role \':roleName\' bude odstraněna.', 'role_delete_users_assigned' => 'Role je přiřazena :userCount uživatelům. Pokud jim chcete náhradou přidělit jinou roli, zvolte jednu z následujících.', - 'role_delete_no_migration' => 'Nepřiřazovat uživatelům náhradní roli', + 'role_delete_no_migration' => "Nepřiřazovat uživatelům náhradní roli", 'role_delete_sure' => 'Opravdu chcete tuto roli odstranit?', 'role_delete_success' => 'Role byla odstraněna', 'role_edit' => 'Upravit roli', diff --git a/resources/lang/da/passwords.php b/resources/lang/da/passwords.php index 39ed9418f..343fa2b85 100644 --- a/resources/lang/da/passwords.php +++ b/resources/lang/da/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'Adgangskoder skal være mindst otte tegn og svare til bekræftelsen.', - 'user' => 'Vi kan ikke finde en bruger med den e-mail adresse.', + 'user' => "Vi kan ikke finde en bruger med den e-mail adresse.", 'token' => 'Linket til nulstilling af adgangskode er ugyldigt for denne e-mail-adresse.', 'sent' => 'Vi har sendt dig en e-mail med et link til at nulstille adgangskoden!', 'reset' => 'Dit kodeord er blevet nulstillet!', diff --git a/resources/lang/da/settings.php b/resources/lang/da/settings.php index d963a7ad4..d33080dbd 100644 --- a/resources/lang/da/settings.php +++ b/resources/lang/da/settings.php @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Slet rolle', 'role_delete_confirm' => 'Dette vil slette rollen med navnet \':roleName\'.', 'role_delete_users_assigned' => 'Denne rolle er tildelt :userCount brugere. Hvis du vil rykke disse brugere fra denne rolle, kan du vælge en ny nedenunder.', - 'role_delete_no_migration' => 'Ryk ikke brugere', + 'role_delete_no_migration' => "Ryk ikke brugere", 'role_delete_sure' => 'Er du sikker på, at du vil slette denne rolle?', 'role_delete_success' => 'Rollen blev slettet', 'role_edit' => 'Rediger rolle', diff --git a/resources/lang/de/passwords.php b/resources/lang/de/passwords.php index 5f3762e16..3da092cb8 100644 --- a/resources/lang/de/passwords.php +++ b/resources/lang/de/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'Passwörter müssen aus mindestens sechs Zeichen bestehen und mit der eingegebenen Wiederholung übereinstimmen.', - 'user' => 'Es wurde kein Benutzer mit dieser E-Mail-Adresse gefunden.', + 'user' => "Es wurde kein Benutzer mit dieser E-Mail-Adresse gefunden.", 'token' => 'Der Link zum Zurücksetzen Ihres Passworts ist entweder ungültig oder abgelaufen.', 'sent' => 'Der Link zum Zurücksetzen Ihres Passwortes wurde Ihnen per E-Mail zugesendet.', 'reset' => 'Ihr Passwort wurde zurückgesetzt!', diff --git a/resources/lang/de/settings.php b/resources/lang/de/settings.php index 1dd84a9a8..6f5492f71 100644 --- a/resources/lang/de/settings.php +++ b/resources/lang/de/settings.php @@ -135,7 +135,7 @@ Hinweis: Benutzer können ihre E-Mail Adresse nach erfolgreicher Registrierung 'role_delete' => 'Rolle löschen', 'role_delete_confirm' => 'Sie möchten die Rolle ":roleName" löschen.', 'role_delete_users_assigned' => 'Diese Rolle ist :userCount Benutzern zugeordnet. Sie können unten eine neue Rolle auswählen, die Sie diesen Benutzern zuordnen möchten.', - 'role_delete_no_migration' => 'Den Benutzern keine andere Rolle zuordnen', + 'role_delete_no_migration' => "Den Benutzern keine andere Rolle zuordnen", 'role_delete_sure' => 'Sind Sie sicher, dass Sie diese Rolle löschen möchten?', 'role_delete_success' => 'Rolle erfolgreich gelöscht', 'role_edit' => 'Rolle bearbeiten', diff --git a/resources/lang/de_informal/passwords.php b/resources/lang/de_informal/passwords.php index b5b38d7fd..0dd28c019 100644 --- a/resources/lang/de_informal/passwords.php +++ b/resources/lang/de_informal/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'Passwörter müssen aus mindestens sechs Zeichen bestehen und mit der eingegebenen Wiederholung übereinstimmen.', - 'user' => 'Es wurde kein Benutzer mit dieser E-Mail-Adresse gefunden.', + 'user' => "Es wurde kein Benutzer mit dieser E-Mail-Adresse gefunden.", 'token' => 'Der Token zum Zurücksetzen des Passworts für diese E-Mail-Adresse ist ungültig.', 'sent' => 'Wir haben dir einen Link zum Zurücksetzen des Passwortes per E-Mail geschickt!', 'reset' => 'Dein Passwort wurde zurückgesetzt!', diff --git a/resources/lang/de_informal/settings.php b/resources/lang/de_informal/settings.php index a5cd94ab0..de102e24a 100644 --- a/resources/lang/de_informal/settings.php +++ b/resources/lang/de_informal/settings.php @@ -135,7 +135,7 @@ Hinweis: Benutzer können ihre E-Mail Adresse nach erfolgreicher Registrierung 'role_delete' => 'Rolle löschen', 'role_delete_confirm' => 'Du möchtest die Rolle ":roleName" löschen.', 'role_delete_users_assigned' => 'Diese Rolle ist :userCount Benutzern zugeordnet. Du kannst unten eine neue Rolle auswählen, die Du diesen Benutzern zuordnen möchtest.', - 'role_delete_no_migration' => 'Den Benutzern keine andere Rolle zuordnen', + 'role_delete_no_migration' => "Den Benutzern keine andere Rolle zuordnen", 'role_delete_sure' => 'Bist Du sicher, dass Du diese Rolle löschen möchtest?', 'role_delete_success' => 'Rolle erfolgreich gelöscht', 'role_edit' => 'Rolle bearbeiten', diff --git a/resources/lang/es/passwords.php b/resources/lang/es/passwords.php index 4a46134c4..15e42d1ec 100644 --- a/resources/lang/es/passwords.php +++ b/resources/lang/es/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'La contraseña debe ser como mínimo de seis caracteres y coincidir con la confirmación.', - 'user' => 'No podemos encontrar un usuario con esta dirección de correo electrónico.', + 'user' => "No podemos encontrar un usuario con esta dirección de correo electrónico.", 'token' => 'El token de modificación de contraseña no es válido para esta dirección de correo electrónico.', 'sent' => '¡Hemos enviado a su cuenta de e-mail un enlace para restaurar su contraseña!', 'reset' => '¡Su contraseña ha sido restaurada!', diff --git a/resources/lang/es/settings.php b/resources/lang/es/settings.php index 079202bfa..60103ce2b 100644 --- a/resources/lang/es/settings.php +++ b/resources/lang/es/settings.php @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Borrar rol', 'role_delete_confirm' => 'Se borrará el rol con nombre \':roleName\'.', 'role_delete_users_assigned' => 'Este rol tiene :userCount usuarios asignados. Si quisiera migrar los usuarios de este rol, seleccione un nuevo rol a continuación.', - 'role_delete_no_migration' => 'No migrar usuarios', + 'role_delete_no_migration' => "No migrar usuarios", 'role_delete_sure' => 'Está seguro que desea borrar este rol?', 'role_delete_success' => 'Rol borrado satisfactoriamente', 'role_edit' => 'Editar rol', diff --git a/resources/lang/es_AR/passwords.php b/resources/lang/es_AR/passwords.php index 92e92a2b7..f9e24939b 100644 --- a/resources/lang/es_AR/passwords.php +++ b/resources/lang/es_AR/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'La contraseña debe ser como mínimo de seis caracteres y coincidir con la confirmación.', - 'user' => 'No podemos encontrar un usuario con esta dirección de correo electrónico.', + 'user' => "No podemos encontrar un usuario con esta dirección de correo electrónico.", 'token' => 'El token para restablecer la contraseña no es válido para esta dirección de correo electrónico.', 'sent' => '¡Hemos enviado a su cuenta de correo electrónico un enlace para restaurar su contraseña!', 'reset' => '¡Su contraseña fue restaurada!', diff --git a/resources/lang/es_AR/settings.php b/resources/lang/es_AR/settings.php index ab8a873b3..77c7b4dd7 100644 --- a/resources/lang/es_AR/settings.php +++ b/resources/lang/es_AR/settings.php @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Borrar rol', 'role_delete_confirm' => 'Se borrará el rol con nombre \':roleName\'.', 'role_delete_users_assigned' => 'Este rol tiene :userCount usuarios asignados. Si ud. quisiera migrar los usuarios de este rol, seleccione un nuevo rol a continuación.', - 'role_delete_no_migration' => 'No migrar usuarios', + 'role_delete_no_migration' => "No migrar usuarios", 'role_delete_sure' => '¿Está seguro que desea borrar este rol?', 'role_delete_success' => 'Rol borrado satisfactoriamente', 'role_edit' => 'Editar rol', diff --git a/resources/lang/et/passwords.php b/resources/lang/et/passwords.php index 6457887d3..8559d60b2 100644 --- a/resources/lang/et/passwords.php +++ b/resources/lang/et/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'Paroolides peab olema vähemalt kaheksa tähemärki ja nad peavad omavahel ühtima.', - 'user' => 'Sellise e-posti aadressiga kasutajat ei leitud.', + 'user' => "Sellise e-posti aadressiga kasutajat ei leitud.", 'token' => 'Parooli lähtestamise link ei kehti selle e-posti aadressiga.', 'sent' => 'Parooli lähtestamise link saadeti e-postiga!', 'reset' => 'Parool on lähtestatud!', diff --git a/resources/lang/et/settings.php b/resources/lang/et/settings.php index 6203d9f0b..a5d7edc55 100644 --- a/resources/lang/et/settings.php +++ b/resources/lang/et/settings.php @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Kustuta roll', 'role_delete_confirm' => 'See kustutab rolli nimega \':roleName\'.', 'role_delete_users_assigned' => 'Selle rolliga on seotud :userCount kasutajat. Kui soovid neile selle asemel uue rolli määrata, siis vali see allpool.', - 'role_delete_no_migration' => 'Ära määra uut rolli', + 'role_delete_no_migration' => "Ära määra uut rolli", 'role_delete_sure' => 'Kas oled kindel, et soovid selle rolli kustutada?', 'role_delete_success' => 'Roll on kustutatud', 'role_edit' => 'Muuda rolli', diff --git a/resources/lang/fa/passwords.php b/resources/lang/fa/passwords.php index 6d342dbe8..06b8f8b50 100644 --- a/resources/lang/fa/passwords.php +++ b/resources/lang/fa/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'گذرواژه باید حداقل هشت حرف و با تایید مطابقت داشته باشد.', - 'user' => 'ما کاربری با این نشانی ایمیل نداریم.', + 'user' => "ما کاربری با این نشانی ایمیل نداریم.", 'token' => 'مشخصه‌ی بازگردانی رمز عبور معتبر نیست.', 'sent' => 'لینک بازگردانی رمز عبور به ایمیل شما ارسال شد!', 'reset' => 'رمز عبور شما بازگردانی شد!', diff --git a/resources/lang/fr/entities.php b/resources/lang/fr/entities.php index 3742f584e..242efa4e0 100644 --- a/resources/lang/fr/entities.php +++ b/resources/lang/fr/entities.php @@ -255,7 +255,7 @@ return [ 'tags' => 'Mots-clés', 'tag_name' => 'Nom du tag', 'tag_value' => 'Valeur du mot-clé (optionnel)', - 'tags_explain' => 'Ajouter des mots-clés pour catégoriser votre contenu.', + 'tags_explain' => "Ajouter des mots-clés pour catégoriser votre contenu.", 'tags_add' => 'Ajouter un autre mot-clé', 'tags_remove' => 'Supprimer le mot-clé', 'attachments' => 'Fichiers joints', diff --git a/resources/lang/fr/settings.php b/resources/lang/fr/settings.php index 5df79561f..1cefbb1d8 100644 --- a/resources/lang/fr/settings.php +++ b/resources/lang/fr/settings.php @@ -72,7 +72,7 @@ return [ // Maintenance settings 'maint' => 'Maintenance', 'maint_image_cleanup' => 'Nettoyer les images', - 'maint_image_cleanup_desc' => "Scanne le contenu des pages et des révisions pour vérifier les images, les dessins en cours d'utilisation et les doublons. Assurez-vous d'avoir une sauvegarde de la base de données et des images avant de lancer ceci.", + 'maint_image_cleanup_desc' => 'Scanne le contenu des pages et des révisions pour vérifier les images, les dessins en cours d\'utilisation et les doublons. Assurez-vous d\'avoir une sauvegarde de la base de données et des images avant de lancer ceci.', 'maint_delete_images_only_in_revisions' => 'Supprimer également les images qui n\'existent que dans les anciennes révisions de page', 'maint_image_cleanup_run' => 'Lancer le nettoyage', 'maint_image_cleanup_warning' => ':count images potentiellement inutilisées trouvées. Êtes-vous sûr de vouloir supprimer ces images ?', @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Supprimer le rôle', 'role_delete_confirm' => 'Ceci va supprimer le rôle \':roleName\'.', 'role_delete_users_assigned' => 'Ce rôle a :userCount utilisateurs assignés. Vous pouvez choisir un rôle de remplacement pour ces utilisateurs.', - 'role_delete_no_migration' => 'Ne pas assigner de nouveau rôle', + 'role_delete_no_migration' => "Ne pas assigner de nouveau rôle", 'role_delete_sure' => 'Êtes-vous sûr de vouloir supprimer ce rôle ?', 'role_delete_success' => 'Le rôle a été supprimé avec succès', 'role_edit' => 'Modifier le rôle', diff --git a/resources/lang/he/entities.php b/resources/lang/he/entities.php index 5ad67afb8..80d896666 100644 --- a/resources/lang/he/entities.php +++ b/resources/lang/he/entities.php @@ -94,7 +94,7 @@ return [ 'shelves_edit' => 'ערוך מדף', 'shelves_delete' => 'מחק מדף', 'shelves_delete_named' => 'מחיקת דף :name', - 'shelves_delete_explain' => 'פעולה זו תמחק את המדף :name - הספרים שמופיעים בו ימחקו גם כן!', + 'shelves_delete_explain' => "פעולה זו תמחק את המדף :name - הספרים שמופיעים בו ימחקו גם כן!", 'shelves_delete_confirmation' => 'האם ברצונך למחוק את המדף?', 'shelves_permissions' => 'הרשאות מדף', 'shelves_permissions_updated' => 'הרשאות מדף עודכנו', diff --git a/resources/lang/he/passwords.php b/resources/lang/he/passwords.php index 0b700f21e..a94d7c30b 100644 --- a/resources/lang/he/passwords.php +++ b/resources/lang/he/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'הסיסמה חייבת להיות בעלת 8 תווים לפחות ולהתאים לאימות.', - 'user' => 'לא נמצא משתמש עם כתובת דוא"ל זו.', + 'user' => "לא נמצא משתמש עם כתובת דוא\"ל זו.", 'token' => 'אסימון איפוס הסיסמה לא תקף עבור כתובת דוא"ל זו.', 'sent' => 'שלחנו לך דוא"ל עם קישור לאיפוס הסיסמה!', 'reset' => 'איפוס הסיסמה הושלם בהצלחה!', diff --git a/resources/lang/he/settings.php b/resources/lang/he/settings.php index 36e36c94d..23410d746 100755 --- a/resources/lang/he/settings.php +++ b/resources/lang/he/settings.php @@ -132,7 +132,7 @@ return [ 'role_delete' => 'מחק תפקיד', 'role_delete_confirm' => 'פעולה זו תמחק את התפקיד: :roleName', 'role_delete_users_assigned' => 'לתפקיד :userCount יש משתמשים אשר משויכים אליו. אם ברצונך להעבירם לתפקיד אחר אנא בחר תפקיד מלמטה', - 'role_delete_no_migration' => 'אל תעביר משתמשים לתפקיד', + 'role_delete_no_migration' => "אל תעביר משתמשים לתפקיד", 'role_delete_sure' => 'האם אתה בטוח שברצונך למחוק את התפקיד?', 'role_delete_success' => 'התפקיד נמחק בהצלחה', 'role_edit' => 'ערוך תפקיד', diff --git a/resources/lang/hu/passwords.php b/resources/lang/hu/passwords.php index f33be37d6..e06c6f6e3 100644 --- a/resources/lang/hu/passwords.php +++ b/resources/lang/hu/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'A jelszónak legalább hat karakterből kell állnia és egyeznie kell a megerősítéssel.', - 'user' => 'Nem található felhasználó ezzel az e-mail címmel.', + 'user' => "Nem található felhasználó ezzel az e-mail címmel.", 'token' => 'The password reset token is invalid for this email address.', 'sent' => 'E-mailben elküldtük a jelszó visszaállító hivatkozást!', 'reset' => 'A jelszó visszaállítva!', diff --git a/resources/lang/hu/settings.php b/resources/lang/hu/settings.php index b0ad98786..31a94d1bb 100644 --- a/resources/lang/hu/settings.php +++ b/resources/lang/hu/settings.php @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Szerepkör törlése', 'role_delete_confirm' => 'Ez törölni fogja \':roleName\' szerepkört.', 'role_delete_users_assigned' => 'Ehhez a szerepkörhöz :userCount felhasználó van hozzárendelve. Ha a felhasználókat át kell helyezni ebből a szerepkörből, akkor ki kell választani egy új szerepkört.', - 'role_delete_no_migration' => 'Nincs felhasználó áthelyezés', + 'role_delete_no_migration' => "Nincs felhasználó áthelyezés", 'role_delete_sure' => 'Biztosan törölhető ez a szerepkör?', 'role_delete_success' => 'Szerepkör sikeresen törölve', 'role_edit' => 'Szerepkör szerkesztése', diff --git a/resources/lang/id/passwords.php b/resources/lang/id/passwords.php index c4578b8d1..3ee2e4d57 100644 --- a/resources/lang/id/passwords.php +++ b/resources/lang/id/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'Kata sandi harus setidaknya delapan karakter dan sesuai dengan konfirmasi.', - 'user' => 'Kami tidak dapat menemukan pengguna dengan alamat email tersebut.', + 'user' => "Kami tidak dapat menemukan pengguna dengan alamat email tersebut.", 'token' => 'Token setel ulang sandi tidak valid untuk alamat email ini.', 'sent' => 'Kami telah mengirimkan email tautan pengaturan ulang kata sandi Anda!', 'reset' => 'Kata sandi Anda telah disetel ulang!', diff --git a/resources/lang/id/settings.php b/resources/lang/id/settings.php index 2ef4b6b08..4925633af 100644 --- a/resources/lang/id/settings.php +++ b/resources/lang/id/settings.php @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Hapus Peran', 'role_delete_confirm' => 'Ini akan menghapus peran dengan nama \':roleName\'.', 'role_delete_users_assigned' => 'Peran ini memiliki :userCount pengguna yang ditugaskan padanya. Jika Anda ingin memindahkan pengguna dari peran ini pilih peran baru di bawah.', - 'role_delete_no_migration' => 'Jangan migrasikan pengguna', + 'role_delete_no_migration' => "Jangan migrasikan pengguna", 'role_delete_sure' => 'Anda yakin ingin menghapus peran ini?', 'role_delete_success' => 'Peran berhasil dihapus', 'role_edit' => 'Edit Peran', diff --git a/resources/lang/it/passwords.php b/resources/lang/it/passwords.php index 03afdbe2d..7099d54f3 100755 --- a/resources/lang/it/passwords.php +++ b/resources/lang/it/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'La password deve avere almeno sei caratteri e corrispondere alla conferma.', - 'user' => 'Non possiamo trovare un utente per quella mail.', + 'user' => "Non possiamo trovare un utente per quella mail.", 'token' => 'Il token per reimpostare la password non è valido per questo indirizzo email.', 'sent' => 'Ti abbiamo inviato via mail il link per reimpostare la password!', 'reset' => 'La tua password è stata reimpostata!', diff --git a/resources/lang/it/settings.php b/resources/lang/it/settings.php index d7573de88..481913b17 100755 --- a/resources/lang/it/settings.php +++ b/resources/lang/it/settings.php @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Elimina Ruolo', 'role_delete_confirm' => 'Questo eliminerà il ruolo con il nome \':roleName\'.', 'role_delete_users_assigned' => 'Questo ruolo ha :userCount utenti assegnati. Se vuoi migrare gli utenti da questo ruolo selezionane uno nuovo sotto.', - 'role_delete_no_migration' => 'Non migrare gli utenti', + 'role_delete_no_migration' => "Non migrare gli utenti", 'role_delete_sure' => 'Sei sicuro di voler eliminare questo ruolo?', 'role_delete_success' => 'Ruolo eliminato correttamente', 'role_edit' => 'Modifica Ruolo', diff --git a/resources/lang/ja/entities.php b/resources/lang/ja/entities.php index 5a1941057..994f87e55 100644 --- a/resources/lang/ja/entities.php +++ b/resources/lang/ja/entities.php @@ -94,7 +94,7 @@ return [ 'shelves_edit' => '本棚を編集', 'shelves_delete' => '本棚を削除', 'shelves_delete_named' => '本棚「:name」を削除', - 'shelves_delete_explain' => 'これにより、この本棚「:name」が削除されます。含まれているブックは削除されません。', + 'shelves_delete_explain' => "これにより、この本棚「:name」が削除されます。含まれているブックは削除されません。", 'shelves_delete_confirmation' => '本当にこの本棚を削除してよろしいですか?', 'shelves_permissions' => 'Bookshelf Permissions', 'shelves_permissions_updated' => 'Bookshelf Permissions Updated', diff --git a/resources/lang/ja/passwords.php b/resources/lang/ja/passwords.php index 40493f6ce..cf4d43114 100644 --- a/resources/lang/ja/passwords.php +++ b/resources/lang/ja/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'パスワードは6文字以上である必要があります。', - 'user' => 'このEメールアドレスに一致するユーザが見つかりませんでした。', + 'user' => "このEメールアドレスに一致するユーザが見つかりませんでした。", 'token' => 'このメールアドレスのパスワードリセットトークンは無効です。', 'sent' => 'パスワードリセットリンクを送信しました。', 'reset' => 'パスワードはリセットされました。', diff --git a/resources/lang/ja/settings.php b/resources/lang/ja/settings.php index c606cfe1b..cdc8c79d2 100644 --- a/resources/lang/ja/settings.php +++ b/resources/lang/ja/settings.php @@ -132,7 +132,7 @@ return [ 'role_delete' => '役割を削除', 'role_delete_confirm' => '役割「:roleName」を削除します。', 'role_delete_users_assigned' => 'この役割は:userCount人のユーザに付与されています。該当するユーザを他の役割へ移行できます。', - 'role_delete_no_migration' => 'ユーザを移行しない', + 'role_delete_no_migration' => "ユーザを移行しない", 'role_delete_sure' => '本当に役割を削除してよろしいですか?', 'role_delete_success' => '役割を削除しました', 'role_edit' => '役割を編集', diff --git a/resources/lang/ko/entities.php b/resources/lang/ko/entities.php index 41d4dfb01..0deee72f6 100644 --- a/resources/lang/ko/entities.php +++ b/resources/lang/ko/entities.php @@ -94,7 +94,7 @@ return [ 'shelves_edit' => '서가 바꾸기', 'shelves_delete' => '서가 삭제하기', 'shelves_delete_named' => ':name 삭제하기', - 'shelves_delete_explain' => ':name을 지웁니다. 책자는 지우지 않습니다.', + 'shelves_delete_explain' => ":name을 지웁니다. 책자는 지우지 않습니다.", 'shelves_delete_confirmation' => '이 서가를 지울 건가요?', 'shelves_permissions' => '서가 권한', 'shelves_permissions_updated' => '서가 권한 바꿈', @@ -255,7 +255,7 @@ return [ 'tags' => '꼬리표', 'tag_name' => '꼬리표 이름', 'tag_value' => '리스트 값 (선택 사항)', - 'tags_explain' => '태그로 문서를 분류하세요.', + 'tags_explain' => "태그로 문서를 분류하세요.", 'tags_add' => '태그 추가', 'tags_remove' => '태그 삭제', 'attachments' => '첨부 파일', diff --git a/resources/lang/ko/errors.php b/resources/lang/ko/errors.php index e4ed5ccb3..b52ee91bc 100644 --- a/resources/lang/ko/errors.php +++ b/resources/lang/ko/errors.php @@ -28,7 +28,7 @@ return [ 'oidc_no_email_address' => 'Could not find an email address, for this user, in the data provided by the external authentication system', 'oidc_fail_authed' => 'Login using :system failed, system did not provide successful authorization', 'social_no_action_defined' => '무슨 활동인지 알 수 없습니다.', - 'social_login_bad_response' => ':socialAccount에 로그인할 수 없습니다. : \\n:error', + 'social_login_bad_response' => ":socialAccount에 로그인할 수 없습니다. : \\n:error", 'social_account_in_use' => ':socialAccount(을)를 가진 사용자가 있습니다. :socialAccount로 로그인하세요.', 'social_account_email_in_use' => ':email(을)를 가진 사용자가 있습니다. 쓰고 있는 계정을 :socialAccount에 연결하세요.', 'social_account_existing' => ':socialAccount(와)과 연결 상태입니다.', diff --git a/resources/lang/ko/passwords.php b/resources/lang/ko/passwords.php index 461afc74b..f93902aef 100644 --- a/resources/lang/ko/passwords.php +++ b/resources/lang/ko/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => '여덟 글자를 넘어야 합니다.', - 'user' => '메일 주소를 가진 사용자가 없습니다.', + 'user' => "메일 주소를 가진 사용자가 없습니다.", 'token' => '비밀번호 재설정 토큰이 이 이메일 주소에 유효하지 않습니다.', 'sent' => '메일을 보냈습니다.', 'reset' => '비밀번호를 바꿨습니다.', diff --git a/resources/lang/ko/settings.php b/resources/lang/ko/settings.php index 7a660bc2d..8828aa84f 100755 --- a/resources/lang/ko/settings.php +++ b/resources/lang/ko/settings.php @@ -132,7 +132,7 @@ return [ 'role_delete' => '권한 제거', 'role_delete_confirm' => ':roleName(을)를 지웁니다.', 'role_delete_users_assigned' => '이 권한을 가진 사용자 :userCount명에 할당할 권한을 고르세요.', - 'role_delete_no_migration' => '할당하지 않음', + 'role_delete_no_migration' => "할당하지 않음", 'role_delete_sure' => '이 권한을 지울 건가요?', 'role_delete_success' => '권한 지움', 'role_edit' => '권한 수정', diff --git a/resources/lang/lv/entities.php b/resources/lang/lv/entities.php index 21f1cbca5..6388b4d43 100644 --- a/resources/lang/lv/entities.php +++ b/resources/lang/lv/entities.php @@ -94,7 +94,7 @@ return [ 'shelves_edit' => 'Labot grāmatplauktu', 'shelves_delete' => 'Dzēst grāmatplauktu', 'shelves_delete_named' => 'Dzēst grāmatplauktu :name', - 'shelves_delete_explain' => 'Tiks dzēsts grāmatplaukts ar nosaukumu ":name". Tajā ievietotās grāmatas netiks dzēstas.', + 'shelves_delete_explain' => "Tiks dzēsts grāmatplaukts ar nosaukumu \":name\". Tajā ievietotās grāmatas netiks dzēstas.", 'shelves_delete_confirmation' => 'Vai esat pārliecināts, ka vēlaties dzēst šo grāmatplauktu?', 'shelves_permissions' => 'Grāmatplaukta atļaujas', 'shelves_permissions_updated' => 'Grāmatplaukta atļaujas atjauninātas', diff --git a/resources/lang/lv/passwords.php b/resources/lang/lv/passwords.php index 5824e71e6..7d939574f 100644 --- a/resources/lang/lv/passwords.php +++ b/resources/lang/lv/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'Parolēm jābūt vismaz astoņu simbolu garām un jāatbilst apstiprinājumam.', - 'user' => 'Mēs nevaram atrast lietotāju ar šādu e-pasta adresi.', + 'user' => "Mēs nevaram atrast lietotāju ar šādu e-pasta adresi.", 'token' => 'Paroles atiestatīšanas atslēga neatbilst šai e-pasta adresei.', 'sent' => 'Esam nosūtījuši paroles atiestatīšanas saiti!', 'reset' => 'Parole ir atiestatīta!', diff --git a/resources/lang/lv/settings.php b/resources/lang/lv/settings.php index 3d06aca13..7e56bc33b 100644 --- a/resources/lang/lv/settings.php +++ b/resources/lang/lv/settings.php @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Dzēst grupu', 'role_delete_confirm' => 'Loma \':roleName\' tiks dzēsta.', 'role_delete_users_assigned' => 'Šajā grupā ir pievienoti :userCount lietotāji. Ja vēlaties pārvietot lietotājus no šīs grupas, tad izvēlaties kādu no zemāk redzamajām grupām.', - 'role_delete_no_migration' => 'Nepārvietot lietotājus', + 'role_delete_no_migration' => "Nepārvietot lietotājus", 'role_delete_sure' => 'Vai tiešām vēlaties dzēst grupu?', 'role_delete_success' => 'Grupa veiksmīgi dzēsta', 'role_edit' => 'Rediģēt grupu', diff --git a/resources/lang/nb/passwords.php b/resources/lang/nb/passwords.php index b7afdaa80..8c3215b42 100644 --- a/resources/lang/nb/passwords.php +++ b/resources/lang/nb/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'Passord må inneholde minst åtte tegn og samsvarer med bekreftelsen.', - 'user' => 'Vi finner ikke en bruker med den e-postadressen.', + 'user' => "Vi finner ikke en bruker med den e-postadressen.", 'token' => 'Passordet for tilbakestilling av passord er ugyldig for denne e-postadressen.', 'sent' => 'Vi har sendt e-postadressen til tilbakestilling av passordet ditt!', 'reset' => 'Passordet ditt har blitt tilbakestilt!', diff --git a/resources/lang/nb/settings.php b/resources/lang/nb/settings.php index 6dfa8bad6..6354be2cb 100644 --- a/resources/lang/nb/settings.php +++ b/resources/lang/nb/settings.php @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Rolle slettet', 'role_delete_confirm' => 'Dette vil slette rollen «:roleName».', 'role_delete_users_assigned' => 'Denne rollen har :userCount kontoer koblet opp mot seg. Velg hvilke rolle du vil flytte disse til.', - 'role_delete_no_migration' => 'Ikke flytt kontoer', + 'role_delete_no_migration' => "Ikke flytt kontoer", 'role_delete_sure' => 'Er du sikker på at du vil slette rollen?', 'role_delete_success' => 'Rollen ble slettet', 'role_edit' => 'Endre rolle', diff --git a/resources/lang/nl/passwords.php b/resources/lang/nl/passwords.php index 5f90eb0df..4b27f03c2 100644 --- a/resources/lang/nl/passwords.php +++ b/resources/lang/nl/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'Wachtwoorden moeten overeenkomen en minimaal zes tekens lang zijn.', - 'user' => 'We kunnen niemand vinden met dat e-mailadres.', + 'user' => "We kunnen niemand vinden met dat e-mailadres.", 'token' => 'Het wachtwoord reset token is ongeldig voor dit e-mailadres.', 'sent' => 'We hebben je een link gestuurd om je wachtwoord te herstellen!', 'reset' => 'Je wachtwoord is hersteld!', diff --git a/resources/lang/nl/settings.php b/resources/lang/nl/settings.php index 379c3a1f6..5584d8e65 100644 --- a/resources/lang/nl/settings.php +++ b/resources/lang/nl/settings.php @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Rol Verwijderen', 'role_delete_confirm' => 'Dit verwijdert de rol \':roleName\'.', 'role_delete_users_assigned' => 'Er zijn :userCount gebruikers met deze rol. Selecteer hieronder een nieuwe rol als je deze gebruikers een andere rol wilt geven.', - 'role_delete_no_migration' => 'Geen gebruikers migreren', + 'role_delete_no_migration' => "Geen gebruikers migreren", 'role_delete_sure' => 'Weet je zeker dat je deze rol wilt verwijderen?', 'role_delete_success' => 'Rol succesvol verwijderd', 'role_edit' => 'Rol Bewerken', diff --git a/resources/lang/pl/passwords.php b/resources/lang/pl/passwords.php index dad844f74..7b67bf38d 100644 --- a/resources/lang/pl/passwords.php +++ b/resources/lang/pl/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'Hasło musi zawierać co najmniej 6 znaków i być zgodne z powtórzeniem.', - 'user' => 'Nie znaleziono użytkownika o takim adresie e-mail.', + 'user' => "Nie znaleziono użytkownika o takim adresie e-mail.", 'token' => 'Token resetowania hasła jest nieprawidłowy dla tego adresu e-mail.', 'sent' => 'Wysłaliśmy Ci link do resetowania hasła!', 'reset' => 'Twoje hasło zostało zresetowane!', diff --git a/resources/lang/pl/settings.php b/resources/lang/pl/settings.php index 23defdad8..4b41319b9 100644 --- a/resources/lang/pl/settings.php +++ b/resources/lang/pl/settings.php @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Usuń rolę', 'role_delete_confirm' => 'To spowoduje usunięcie roli \':roleName\'.', 'role_delete_users_assigned' => 'Tę rolę ma przypisanych :userCount użytkowników. Jeśli chcesz zmigrować użytkowników z tej roli, wybierz nową poniżej.', - 'role_delete_no_migration' => 'Nie migruj użytkowników', + 'role_delete_no_migration' => "Nie migruj użytkowników", 'role_delete_sure' => 'Czy na pewno chcesz usunąć tę rolę?', 'role_delete_success' => 'Rola usunięta pomyślnie', 'role_edit' => 'Edytuj rolę', diff --git a/resources/lang/pt/passwords.php b/resources/lang/pt/passwords.php index bf30e0e13..e468b9f68 100644 --- a/resources/lang/pt/passwords.php +++ b/resources/lang/pt/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'As palavras-passe devem ter no mínimo oito caracteres e serem iguais à confirmação.', - 'user' => 'Não pudemos encontrar um utilizador com o endereço de e-mail fornecido.', + 'user' => "Não pudemos encontrar um utilizador com o endereço de e-mail fornecido.", 'token' => 'O token de redefinição de senha é inválido para este endereço de e-mail.', 'sent' => 'Enviamos o link de redefinição de palavra-passe para o seu e-mail!', 'reset' => 'A sua palavra-passe foi redefinida com sucesso!', diff --git a/resources/lang/pt/settings.php b/resources/lang/pt/settings.php index c87bba984..d76ace1e2 100644 --- a/resources/lang/pt/settings.php +++ b/resources/lang/pt/settings.php @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Excluir Cargo', 'role_delete_confirm' => 'A ação vai eliminar o cargo de nome \':roleName\'.', 'role_delete_users_assigned' => 'Esse cargo tem :userCount utilizadores vinculados nele. Se quiser migrar utilizadores deste cargo para outro, selecione um novo cargo.', - 'role_delete_no_migration' => 'Não migrar utilizadores', + 'role_delete_no_migration' => "Não migrar utilizadores", 'role_delete_sure' => 'Tem certeza que deseja excluir este cargo?', 'role_delete_success' => 'Cargo excluído com sucesso', 'role_edit' => 'Editar Cargo', diff --git a/resources/lang/pt_BR/passwords.php b/resources/lang/pt_BR/passwords.php index 8343ad57a..fde9e2937 100644 --- a/resources/lang/pt_BR/passwords.php +++ b/resources/lang/pt_BR/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'Senhas devem ter ao menos oito caracteres e ser iguais à confirmação.', - 'user' => 'Não pudemos encontrar um usuário com o e-mail fornecido.', + 'user' => "Não pudemos encontrar um usuário com o e-mail fornecido.", 'token' => 'O token de redefinição de senha é inválido para este endereço de e-mail.', 'sent' => 'Enviamos o link de redefinição de senha para o seu e-mail!', 'reset' => 'Sua senha foi redefinida com sucesso!', diff --git a/resources/lang/pt_BR/settings.php b/resources/lang/pt_BR/settings.php index 170dd0a1a..4264e22c0 100644 --- a/resources/lang/pt_BR/settings.php +++ b/resources/lang/pt_BR/settings.php @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Excluir Cargo', 'role_delete_confirm' => 'A ação vai excluír o cargo de nome \':roleName\'.', 'role_delete_users_assigned' => 'Esse cargo tem :userCount usuários vinculados a ele. Se quiser migrar usuários desse cargo para outro, selecione um novo cargo.', - 'role_delete_no_migration' => 'Não migre os usuários', + 'role_delete_no_migration' => "Não migre os usuários", 'role_delete_sure' => 'Tem certeza que deseja excluir esse cargo?', 'role_delete_success' => 'Cargo excluído com sucesso', 'role_edit' => 'Editar Cargo', diff --git a/resources/lang/ru/entities.php b/resources/lang/ru/entities.php index d5418955c..122b82f52 100644 --- a/resources/lang/ru/entities.php +++ b/resources/lang/ru/entities.php @@ -255,7 +255,7 @@ return [ 'tags' => 'Теги', 'tag_name' => 'Имя тега', 'tag_value' => 'Значение тега (опционально)', - 'tags_explain' => 'Добавьте теги, чтобы лучше классифицировать ваш контент. \\n Вы можете присвоить значение тегу для более глубокой организации.', + 'tags_explain' => "Добавьте теги, чтобы лучше классифицировать ваш контент. \\n Вы можете присвоить значение тегу для более глубокой организации.", 'tags_add' => 'Добавить тег', 'tags_remove' => 'Удалить этот тег', 'attachments' => 'Вложения', diff --git a/resources/lang/ru/errors.php b/resources/lang/ru/errors.php index ae7bac814..1edef426c 100644 --- a/resources/lang/ru/errors.php +++ b/resources/lang/ru/errors.php @@ -28,7 +28,7 @@ return [ 'oidc_no_email_address' => 'Could not find an email address, for this user, in the data provided by the external authentication system', 'oidc_fail_authed' => 'Login using :system failed, system did not provide successful authorization', 'social_no_action_defined' => 'Действие не определено', - 'social_login_bad_response' => 'При попытке входа с :socialAccount произошла ошибка: \\n:error', + 'social_login_bad_response' => "При попытке входа с :socialAccount произошла ошибка: \\n:error", 'social_account_in_use' => 'Этот :socialAccount аккаунт уже используется, попробуйте войти с параметрами :socialAccount.', 'social_account_email_in_use' => 'Электронный ящик :email уже используется. Если у вас уже есть учетная запись, вы можете подключить свою учетную запись :socialAccount из настроек своего профиля.', 'social_account_existing' => 'Этот :socialAccount уже привязан к вашему профилю.', diff --git a/resources/lang/ru/passwords.php b/resources/lang/ru/passwords.php index 6880c0db6..433c70454 100644 --- a/resources/lang/ru/passwords.php +++ b/resources/lang/ru/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'Пароль должен содержать не менее восьми символов и совпадать с подтверждением.', - 'user' => 'Пользователя с данным адресом электронной почты не существует.', + 'user' => "Пользователя с данным адресом электронной почты не существует.", 'token' => 'Токен сброса пароля недействителен для этого адреса электронной почты.', 'sent' => 'Ссылка для сброса пароля отправлена на вашу почту!', 'reset' => 'Ваш пароль был сброшен!', diff --git a/resources/lang/ru/settings.php b/resources/lang/ru/settings.php index c4591dc06..af18213ce 100755 --- a/resources/lang/ru/settings.php +++ b/resources/lang/ru/settings.php @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Удалить роль', 'role_delete_confirm' => 'Это удалит роль с именем \':roleName\'.', 'role_delete_users_assigned' => 'Эта роль назначена :userCount пользователям. Если вы хотите перенести их, выберите новую роль ниже.', - 'role_delete_no_migration' => 'Не переносить пользователей', + 'role_delete_no_migration' => "Не переносить пользователей", 'role_delete_sure' => 'Вы уверены что хотите удалить данную роль?', 'role_delete_success' => 'Роль успешно удалена', 'role_edit' => 'Редактировать роль', diff --git a/resources/lang/sk/passwords.php b/resources/lang/sk/passwords.php index 9894b91b3..5b80f62da 100644 --- a/resources/lang/sk/passwords.php +++ b/resources/lang/sk/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'Heslo musí obsahovať aspoň osem znakov a musí byť rovnaké ako potvrdzujúce.', - 'user' => 'Nenašli sme používateľa s takou emailovou adresou.', + 'user' => "Nenašli sme používateľa s takou emailovou adresou.", 'token' => 'Token na obnovenie hesla je pre túto e-mailovú adresu neplatný.', 'sent' => 'Poslali sme Vám email s odkazom na reset hesla!', 'reset' => 'Vaše heslo bolo resetované!', diff --git a/resources/lang/sk/settings.php b/resources/lang/sk/settings.php index 4aa813d80..2e5d0b58f 100644 --- a/resources/lang/sk/settings.php +++ b/resources/lang/sk/settings.php @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Zmazať rolu', 'role_delete_confirm' => 'Toto zmaže rolu menom \':roleName\'.', 'role_delete_users_assigned' => 'Túto rolu má priradenú :userCount používateľov. Ak chcete premigrovať používateľov z tejto roly, vyberte novú rolu nižšie.', - 'role_delete_no_migration' => 'Nemigrovať používateľov', + 'role_delete_no_migration' => "Nemigrovať používateľov", 'role_delete_sure' => 'Ste si istý, že chcete zmazať túto rolu?', 'role_delete_success' => 'Rola úspešne zmazaná', 'role_edit' => 'Upraviť rolu', diff --git a/resources/lang/sl/passwords.php b/resources/lang/sl/passwords.php index 4a3b791b5..e9e195fe9 100644 --- a/resources/lang/sl/passwords.php +++ b/resources/lang/sl/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'Gesla morajo biti najmanj osem znakov dolga in se morajo ujemati s potrditvijo.', - 'user' => 'Ne moremo najti uporabnika s tem e-poštnim naslovom.', + 'user' => "Ne moremo najti uporabnika s tem e-poštnim naslovom.", 'token' => 'Žeton za ponastavitev gesla ni veljaven za ta e-poštni naslov.', 'sent' => 'Poslali smo vam povezavo za ponastavitev gesla!', 'reset' => 'Vaše geslo je bilo ponastavljeno!', diff --git a/resources/lang/sl/settings.php b/resources/lang/sl/settings.php index e18dc11c2..e4bfb0115 100644 --- a/resources/lang/sl/settings.php +++ b/resources/lang/sl/settings.php @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Brisanje vloge', 'role_delete_confirm' => 'Izbrisana bo vloga z imenom \':roleName\'.', 'role_delete_users_assigned' => 'Ta vloga ima dodeljenih :userCount uporabnikov. V kolikor želite uporabnike preseliti iz te vloge, spodaj izberite novo vlogo.', - 'role_delete_no_migration' => 'Ne prenašaj uporabnikov', + 'role_delete_no_migration' => "Ne prenašaj uporabnikov", 'role_delete_sure' => 'Ali ste prepričani, da želite izbrisati to vlogo?', 'role_delete_success' => 'Vloga uspešno izbrisana', 'role_edit' => 'Uredi vlogo', diff --git a/resources/lang/sv/passwords.php b/resources/lang/sv/passwords.php index 9bd8dbc02..640309b88 100644 --- a/resources/lang/sv/passwords.php +++ b/resources/lang/sv/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'Lösenord måste vara minst sex tecken långa och anges likadant två gånger.', - 'user' => 'Det finns ingen användare med den e-postadressen.', + 'user' => "Det finns ingen användare med den e-postadressen.", 'token' => 'Lösenordsåterställningstoken är ogiltig för denna e-postadress.', 'sent' => 'Vi har mailat dig en länk för att återställa ditt lösenord!', 'reset' => 'Ditt lösenord har blivit återställt!', diff --git a/resources/lang/sv/settings.php b/resources/lang/sv/settings.php index 76ceede74..57b2965aa 100644 --- a/resources/lang/sv/settings.php +++ b/resources/lang/sv/settings.php @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Ta bort roll', 'role_delete_confirm' => 'Rollen med namn \':roleName\' kommer att tas bort.', 'role_delete_users_assigned' => 'Det finns :userCount användare som tillhör den här rollen. Om du vill migrera användarna från den här rollen, välj en ny roll nedan.', - 'role_delete_no_migration' => 'Migrera inte användare', + 'role_delete_no_migration' => "Migrera inte användare", 'role_delete_sure' => 'Är du säker på att du vill ta bort den här rollen?', 'role_delete_success' => 'Rollen har tagits bort', 'role_edit' => 'Redigera roll', diff --git a/resources/lang/tr/entities.php b/resources/lang/tr/entities.php index c562ec824..a32deb373 100644 --- a/resources/lang/tr/entities.php +++ b/resources/lang/tr/entities.php @@ -255,7 +255,7 @@ return [ 'tags' => 'Etiketler', 'tag_name' => 'Etiket İsmi', 'tag_value' => 'Etiket Değeri (Opsiyonel)', - 'tags_explain' => 'İçeriğinizi daha iyi kategorize etmek için etiket ekleyin. Etiketlere değer atayarak daha derinlemesine bir düzen elde edebilirsiniz.', + 'tags_explain' => "İçeriğinizi daha iyi kategorize etmek için etiket ekleyin. Etiketlere değer atayarak daha derinlemesine bir düzen elde edebilirsiniz.", 'tags_add' => 'Başka etiket ekle', 'tags_remove' => 'Bu etiketi sil', 'attachments' => 'Ekler', diff --git a/resources/lang/tr/passwords.php b/resources/lang/tr/passwords.php index 890f2d628..ba1fd913f 100644 --- a/resources/lang/tr/passwords.php +++ b/resources/lang/tr/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'Şifreniz en az 6 karakterden oluşmalı ve her iki şifre de birbiri ile eşleşmelidir.', - 'user' => 'Bu e-posta adresine sahip bir kullanıcı bulamadık.', + 'user' => "Bu e-posta adresine sahip bir kullanıcı bulamadık.", 'token' => 'Şifre sıfırlama anahtarı, bu e-posta adresi için geçersizdir.', 'sent' => 'Şifre sıfırlama bağlantısını e-posta adresinize gönderdik!', 'reset' => 'Şifreniz sıfırlandı!', diff --git a/resources/lang/tr/settings.php b/resources/lang/tr/settings.php index 95de460b7..8f7261c5d 100755 --- a/resources/lang/tr/settings.php +++ b/resources/lang/tr/settings.php @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Rolü Sil', 'role_delete_confirm' => 'Bu işlem, \':roleName\' adlı rolü silecektir.', 'role_delete_users_assigned' => 'Bu role atanmış :userCount adet kullanıcı var. Eğer bu kullanıcıların rollerini değiştirmek istiyorsanız, aşağıdan yeni bir rol seçin.', - 'role_delete_no_migration' => 'Kullanıcıları taşıma', + 'role_delete_no_migration' => "Kullanıcıları taşıma", 'role_delete_sure' => 'Bu rolü silmek istediğinize emin misiniz?', 'role_delete_success' => 'Rol başarıyla silindi', 'role_edit' => 'Rolü Düzenle', diff --git a/resources/lang/uk/passwords.php b/resources/lang/uk/passwords.php index 62a02073d..90c31777c 100644 --- a/resources/lang/uk/passwords.php +++ b/resources/lang/uk/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'Пароль повинен містити не менше восьми символів і збігатись з підтвердженням.', - 'user' => 'Ми не можемо знайти користувача з цією адресою електронної пошти.', + 'user' => "Ми не можемо знайти користувача з цією адресою електронної пошти.", 'token' => 'Токен скидання пароля недійсний для цієї адреси електронної пошти.', 'sent' => 'Ми надіслали Вам електронний лист із посиланням для скидання пароля!', 'reset' => 'Ваш пароль скинуто!', diff --git a/resources/lang/uk/settings.php b/resources/lang/uk/settings.php index 1b48adfec..a538ff90d 100644 --- a/resources/lang/uk/settings.php +++ b/resources/lang/uk/settings.php @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Видалити роль', 'role_delete_confirm' => 'Це призведе до видалення ролі з назвою \':roleName\'.', 'role_delete_users_assigned' => 'Цій ролі належать :userCount користувачі(в). Якщо ви хочете перенести користувачів із цієї ролі, виберіть нову роль нижче.', - 'role_delete_no_migration' => 'Не мігрувати користувачів', + 'role_delete_no_migration' => "Не мігрувати користувачів", 'role_delete_sure' => 'Ви впевнені, що хочете видалити цю роль?', 'role_delete_success' => 'Роль успішно видалена', 'role_edit' => 'Редагувати роль', diff --git a/resources/lang/vi/passwords.php b/resources/lang/vi/passwords.php index e31974161..65b42b4d8 100644 --- a/resources/lang/vi/passwords.php +++ b/resources/lang/vi/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => 'Mật khẩu phải có tối thiểu 8 ký tự và và phải trùng với mật khẩu xác nhận.', - 'user' => 'Chúng tôi không tìm thấy người dùng với địa chỉ email đó.', + 'user' => "Chúng tôi không tìm thấy người dùng với địa chỉ email đó.", 'token' => 'Mã token đặt lại mật khẩu cho địa chỉ email này không hợp lệ.', 'sent' => 'Chúng tôi đã gửi email chứa liên kết đặt lại mật khẩu cho bạn!', 'reset' => 'Mật khẩu của bạn đã được đặt lại!', diff --git a/resources/lang/vi/settings.php b/resources/lang/vi/settings.php index 39358a13a..566374967 100644 --- a/resources/lang/vi/settings.php +++ b/resources/lang/vi/settings.php @@ -132,7 +132,7 @@ return [ 'role_delete' => 'Xóa quyền', 'role_delete_confirm' => 'Chức năng này sẽ xóa quyền với tên \':roleName\'.', 'role_delete_users_assigned' => 'Quyền này có :userCount người dùng được gán. Nếu bạn muốn di dời các người dùng từ quyền này hãy chọn một quyền mới bên dưới.', - 'role_delete_no_migration' => 'Không di dời các người dùng', + 'role_delete_no_migration' => "Không di dời các người dùng", 'role_delete_sure' => 'Bạn có chắc rằng muốn xóa quyền này?', 'role_delete_success' => 'Quyền đã được xóa thành công', 'role_edit' => 'Sửa quyền', diff --git a/resources/lang/zh_CN/passwords.php b/resources/lang/zh_CN/passwords.php index 712120f60..8d8272ee0 100644 --- a/resources/lang/zh_CN/passwords.php +++ b/resources/lang/zh_CN/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => '密码必须至少包含六个字符并与确认相符。', - 'user' => '使用该Email地址的用户不存在。', + 'user' => "使用该Email地址的用户不存在。", 'token' => '重置密码链接无法发送至此邮件地址。', 'sent' => '我们已经通过Email发送您的密码重置链接!', 'reset' => '您的密码已被重置!', diff --git a/resources/lang/zh_CN/settings.php b/resources/lang/zh_CN/settings.php index 1686406de..b662bb755 100755 --- a/resources/lang/zh_CN/settings.php +++ b/resources/lang/zh_CN/settings.php @@ -132,7 +132,7 @@ return [ 'role_delete' => '删除角色', 'role_delete_confirm' => '这将会删除名为 \':roleName\' 的角色.', 'role_delete_users_assigned' => '有:userCount位用户属于此角色。如果您想将此角色中的用户迁移,请在下面选择一个新角色。', - 'role_delete_no_migration' => '不要迁移用户', + 'role_delete_no_migration' => "不要迁移用户", 'role_delete_sure' => '您确定要删除这个角色?', 'role_delete_success' => '角色删除成功', 'role_edit' => '编辑角色', diff --git a/resources/lang/zh_TW/entities.php b/resources/lang/zh_TW/entities.php index a19e53860..a8447ae78 100644 --- a/resources/lang/zh_TW/entities.php +++ b/resources/lang/zh_TW/entities.php @@ -94,7 +94,7 @@ return [ 'shelves_edit' => '編輯書架', 'shelves_delete' => '刪除書架', 'shelves_delete_named' => '刪除書架 :name', - 'shelves_delete_explain' => '這將刪除名為「:name」的書架。但其中的書本不會被刪除。', + 'shelves_delete_explain' => "這將刪除名為「:name」的書架。但其中的書本不會被刪除。", 'shelves_delete_confirmation' => '您確定要刪除此書架嗎?', 'shelves_permissions' => '書架權限', 'shelves_permissions_updated' => '書架權限已更新', diff --git a/resources/lang/zh_TW/passwords.php b/resources/lang/zh_TW/passwords.php index 614b9e2bf..f4d8dc30c 100644 --- a/resources/lang/zh_TW/passwords.php +++ b/resources/lang/zh_TW/passwords.php @@ -7,7 +7,7 @@ return [ 'password' => '密碼必須至少八個字元,並與確認密碼相符。', - 'user' => '沒有使用這個電子郵件位址的使用者。', + 'user' => "沒有使用這個電子郵件位址的使用者。", 'token' => '這個電子郵件地址的密碼重設權杖無效。', 'sent' => '我們已經透過電子郵件發送您的密碼重設連結。', 'reset' => '您的密碼已被重設!', diff --git a/resources/lang/zh_TW/settings.php b/resources/lang/zh_TW/settings.php index ca49aeaad..9816a8c15 100644 --- a/resources/lang/zh_TW/settings.php +++ b/resources/lang/zh_TW/settings.php @@ -132,7 +132,7 @@ return [ 'role_delete' => '刪除角色', 'role_delete_confirm' => '這將會刪除名為「:roleName」的角色.', 'role_delete_users_assigned' => '有 :userCount 位使用者屬於此角色。如果您想將此角色中的使用者遷移,請在下面選擇一個新角色。', - 'role_delete_no_migration' => '不要遷移使用者', + 'role_delete_no_migration' => "不要遷移使用者", 'role_delete_sure' => '您確定要刪除此角色?', 'role_delete_success' => '角色刪除成功', 'role_edit' => '編輯角色', From de5322288c253e87dcfd0594211333a406632fa1 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Thu, 4 Nov 2021 22:57:49 +0000 Subject: [PATCH 10/59] Applied latest styleci changes --- app/Config/clockwork.php | 818 +++++++++--------- app/Config/filesystems.php | 8 +- .../Middleware/RedirectIfAuthenticated.php | 9 +- public/index.php | 4 +- 4 files changed, 420 insertions(+), 419 deletions(-) diff --git a/app/Config/clockwork.php b/app/Config/clockwork.php index ff9929d52..394af8451 100644 --- a/app/Config/clockwork.php +++ b/app/Config/clockwork.php @@ -2,414 +2,414 @@ return [ - /* - |------------------------------------------------------------------------------------------------------------------ - | Enable Clockwork - |------------------------------------------------------------------------------------------------------------------ - | - | Clockwork is enabled by default only when your application is in debug mode. Here you can explicitly enable or - | disable Clockwork. When disabled, no data is collected and the api and web ui are inactive. - | - */ - - 'enable' => env('CLOCKWORK_ENABLE', false), - - /* - |------------------------------------------------------------------------------------------------------------------ - | Features - |------------------------------------------------------------------------------------------------------------------ - | - | You can enable or disable various Clockwork features here. Some features have additional settings (eg. slow query - | threshold for database queries). - | - */ - - 'features' => [ - - // Cache usage stats and cache queries including results - 'cache' => [ - 'enabled' => true, - - // Collect cache queries - 'collect_queries' => true, - - // Collect values from cache queries (high performance impact with a very high number of queries) - 'collect_values' => false - ], - - // Database usage stats and queries - 'database' => [ - 'enabled' => true, - - // Collect database queries (high performance impact with a very high number of queries) - 'collect_queries' => true, - - // Collect details of models updates (high performance impact with a lot of model updates) - 'collect_models_actions' => true, - - // Collect details of retrieved models (very high performance impact with a lot of models retrieved) - 'collect_models_retrieved' => false, - - // Query execution time threshold in miliseconds after which the query will be marked as slow - 'slow_threshold' => null, - - // Collect only slow database queries - 'slow_only' => false, - - // Detect and report duplicate (N+1) queries - 'detect_duplicate_queries' => false - ], - - // Dispatched events - 'events' => [ - 'enabled' => true, - - // Ignored events (framework events are ignored by default) - 'ignored_events' => [ - // App\Events\UserRegistered::class, - // 'user.registered' - ], - ], - - // Laravel log (you can still log directly to Clockwork with laravel log disabled) - 'log' => [ - 'enabled' => true - ], - - // Sent notifications - 'notifications' => [ - 'enabled' => true, - ], - - // Performance metrics - 'performance' => [ - // Allow collecting of client metrics. Requires separate clockwork-browser npm package. - 'client_metrics' => true - ], - - // Dispatched queue jobs - 'queue' => [ - 'enabled' => true - ], - - // Redis commands - 'redis' => [ - 'enabled' => true - ], - - // Routes list - 'routes' => [ - 'enabled' => false, - - // Collect only routes from particular namespaces (only application routes by default) - 'only_namespaces' => [ 'App' ] - ], - - // Rendered views - 'views' => [ - 'enabled' => true, - - // Collect views including view data (high performance impact with a high number of views) - 'collect_data' => false, - - // Use Twig profiler instead of Laravel events for apps using laravel-twigbridge (more precise, but does - // not support collecting view data) - 'use_twig_profiler' => false - ] - - ], - - /* - |------------------------------------------------------------------------------------------------------------------ - | Enable web UI - |------------------------------------------------------------------------------------------------------------------ - | - | Clockwork comes with a web UI accessibla via http://your.app/clockwork. Here you can enable or disable this - | feature. You can also set a custom path for the web UI. - | - */ - - 'web' => true, - - /* - |------------------------------------------------------------------------------------------------------------------ - | Enable toolbar - |------------------------------------------------------------------------------------------------------------------ - | - | Clockwork can show a toolbar with basic metrics on all responses. Here you can enable or disable this feature. - | Requires a separate clockwork-browser npm library. - | For installation instructions see https://underground.works/clockwork/#docs-viewing-data - | - */ - - 'toolbar' => true, - - /* - |------------------------------------------------------------------------------------------------------------------ - | HTTP requests collection - |------------------------------------------------------------------------------------------------------------------ - | - | Clockwork collects data about HTTP requests to your app. Here you can choose which requests should be collected. - | - */ - - 'requests' => [ - // With on-demand mode enabled, Clockwork will only profile requests when the browser extension is open or you - // manually pass a "clockwork-profile" cookie or get/post data key. - // Optionally you can specify a "secret" that has to be passed as the value to enable profiling. - 'on_demand' => false, - - // Collect only errors (requests with HTTP 4xx and 5xx responses) - 'errors_only' => false, - - // Response time threshold in miliseconds after which the request will be marked as slow - 'slow_threshold' => null, - - // Collect only slow requests - 'slow_only' => false, - - // Sample the collected requests (eg. set to 100 to collect only 1 in 100 requests) - 'sample' => false, - - // List of URIs that should not be collected - 'except' => [ - '/horizon/.*', // Laravel Horizon requests - '/telescope/.*', // Laravel Telescope requests - '/_debugbar/.*', // Laravel DebugBar requests - ], - - // List of URIs that should be collected, any other URI will not be collected if not empty - 'only' => [ - // '/api/.*' - ], - - // Don't collect OPTIONS requests, mostly used in the CSRF pre-flight requests and are rarely of interest - 'except_preflight' => true - ], - - /* - |------------------------------------------------------------------------------------------------------------------ - | Artisan commands collection - |------------------------------------------------------------------------------------------------------------------ - | - | Clockwork can collect data about executed artisan commands. Here you can enable and configure which commands - | should be collected. - | - */ - - 'artisan' => [ - // Enable or disable collection of executed Artisan commands - 'collect' => false, - - // List of commands that should not be collected (built-in commands are not collected by default) - 'except' => [ - // 'inspire' - ], - - // List of commands that should be collected, any other command will not be collected if not empty - 'only' => [ - // 'inspire' - ], - - // Enable or disable collection of command output - 'collect_output' => false, - - // Enable or disable collection of built-in Laravel commands - 'except_laravel_commands' => true - ], - - /* - |------------------------------------------------------------------------------------------------------------------ - | Queue jobs collection - |------------------------------------------------------------------------------------------------------------------ - | - | Clockwork can collect data about executed queue jobs. Here you can enable and configure which queue jobs should - | be collected. - | - */ - - 'queue' => [ - // Enable or disable collection of executed queue jobs - 'collect' => false, - - // List of queue jobs that should not be collected - 'except' => [ - // App\Jobs\ExpensiveJob::class - ], - - // List of queue jobs that should be collected, any other queue job will not be collected if not empty - 'only' => [ - // App\Jobs\BuggyJob::class - ] - ], - - /* - |------------------------------------------------------------------------------------------------------------------ - | Tests collection - |------------------------------------------------------------------------------------------------------------------ - | - | Clockwork can collect data about executed tests. Here you can enable and configure which tests should be - | collected. - | - */ - - 'tests' => [ - // Enable or disable collection of ran tests - 'collect' => false, - - // List of tests that should not be collected - 'except' => [ - // Tests\Unit\ExampleTest::class - ] - ], - - /* - |------------------------------------------------------------------------------------------------------------------ - | Enable data collection when Clockwork is disabled - |------------------------------------------------------------------------------------------------------------------ - | - | You can enable this setting to collect data even when Clockwork is disabled. Eg. for future analysis. - | - */ - - 'collect_data_always' => false, - - /* - |------------------------------------------------------------------------------------------------------------------ - | Metadata storage - |------------------------------------------------------------------------------------------------------------------ - | - | Configure how is the metadata collected by Clockwork stored. Two options are available: - | - files - A simple fast storage implementation storing data in one-per-request files. - | - sql - Stores requests in a sql database. Supports MySQL, Postgresql, Sqlite and requires PDO. - | - */ - - 'storage' => 'files', - - // Path where the Clockwork metadata is stored - 'storage_files_path' => storage_path('clockwork'), - - // Compress the metadata files using gzip, trading a little bit of performance for lower disk usage - 'storage_files_compress' => false, - - // SQL database to use, can be a name of database configured in database.php or a path to a sqlite file - 'storage_sql_database' => storage_path('clockwork.sqlite'), - - // SQL table name to use, the table is automatically created and udpated when needed - 'storage_sql_table' => 'clockwork', - - // Maximum lifetime of collected metadata in minutes, older requests will automatically be deleted, false to disable - 'storage_expiration' => 60 * 24 * 7, - - /* - |------------------------------------------------------------------------------------------------------------------ - | Authentication - |------------------------------------------------------------------------------------------------------------------ - | - | Clockwork can be configured to require authentication before allowing access to the collected data. This might be - | useful when the application is publicly accessible. Setting to true will enable a simple authentication with a - | pre-configured password. You can also pass a class name of a custom implementation. - | - */ - - 'authentication' => false, - - // Password for the simple authentication - 'authentication_password' => 'VerySecretPassword', - - /* - |------------------------------------------------------------------------------------------------------------------ - | Stack traces collection - |------------------------------------------------------------------------------------------------------------------ - | - | Clockwork can collect stack traces for log messages and certain data like database queries. Here you can set - | whether to collect stack traces, limit the number of collected frames and set further configuration. Collecting - | long stack traces considerably increases metadata size. - | - */ - - 'stack_traces' => [ - // Enable or disable collecting of stack traces - 'enabled' => true, - - // Limit the number of frames to be collected - 'limit' => 10, - - // List of vendor names to skip when determining caller, common vendors are automatically added - 'skip_vendors' => [ - // 'phpunit' - ], - - // List of namespaces to skip when determining caller - 'skip_namespaces' => [ - // 'Laravel' - ], - - // List of class names to skip when determining caller - 'skip_classes' => [ - // App\CustomLog::class - ] - - ], - - /* - |------------------------------------------------------------------------------------------------------------------ - | Serialization - |------------------------------------------------------------------------------------------------------------------ - | - | Clockwork serializes the collected data to json for storage and transfer. Here you can configure certain aspects - | of serialization. Serialization has a large effect on the cpu time and memory usage. - | - */ - - // Maximum depth of serialized multi-level arrays and objects - 'serialization_depth' => 10, - - // A list of classes that will never be serialized (eg. a common service container class) - 'serialization_blackbox' => [ - \Illuminate\Container\Container::class, - \Illuminate\Foundation\Application::class, - ], - - /* - |------------------------------------------------------------------------------------------------------------------ - | Register helpers - |------------------------------------------------------------------------------------------------------------------ - | - | Clockwork comes with a "clock" global helper function. You can use this helper to quickly log something and to - | access the Clockwork instance. - | - */ - - 'register_helpers' => true, - - /* - |------------------------------------------------------------------------------------------------------------------ - | Send Headers for AJAX request - |------------------------------------------------------------------------------------------------------------------ - | - | When trying to collect data the AJAX method can sometimes fail if it is missing required headers. For example, an - | API might require a version number using Accept headers to route the HTTP request to the correct codebase. - | - */ - - 'headers' => [ - // 'Accept' => 'application/vnd.com.whatever.v1+json', - ], - - /* - |------------------------------------------------------------------------------------------------------------------ - | Server-Timing - |------------------------------------------------------------------------------------------------------------------ - | - | Clockwork supports the W3C Server Timing specification, which allows for collecting a simple performance metrics - | in a cross-browser way. Eg. in Chrome, your app, database and timeline event timings will be shown in the Dev - | Tools network tab. This setting specifies the max number of timeline events that will be sent. Setting to false - | will disable the feature. - | - */ - - 'server_timing' => 10 + /* + |------------------------------------------------------------------------------------------------------------------ + | Enable Clockwork + |------------------------------------------------------------------------------------------------------------------ + | + | Clockwork is enabled by default only when your application is in debug mode. Here you can explicitly enable or + | disable Clockwork. When disabled, no data is collected and the api and web ui are inactive. + | + */ + + 'enable' => env('CLOCKWORK_ENABLE', false), + + /* + |------------------------------------------------------------------------------------------------------------------ + | Features + |------------------------------------------------------------------------------------------------------------------ + | + | You can enable or disable various Clockwork features here. Some features have additional settings (eg. slow query + | threshold for database queries). + | + */ + + 'features' => [ + + // Cache usage stats and cache queries including results + 'cache' => [ + 'enabled' => true, + + // Collect cache queries + 'collect_queries' => true, + + // Collect values from cache queries (high performance impact with a very high number of queries) + 'collect_values' => false, + ], + + // Database usage stats and queries + 'database' => [ + 'enabled' => true, + + // Collect database queries (high performance impact with a very high number of queries) + 'collect_queries' => true, + + // Collect details of models updates (high performance impact with a lot of model updates) + 'collect_models_actions' => true, + + // Collect details of retrieved models (very high performance impact with a lot of models retrieved) + 'collect_models_retrieved' => false, + + // Query execution time threshold in miliseconds after which the query will be marked as slow + 'slow_threshold' => null, + + // Collect only slow database queries + 'slow_only' => false, + + // Detect and report duplicate (N+1) queries + 'detect_duplicate_queries' => false, + ], + + // Dispatched events + 'events' => [ + 'enabled' => true, + + // Ignored events (framework events are ignored by default) + 'ignored_events' => [ + // App\Events\UserRegistered::class, + // 'user.registered' + ], + ], + + // Laravel log (you can still log directly to Clockwork with laravel log disabled) + 'log' => [ + 'enabled' => true, + ], + + // Sent notifications + 'notifications' => [ + 'enabled' => true, + ], + + // Performance metrics + 'performance' => [ + // Allow collecting of client metrics. Requires separate clockwork-browser npm package. + 'client_metrics' => true, + ], + + // Dispatched queue jobs + 'queue' => [ + 'enabled' => true, + ], + + // Redis commands + 'redis' => [ + 'enabled' => true, + ], + + // Routes list + 'routes' => [ + 'enabled' => false, + + // Collect only routes from particular namespaces (only application routes by default) + 'only_namespaces' => ['App'], + ], + + // Rendered views + 'views' => [ + 'enabled' => true, + + // Collect views including view data (high performance impact with a high number of views) + 'collect_data' => false, + + // Use Twig profiler instead of Laravel events for apps using laravel-twigbridge (more precise, but does + // not support collecting view data) + 'use_twig_profiler' => false, + ], + + ], + + /* + |------------------------------------------------------------------------------------------------------------------ + | Enable web UI + |------------------------------------------------------------------------------------------------------------------ + | + | Clockwork comes with a web UI accessibla via http://your.app/clockwork. Here you can enable or disable this + | feature. You can also set a custom path for the web UI. + | + */ + + 'web' => true, + + /* + |------------------------------------------------------------------------------------------------------------------ + | Enable toolbar + |------------------------------------------------------------------------------------------------------------------ + | + | Clockwork can show a toolbar with basic metrics on all responses. Here you can enable or disable this feature. + | Requires a separate clockwork-browser npm library. + | For installation instructions see https://underground.works/clockwork/#docs-viewing-data + | + */ + + 'toolbar' => true, + + /* + |------------------------------------------------------------------------------------------------------------------ + | HTTP requests collection + |------------------------------------------------------------------------------------------------------------------ + | + | Clockwork collects data about HTTP requests to your app. Here you can choose which requests should be collected. + | + */ + + 'requests' => [ + // With on-demand mode enabled, Clockwork will only profile requests when the browser extension is open or you + // manually pass a "clockwork-profile" cookie or get/post data key. + // Optionally you can specify a "secret" that has to be passed as the value to enable profiling. + 'on_demand' => false, + + // Collect only errors (requests with HTTP 4xx and 5xx responses) + 'errors_only' => false, + + // Response time threshold in miliseconds after which the request will be marked as slow + 'slow_threshold' => null, + + // Collect only slow requests + 'slow_only' => false, + + // Sample the collected requests (eg. set to 100 to collect only 1 in 100 requests) + 'sample' => false, + + // List of URIs that should not be collected + 'except' => [ + '/horizon/.*', // Laravel Horizon requests + '/telescope/.*', // Laravel Telescope requests + '/_debugbar/.*', // Laravel DebugBar requests + ], + + // List of URIs that should be collected, any other URI will not be collected if not empty + 'only' => [ + // '/api/.*' + ], + + // Don't collect OPTIONS requests, mostly used in the CSRF pre-flight requests and are rarely of interest + 'except_preflight' => true, + ], + + /* + |------------------------------------------------------------------------------------------------------------------ + | Artisan commands collection + |------------------------------------------------------------------------------------------------------------------ + | + | Clockwork can collect data about executed artisan commands. Here you can enable and configure which commands + | should be collected. + | + */ + + 'artisan' => [ + // Enable or disable collection of executed Artisan commands + 'collect' => false, + + // List of commands that should not be collected (built-in commands are not collected by default) + 'except' => [ + // 'inspire' + ], + + // List of commands that should be collected, any other command will not be collected if not empty + 'only' => [ + // 'inspire' + ], + + // Enable or disable collection of command output + 'collect_output' => false, + + // Enable or disable collection of built-in Laravel commands + 'except_laravel_commands' => true, + ], + + /* + |------------------------------------------------------------------------------------------------------------------ + | Queue jobs collection + |------------------------------------------------------------------------------------------------------------------ + | + | Clockwork can collect data about executed queue jobs. Here you can enable and configure which queue jobs should + | be collected. + | + */ + + 'queue' => [ + // Enable or disable collection of executed queue jobs + 'collect' => false, + + // List of queue jobs that should not be collected + 'except' => [ + // App\Jobs\ExpensiveJob::class + ], + + // List of queue jobs that should be collected, any other queue job will not be collected if not empty + 'only' => [ + // App\Jobs\BuggyJob::class + ], + ], + + /* + |------------------------------------------------------------------------------------------------------------------ + | Tests collection + |------------------------------------------------------------------------------------------------------------------ + | + | Clockwork can collect data about executed tests. Here you can enable and configure which tests should be + | collected. + | + */ + + 'tests' => [ + // Enable or disable collection of ran tests + 'collect' => false, + + // List of tests that should not be collected + 'except' => [ + // Tests\Unit\ExampleTest::class + ], + ], + + /* + |------------------------------------------------------------------------------------------------------------------ + | Enable data collection when Clockwork is disabled + |------------------------------------------------------------------------------------------------------------------ + | + | You can enable this setting to collect data even when Clockwork is disabled. Eg. for future analysis. + | + */ + + 'collect_data_always' => false, + + /* + |------------------------------------------------------------------------------------------------------------------ + | Metadata storage + |------------------------------------------------------------------------------------------------------------------ + | + | Configure how is the metadata collected by Clockwork stored. Two options are available: + | - files - A simple fast storage implementation storing data in one-per-request files. + | - sql - Stores requests in a sql database. Supports MySQL, Postgresql, Sqlite and requires PDO. + | + */ + + 'storage' => 'files', + + // Path where the Clockwork metadata is stored + 'storage_files_path' => storage_path('clockwork'), + + // Compress the metadata files using gzip, trading a little bit of performance for lower disk usage + 'storage_files_compress' => false, + + // SQL database to use, can be a name of database configured in database.php or a path to a sqlite file + 'storage_sql_database' => storage_path('clockwork.sqlite'), + + // SQL table name to use, the table is automatically created and udpated when needed + 'storage_sql_table' => 'clockwork', + + // Maximum lifetime of collected metadata in minutes, older requests will automatically be deleted, false to disable + 'storage_expiration' => 60 * 24 * 7, + + /* + |------------------------------------------------------------------------------------------------------------------ + | Authentication + |------------------------------------------------------------------------------------------------------------------ + | + | Clockwork can be configured to require authentication before allowing access to the collected data. This might be + | useful when the application is publicly accessible. Setting to true will enable a simple authentication with a + | pre-configured password. You can also pass a class name of a custom implementation. + | + */ + + 'authentication' => false, + + // Password for the simple authentication + 'authentication_password' => 'VerySecretPassword', + + /* + |------------------------------------------------------------------------------------------------------------------ + | Stack traces collection + |------------------------------------------------------------------------------------------------------------------ + | + | Clockwork can collect stack traces for log messages and certain data like database queries. Here you can set + | whether to collect stack traces, limit the number of collected frames and set further configuration. Collecting + | long stack traces considerably increases metadata size. + | + */ + + 'stack_traces' => [ + // Enable or disable collecting of stack traces + 'enabled' => true, + + // Limit the number of frames to be collected + 'limit' => 10, + + // List of vendor names to skip when determining caller, common vendors are automatically added + 'skip_vendors' => [ + // 'phpunit' + ], + + // List of namespaces to skip when determining caller + 'skip_namespaces' => [ + // 'Laravel' + ], + + // List of class names to skip when determining caller + 'skip_classes' => [ + // App\CustomLog::class + ], + + ], + + /* + |------------------------------------------------------------------------------------------------------------------ + | Serialization + |------------------------------------------------------------------------------------------------------------------ + | + | Clockwork serializes the collected data to json for storage and transfer. Here you can configure certain aspects + | of serialization. Serialization has a large effect on the cpu time and memory usage. + | + */ + + // Maximum depth of serialized multi-level arrays and objects + 'serialization_depth' => 10, + + // A list of classes that will never be serialized (eg. a common service container class) + 'serialization_blackbox' => [ + \Illuminate\Container\Container::class, + \Illuminate\Foundation\Application::class, + ], + + /* + |------------------------------------------------------------------------------------------------------------------ + | Register helpers + |------------------------------------------------------------------------------------------------------------------ + | + | Clockwork comes with a "clock" global helper function. You can use this helper to quickly log something and to + | access the Clockwork instance. + | + */ + + 'register_helpers' => true, + + /* + |------------------------------------------------------------------------------------------------------------------ + | Send Headers for AJAX request + |------------------------------------------------------------------------------------------------------------------ + | + | When trying to collect data the AJAX method can sometimes fail if it is missing required headers. For example, an + | API might require a version number using Accept headers to route the HTTP request to the correct codebase. + | + */ + + 'headers' => [ + // 'Accept' => 'application/vnd.com.whatever.v1+json', + ], + + /* + |------------------------------------------------------------------------------------------------------------------ + | Server-Timing + |------------------------------------------------------------------------------------------------------------------ + | + | Clockwork supports the W3C Server Timing specification, which allows for collecting a simple performance metrics + | in a cross-browser way. Eg. in Chrome, your app, database and timeline event timings will be shown in the Dev + | Tools network tab. This setting specifies the max number of timeline events that will be sent. Setting to false + | will disable the feature. + | + */ + + 'server_timing' => 10, ]; diff --git a/app/Config/filesystems.php b/app/Config/filesystems.php index 4d59ba919..493d53bfa 100644 --- a/app/Config/filesystems.php +++ b/app/Config/filesystems.php @@ -30,8 +30,8 @@ return [ 'disks' => [ 'local' => [ - 'driver' => 'local', - 'root' => public_path(), + 'driver' => 'local', + 'root' => public_path(), 'visibility' => 'public', ], @@ -41,8 +41,8 @@ return [ ], 'local_secure_images' => [ - 'driver' => 'local', - 'root' => storage_path('uploads/images/'), + 'driver' => 'local', + 'root' => storage_path('uploads/images/'), 'visibility' => 'public', ], diff --git a/app/Http/Middleware/RedirectIfAuthenticated.php b/app/Http/Middleware/RedirectIfAuthenticated.php index 76e64a3b9..ee7fe880c 100644 --- a/app/Http/Middleware/RedirectIfAuthenticated.php +++ b/app/Http/Middleware/RedirectIfAuthenticated.php @@ -12,9 +12,10 @@ class RedirectIfAuthenticated /** * Handle an incoming request. * - * @param \Illuminate\Http\Request $request - * @param \Closure $next - * @param string|null ...$guards + * @param \Illuminate\Http\Request $request + * @param \Closure $next + * @param string|null ...$guards + * * @return mixed */ public function handle(Request $request, Closure $next, ...$guards) @@ -29,4 +30,4 @@ class RedirectIfAuthenticated return $next($request); } -} \ No newline at end of file +} diff --git a/public/index.php b/public/index.php index c2f34d4bf..fdf6e720f 100644 --- a/public/index.php +++ b/public/index.php @@ -1,7 +1,7 @@ handle( $request = Request::capture() ))->send(); -$kernel->terminate($request, $response); \ No newline at end of file +$kernel->terminate($request, $response); From 0ba854137081ae2f23f0903991c50c1fa6bfb183 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Thu, 4 Nov 2021 23:07:36 +0000 Subject: [PATCH 11/59] Updated npm deps --- package-lock.json | 1246 +++++++++++++++++++++++++++++++++++++-------- package.json | 10 +- 2 files changed, 1049 insertions(+), 207 deletions(-) diff --git a/package-lock.json b/package-lock.json index 97d4d8287..f2013e928 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,19 +6,19 @@ "": { "dependencies": { "clipboard": "^2.0.8", - "codemirror": "^5.62.3", - "dropzone": "^5.9.2", + "codemirror": "^5.63.3", + "dropzone": "^5.9.3", "markdown-it": "^12.2.0", "markdown-it-task-lists": "^2.1.1", "sortablejs": "^1.14.0" }, "devDependencies": { - "chokidar-cli": "^3.0.0", - "esbuild": "0.12.22", + "chokidar-cli": "^3.0", + "esbuild": "0.13.12", "livereload": "^0.9.3", "npm-run-all": "^4.1.5", "punycode": "^2.1.1", - "sass": "^1.38.0" + "sass": "^1.43.4" } }, "node_modules/ansi-regex": { @@ -61,15 +61,15 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, "node_modules/binary-extensions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", - "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true, "engines": { "node": ">=8" @@ -97,6 +97,19 @@ "node": ">=8" } }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", @@ -181,9 +194,9 @@ } }, "node_modules/codemirror": { - "version": "5.62.3", - "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.62.3.tgz", - "integrity": "sha512-zZAyOfN8TU67ngqrxhOgtkSAGV9jSpN1snbl8elPtnh9Z5A11daR405+dhLzLnuXrwX0WCShWlybxPN3QC/9Pg==" + "version": "5.63.3", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.63.3.tgz", + "integrity": "sha512-1C+LELr+5grgJYqwZKqxrcbPsHFHapVaVAloBsFBASbpLnQqLw1U8yXJ3gT5D+rhxIiSpo+kTqN+hQ+9ialIXw==" }, "node_modules/color-convert": { "version": "1.9.3", @@ -249,9 +262,9 @@ "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==" }, "node_modules/dropzone": { - "version": "5.9.2", - "resolved": "https://registry.npmjs.org/dropzone/-/dropzone-5.9.2.tgz", - "integrity": "sha512-5t2z51DzIsWDbTpwcJIvUlwxBbvcwdCApz0yb9ecKJwG155Xm92KMEZmHW1B0MzoXOKvFwdd0nPu5cpeVcvPHQ==" + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/dropzone/-/dropzone-5.9.3.tgz", + "integrity": "sha512-Azk8kD/2/nJIuVPK+zQ9sjKMRIpRvNyqn9XwbBHNq+iNuSccbJS6hwm1Woy0pMST0erSo0u4j+KJaodndDk4vA==" }, "node_modules/emoji-regex": { "version": "7.0.3", @@ -277,25 +290,37 @@ } }, "node_modules/es-abstract": { - "version": "1.17.6", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", - "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz", + "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==", "dev": true, "dependencies": { + "call-bind": "^1.0.2", "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", + "get-symbol-description": "^1.0.0", "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-regex": "^1.1.0", - "object-inspect": "^1.7.0", + "has-symbols": "^1.0.2", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.4", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.1", + "is-string": "^1.0.7", + "is-weakref": "^1.0.1", + "object-inspect": "^1.11.0", "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.1" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/es-to-primitive": { @@ -310,18 +335,261 @@ }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/esbuild": { - "version": "0.12.22", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.12.22.tgz", - "integrity": "sha512-yWCr9RoFehpqoe/+MwZXJpYOEIt7KOEvNnjIeMZpMSyQt+KCBASM3y7yViiN5dJRphf1wGdUz1+M4rTtWd/ulA==", + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.13.12.tgz", + "integrity": "sha512-vTKKUt+yoz61U/BbrnmlG9XIjwpdIxmHB8DlPR0AAW6OdS+nBQBci6LUHU2q9WbBobMEIQxxDpKbkmOGYvxsow==", "dev": true, "hasInstallScript": true, "bin": { "esbuild": "bin/esbuild" + }, + "optionalDependencies": { + "esbuild-android-arm64": "0.13.12", + "esbuild-darwin-64": "0.13.12", + "esbuild-darwin-arm64": "0.13.12", + "esbuild-freebsd-64": "0.13.12", + "esbuild-freebsd-arm64": "0.13.12", + "esbuild-linux-32": "0.13.12", + "esbuild-linux-64": "0.13.12", + "esbuild-linux-arm": "0.13.12", + "esbuild-linux-arm64": "0.13.12", + "esbuild-linux-mips64le": "0.13.12", + "esbuild-linux-ppc64le": "0.13.12", + "esbuild-netbsd-64": "0.13.12", + "esbuild-openbsd-64": "0.13.12", + "esbuild-sunos-64": "0.13.12", + "esbuild-windows-32": "0.13.12", + "esbuild-windows-64": "0.13.12", + "esbuild-windows-arm64": "0.13.12" } }, + "node_modules/esbuild-android-arm64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.13.12.tgz", + "integrity": "sha512-TSVZVrb4EIXz6KaYjXfTzPyyRpXV5zgYIADXtQsIenjZ78myvDGaPi11o4ZSaHIwFHsuwkB6ne5SZRBwAQ7maw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/esbuild-darwin-64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.13.12.tgz", + "integrity": "sha512-c51C+N+UHySoV2lgfWSwwmlnLnL0JWj/LzuZt9Ltk9ub1s2Y8cr6SQV5W3mqVH1egUceew6KZ8GyI4nwu+fhsw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/esbuild-darwin-arm64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.13.12.tgz", + "integrity": "sha512-JvAMtshP45Hd8A8wOzjkY1xAnTKTYuP/QUaKp5eUQGX+76GIie3fCdUUr2ZEKdvpSImNqxiZSIMziEiGB5oUmQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/esbuild-freebsd-64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.13.12.tgz", + "integrity": "sha512-r6On/Skv9f0ZjTu6PW5o7pdXr8aOgtFOEURJZYf1XAJs0IQ+gW+o1DzXjVkIoT+n1cm3N/t1KRJfX71MPg/ZUA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/esbuild-freebsd-arm64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.13.12.tgz", + "integrity": "sha512-F6LmI2Q1gii073kmBE3NOTt/6zLL5zvZsxNLF8PMAwdHc+iBhD1vzfI8uQZMJA1IgXa3ocr3L3DJH9fLGXy6Yw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/esbuild-linux-32": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.13.12.tgz", + "integrity": "sha512-U1UZwG3UIwF7/V4tCVAo/nkBV9ag5KJiJTt+gaCmLVWH3bPLX7y+fNlhIWZy8raTMnXhMKfaTvWZ9TtmXzvkuQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/esbuild-linux-64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.13.12.tgz", + "integrity": "sha512-YpXSwtu2NxN3N4ifJxEdsgd6Q5d8LYqskrAwjmoCT6yQnEHJSF5uWcxv783HWN7lnGpJi9KUtDvYsnMdyGw71Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/esbuild-linux-arm": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.13.12.tgz", + "integrity": "sha512-SyiT/JKxU6J+DY2qUiSLZJqCAftIt3uoGejZ0HDnUM2MGJqEGSGh7p1ecVL2gna3PxS4P+j6WAehCwgkBPXNIw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/esbuild-linux-arm64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.13.12.tgz", + "integrity": "sha512-sgDNb8kb3BVodtAlcFGgwk+43KFCYjnFOaOfJibXnnIojNWuJHpL6aQJ4mumzNWw8Rt1xEtDQyuGK9f+Y24jGA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/esbuild-linux-mips64le": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.13.12.tgz", + "integrity": "sha512-qQJHlZBG+QwVIA8AbTEtbvF084QgDi4DaUsUnA+EolY1bxrG+UyOuGflM2ZritGhfS/k7THFjJbjH2wIeoKA2g==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/esbuild-linux-ppc64le": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.13.12.tgz", + "integrity": "sha512-2dSnm1ldL7Lppwlo04CGQUpwNn5hGqXI38OzaoPOkRsBRWFBozyGxTFSee/zHFS+Pdh3b28JJbRK3owrrRgWNw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/esbuild-netbsd-64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.13.12.tgz", + "integrity": "sha512-D4raxr02dcRiQNbxOLzpqBzcJNFAdsDNxjUbKkDMZBkL54Z0vZh4LRndycdZAMcIdizC/l/Yp/ZsBdAFxc5nbA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ] + }, + "node_modules/esbuild-openbsd-64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.13.12.tgz", + "integrity": "sha512-KuLCmYMb2kh05QuPJ+va60bKIH5wHL8ypDkmpy47lzwmdxNsuySeCMHuTv5o2Af1RUn5KLO5ZxaZeq4GEY7DaQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/esbuild-sunos-64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.13.12.tgz", + "integrity": "sha512-jBsF+e0woK3miKI8ufGWKG3o3rY9DpHvCVRn5eburMIIE+2c+y3IZ1srsthKyKI6kkXLvV4Cf/E7w56kLipMXw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ] + }, + "node_modules/esbuild-windows-32": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.13.12.tgz", + "integrity": "sha512-L9m4lLFQrFeR7F+eLZXG82SbXZfUhyfu6CexZEil6vm+lc7GDCE0Q8DiNutkpzjv1+RAbIGVva9muItQ7HVTkQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/esbuild-windows-64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.13.12.tgz", + "integrity": "sha512-k4tX4uJlSbSkfs78W5d9+I9gpd+7N95W7H2bgOMFPsYREVJs31+Q2gLLHlsnlY95zBoPQMIzHooUIsixQIBjaQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/esbuild-windows-arm64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.13.12.tgz", + "integrity": "sha512-2tTv/BpYRIvuwHpp2M960nG7uvL+d78LFW/ikPItO+2GfK51CswIKSetSpDii+cjz8e9iSPgs+BU4o8nWICBwQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -384,6 +652,36 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", @@ -405,9 +703,9 @@ } }, "node_modules/graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", "dev": true }, "node_modules/has": { @@ -422,6 +720,15 @@ "node": ">= 0.4.0" } }, + "node_modules/has-bigints": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", + "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -432,12 +739,30 @@ } }, "node_modules/has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", "dev": true, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/hosted-git-info": { @@ -446,12 +771,38 @@ "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true }, + "node_modules/internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "dev": true }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -464,22 +815,59 @@ "node": ">=8" } }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-callable": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz", - "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", "dev": true, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz", + "integrity": "sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-extglob": { @@ -501,9 +889,9 @@ } }, "node_modules/is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, "dependencies": { "is-extglob": "^2.1.1" @@ -512,6 +900,18 @@ "node": ">=0.10.0" } }, + "node_modules/is-negative-zero": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", + "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -521,28 +921,86 @@ "node": ">=0.12.0" } }, - "node_modules/is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "node_modules/is-number-object": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", + "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", "dev": true, "dependencies": { - "has-symbols": "^1.0.1" + "has-tostringtag": "^1.0.0" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz", + "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", "dev": true, "dependencies": { - "has-symbols": "^1.0.1" + "has-symbols": "^1.0.2" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.1.tgz", + "integrity": "sha512-b2jKc2pQZjaeFYWEf7ScFj+Be1I+PXmlu572Q8coTXZ+LD/QQZ7ShPMst8h16riVgyXTQwUsFEl74mDvc/3MHQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/isexe": { @@ -558,9 +1016,9 @@ "dev": true }, "node_modules/linkify-it": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.2.tgz", - "integrity": "sha512-gDBO4aHNZS6coiZCKVhSNh43F9ioIL4JwRjLZPkoLIY4yZFwg264Y5lu2x6rb1Js42Gh6Yqm2f6L2AJcnkzinQ==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", + "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", "dependencies": { "uc.micro": "^1.0.1" } @@ -728,10 +1186,13 @@ } }, "node_modules/object-inspect": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", - "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", - "dev": true + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.0.tgz", + "integrity": "sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/object-keys": { "version": "1.1.1", @@ -743,18 +1204,21 @@ } }, "node_modules/object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", "dev": true, "dependencies": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/opts": { @@ -773,6 +1237,9 @@ }, "engines": { "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-locate": { @@ -846,12 +1313,15 @@ } }, "node_modules/picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", "dev": true, "engines": { "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/pidtree": { @@ -926,18 +1396,22 @@ "dev": true }, "node_modules/resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", "dev": true, "dependencies": { + "is-core-module": "^2.2.0", "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/sass": { - "version": "1.38.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.38.0.tgz", - "integrity": "sha512-WBccZeMigAGKoI+NgD7Adh0ab1HUq+6BmyBUEaGxtErbUtWUevEbdgo5EZiJQofLUGcKtlNaO2IdN73AHEua5g==", + "version": "1.43.4", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.43.4.tgz", + "integrity": "sha512-/ptG7KE9lxpGSYiXn7Ar+lKOv37xfWsZRtFYal2QHNigyVQDx685VFT/h7ejVr+R8w7H4tmUgtulsKl5YpveOg==", "dev": true, "dependencies": { "chokidar": ">=3.0.0 <4.0.0" @@ -991,11 +1465,25 @@ } }, "node_modules/shell-quote": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz", - "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==", + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz", + "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==", "dev": true }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/sortablejs": { "version": "1.14.0", "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.14.0.tgz", @@ -1028,9 +1516,9 @@ } }, "node_modules/spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz", + "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==", "dev": true }, "node_modules/string-width": { @@ -1048,36 +1536,46 @@ } }, "node_modules/string.prototype.padend": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.0.tgz", - "integrity": "sha512-3aIv8Ffdp8EZj8iLwREGpQaUZiPyrWrpzMBHvkiSW/bK/EGve9np07Vwy7IJ5waydpGXzQZu/F8Oze2/IWkBaA==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.3.tgz", + "integrity": "sha512-jNIIeokznm8SD/TZISQsZKYu7RJyheFNt84DUPrh482GC8RVp2MKqm2O5oBRdGxbDQoXrhhWtPIWQOiy20svUg==", "dev": true, "dependencies": { + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" + "es-abstract": "^1.19.1" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/string.prototype.trimend": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", - "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", "dev": true, "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/string.prototype.trimstart": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", - "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", "dev": true, "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/strip-ansi": { @@ -1135,6 +1633,21 @@ "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==" }, + "node_modules/unbox-primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", + "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has-bigints": "^1.0.1", + "has-symbols": "^1.0.2", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -1157,6 +1670,22 @@ "which": "bin/which" } }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", @@ -1178,9 +1707,9 @@ } }, "node_modules/ws": { - "version": "7.4.6", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", - "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.5.tgz", + "integrity": "sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==", "dev": true, "engines": { "node": ">=8.3.0" @@ -1199,9 +1728,9 @@ } }, "node_modules/y18n": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", - "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", "dev": true }, "node_modules/yargs": { @@ -1265,15 +1794,15 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, "binary-extensions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", - "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true }, "brace-expansion": { @@ -1295,6 +1824,16 @@ "fill-range": "^7.0.1" } }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, "camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", @@ -1362,9 +1901,9 @@ } }, "codemirror": { - "version": "5.62.3", - "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.62.3.tgz", - "integrity": "sha512-zZAyOfN8TU67ngqrxhOgtkSAGV9jSpN1snbl8elPtnh9Z5A11daR405+dhLzLnuXrwX0WCShWlybxPN3QC/9Pg==" + "version": "5.63.3", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.63.3.tgz", + "integrity": "sha512-1C+LELr+5grgJYqwZKqxrcbPsHFHapVaVAloBsFBASbpLnQqLw1U8yXJ3gT5D+rhxIiSpo+kTqN+hQ+9ialIXw==" }, "color-convert": { "version": "1.9.3", @@ -1421,9 +1960,9 @@ "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==" }, "dropzone": { - "version": "5.9.2", - "resolved": "https://registry.npmjs.org/dropzone/-/dropzone-5.9.2.tgz", - "integrity": "sha512-5t2z51DzIsWDbTpwcJIvUlwxBbvcwdCApz0yb9ecKJwG155Xm92KMEZmHW1B0MzoXOKvFwdd0nPu5cpeVcvPHQ==" + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/dropzone/-/dropzone-5.9.3.tgz", + "integrity": "sha512-Azk8kD/2/nJIuVPK+zQ9sjKMRIpRvNyqn9XwbBHNq+iNuSccbJS6hwm1Woy0pMST0erSo0u4j+KJaodndDk4vA==" }, "emoji-regex": { "version": "7.0.3", @@ -1446,22 +1985,31 @@ } }, "es-abstract": { - "version": "1.17.6", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", - "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz", + "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==", "dev": true, "requires": { + "call-bind": "^1.0.2", "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", + "get-symbol-description": "^1.0.0", "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-regex": "^1.1.0", - "object-inspect": "^1.7.0", + "has-symbols": "^1.0.2", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.4", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.1", + "is-string": "^1.0.7", + "is-weakref": "^1.0.1", + "object-inspect": "^1.11.0", "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.1" } }, "es-to-primitive": { @@ -1476,10 +2024,148 @@ } }, "esbuild": { - "version": "0.12.22", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.12.22.tgz", - "integrity": "sha512-yWCr9RoFehpqoe/+MwZXJpYOEIt7KOEvNnjIeMZpMSyQt+KCBASM3y7yViiN5dJRphf1wGdUz1+M4rTtWd/ulA==", - "dev": true + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.13.12.tgz", + "integrity": "sha512-vTKKUt+yoz61U/BbrnmlG9XIjwpdIxmHB8DlPR0AAW6OdS+nBQBci6LUHU2q9WbBobMEIQxxDpKbkmOGYvxsow==", + "dev": true, + "requires": { + "esbuild-android-arm64": "0.13.12", + "esbuild-darwin-64": "0.13.12", + "esbuild-darwin-arm64": "0.13.12", + "esbuild-freebsd-64": "0.13.12", + "esbuild-freebsd-arm64": "0.13.12", + "esbuild-linux-32": "0.13.12", + "esbuild-linux-64": "0.13.12", + "esbuild-linux-arm": "0.13.12", + "esbuild-linux-arm64": "0.13.12", + "esbuild-linux-mips64le": "0.13.12", + "esbuild-linux-ppc64le": "0.13.12", + "esbuild-netbsd-64": "0.13.12", + "esbuild-openbsd-64": "0.13.12", + "esbuild-sunos-64": "0.13.12", + "esbuild-windows-32": "0.13.12", + "esbuild-windows-64": "0.13.12", + "esbuild-windows-arm64": "0.13.12" + } + }, + "esbuild-android-arm64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.13.12.tgz", + "integrity": "sha512-TSVZVrb4EIXz6KaYjXfTzPyyRpXV5zgYIADXtQsIenjZ78myvDGaPi11o4ZSaHIwFHsuwkB6ne5SZRBwAQ7maw==", + "dev": true, + "optional": true + }, + "esbuild-darwin-64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.13.12.tgz", + "integrity": "sha512-c51C+N+UHySoV2lgfWSwwmlnLnL0JWj/LzuZt9Ltk9ub1s2Y8cr6SQV5W3mqVH1egUceew6KZ8GyI4nwu+fhsw==", + "dev": true, + "optional": true + }, + "esbuild-darwin-arm64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.13.12.tgz", + "integrity": "sha512-JvAMtshP45Hd8A8wOzjkY1xAnTKTYuP/QUaKp5eUQGX+76GIie3fCdUUr2ZEKdvpSImNqxiZSIMziEiGB5oUmQ==", + "dev": true, + "optional": true + }, + "esbuild-freebsd-64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.13.12.tgz", + "integrity": "sha512-r6On/Skv9f0ZjTu6PW5o7pdXr8aOgtFOEURJZYf1XAJs0IQ+gW+o1DzXjVkIoT+n1cm3N/t1KRJfX71MPg/ZUA==", + "dev": true, + "optional": true + }, + "esbuild-freebsd-arm64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.13.12.tgz", + "integrity": "sha512-F6LmI2Q1gii073kmBE3NOTt/6zLL5zvZsxNLF8PMAwdHc+iBhD1vzfI8uQZMJA1IgXa3ocr3L3DJH9fLGXy6Yw==", + "dev": true, + "optional": true + }, + "esbuild-linux-32": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.13.12.tgz", + "integrity": "sha512-U1UZwG3UIwF7/V4tCVAo/nkBV9ag5KJiJTt+gaCmLVWH3bPLX7y+fNlhIWZy8raTMnXhMKfaTvWZ9TtmXzvkuQ==", + "dev": true, + "optional": true + }, + "esbuild-linux-64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.13.12.tgz", + "integrity": "sha512-YpXSwtu2NxN3N4ifJxEdsgd6Q5d8LYqskrAwjmoCT6yQnEHJSF5uWcxv783HWN7lnGpJi9KUtDvYsnMdyGw71Q==", + "dev": true, + "optional": true + }, + "esbuild-linux-arm": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.13.12.tgz", + "integrity": "sha512-SyiT/JKxU6J+DY2qUiSLZJqCAftIt3uoGejZ0HDnUM2MGJqEGSGh7p1ecVL2gna3PxS4P+j6WAehCwgkBPXNIw==", + "dev": true, + "optional": true + }, + "esbuild-linux-arm64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.13.12.tgz", + "integrity": "sha512-sgDNb8kb3BVodtAlcFGgwk+43KFCYjnFOaOfJibXnnIojNWuJHpL6aQJ4mumzNWw8Rt1xEtDQyuGK9f+Y24jGA==", + "dev": true, + "optional": true + }, + "esbuild-linux-mips64le": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.13.12.tgz", + "integrity": "sha512-qQJHlZBG+QwVIA8AbTEtbvF084QgDi4DaUsUnA+EolY1bxrG+UyOuGflM2ZritGhfS/k7THFjJbjH2wIeoKA2g==", + "dev": true, + "optional": true + }, + "esbuild-linux-ppc64le": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.13.12.tgz", + "integrity": "sha512-2dSnm1ldL7Lppwlo04CGQUpwNn5hGqXI38OzaoPOkRsBRWFBozyGxTFSee/zHFS+Pdh3b28JJbRK3owrrRgWNw==", + "dev": true, + "optional": true + }, + "esbuild-netbsd-64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.13.12.tgz", + "integrity": "sha512-D4raxr02dcRiQNbxOLzpqBzcJNFAdsDNxjUbKkDMZBkL54Z0vZh4LRndycdZAMcIdizC/l/Yp/ZsBdAFxc5nbA==", + "dev": true, + "optional": true + }, + "esbuild-openbsd-64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.13.12.tgz", + "integrity": "sha512-KuLCmYMb2kh05QuPJ+va60bKIH5wHL8ypDkmpy47lzwmdxNsuySeCMHuTv5o2Af1RUn5KLO5ZxaZeq4GEY7DaQ==", + "dev": true, + "optional": true + }, + "esbuild-sunos-64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.13.12.tgz", + "integrity": "sha512-jBsF+e0woK3miKI8ufGWKG3o3rY9DpHvCVRn5eburMIIE+2c+y3IZ1srsthKyKI6kkXLvV4Cf/E7w56kLipMXw==", + "dev": true, + "optional": true + }, + "esbuild-windows-32": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.13.12.tgz", + "integrity": "sha512-L9m4lLFQrFeR7F+eLZXG82SbXZfUhyfu6CexZEil6vm+lc7GDCE0Q8DiNutkpzjv1+RAbIGVva9muItQ7HVTkQ==", + "dev": true, + "optional": true + }, + "esbuild-windows-64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.13.12.tgz", + "integrity": "sha512-k4tX4uJlSbSkfs78W5d9+I9gpd+7N95W7H2bgOMFPsYREVJs31+Q2gLLHlsnlY95zBoPQMIzHooUIsixQIBjaQ==", + "dev": true, + "optional": true + }, + "esbuild-windows-arm64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.13.12.tgz", + "integrity": "sha512-2tTv/BpYRIvuwHpp2M960nG7uvL+d78LFW/ikPItO+2GfK51CswIKSetSpDii+cjz8e9iSPgs+BU4o8nWICBwQ==", + "dev": true, + "optional": true }, "escape-string-regexp": { "version": "1.0.5", @@ -1524,6 +2210,27 @@ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true }, + "get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, + "get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + } + }, "glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", @@ -1542,9 +2249,9 @@ } }, "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", "dev": true }, "has": { @@ -1556,6 +2263,12 @@ "function-bind": "^1.1.1" } }, + "has-bigints": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", + "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "dev": true + }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -1563,23 +2276,52 @@ "dev": true }, "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", "dev": true }, + "has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.2" + } + }, "hosted-git-info": { "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true }, + "internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + } + }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "dev": true }, + "is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "requires": { + "has-bigints": "^1.0.1" + } + }, "is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -1589,17 +2331,39 @@ "binary-extensions": "^2.0.0" } }, + "is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, "is-callable": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz", - "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", "dev": true }, + "is-core-module": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz", + "integrity": "sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, "is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", - "dev": true + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } }, "is-extglob": { "version": "2.1.1", @@ -1614,36 +2378,76 @@ "dev": true }, "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, "requires": { "is-extglob": "^2.1.1" } }, + "is-negative-zero": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", + "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", + "dev": true + }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, - "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "is-number-object": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", + "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", "dev": true, "requires": { - "has-symbols": "^1.0.1" + "has-tostringtag": "^1.0.0" + } + }, + "is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-shared-array-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz", + "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==", + "dev": true + }, + "is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" } }, "is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", "dev": true, "requires": { - "has-symbols": "^1.0.1" + "has-symbols": "^1.0.2" + } + }, + "is-weakref": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.1.tgz", + "integrity": "sha512-b2jKc2pQZjaeFYWEf7ScFj+Be1I+PXmlu572Q8coTXZ+LD/QQZ7ShPMst8h16riVgyXTQwUsFEl74mDvc/3MHQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.0" } }, "isexe": { @@ -1659,9 +2463,9 @@ "dev": true }, "linkify-it": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.2.tgz", - "integrity": "sha512-gDBO4aHNZS6coiZCKVhSNh43F9ioIL4JwRjLZPkoLIY4yZFwg264Y5lu2x6rb1Js42Gh6Yqm2f6L2AJcnkzinQ==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", + "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", "requires": { "uc.micro": "^1.0.1" } @@ -1797,9 +2601,9 @@ } }, "object-inspect": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", - "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.0.tgz", + "integrity": "sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg==", "dev": true }, "object-keys": { @@ -1809,15 +2613,15 @@ "dev": true }, "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", "dev": true, "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" } }, "opts": { @@ -1888,9 +2692,9 @@ } }, "picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", "dev": true }, "pidtree": { @@ -1944,18 +2748,19 @@ "dev": true }, "resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", "dev": true, "requires": { + "is-core-module": "^2.2.0", "path-parse": "^1.0.6" } }, "sass": { - "version": "1.38.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.38.0.tgz", - "integrity": "sha512-WBccZeMigAGKoI+NgD7Adh0ab1HUq+6BmyBUEaGxtErbUtWUevEbdgo5EZiJQofLUGcKtlNaO2IdN73AHEua5g==", + "version": "1.43.4", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.43.4.tgz", + "integrity": "sha512-/ptG7KE9lxpGSYiXn7Ar+lKOv37xfWsZRtFYal2QHNigyVQDx685VFT/h7ejVr+R8w7H4tmUgtulsKl5YpveOg==", "dev": true, "requires": { "chokidar": ">=3.0.0 <4.0.0" @@ -1994,11 +2799,22 @@ "dev": true }, "shell-quote": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz", - "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==", + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz", + "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==", "dev": true }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, "sortablejs": { "version": "1.14.0", "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.14.0.tgz", @@ -2031,9 +2847,9 @@ } }, "spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz", + "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==", "dev": true }, "string-width": { @@ -2048,33 +2864,34 @@ } }, "string.prototype.padend": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.0.tgz", - "integrity": "sha512-3aIv8Ffdp8EZj8iLwREGpQaUZiPyrWrpzMBHvkiSW/bK/EGve9np07Vwy7IJ5waydpGXzQZu/F8Oze2/IWkBaA==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.3.tgz", + "integrity": "sha512-jNIIeokznm8SD/TZISQsZKYu7RJyheFNt84DUPrh482GC8RVp2MKqm2O5oBRdGxbDQoXrhhWtPIWQOiy20svUg==", "dev": true, "requires": { + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" + "es-abstract": "^1.19.1" } }, "string.prototype.trimend": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", - "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", "dev": true, "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" } }, "string.prototype.trimstart": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", - "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", "dev": true, "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" } }, "strip-ansi": { @@ -2120,6 +2937,18 @@ "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==" }, + "unbox-primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", + "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has-bigints": "^1.0.1", + "has-symbols": "^1.0.2", + "which-boxed-primitive": "^1.0.2" + } + }, "validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -2139,6 +2968,19 @@ "isexe": "^2.0.0" } }, + "which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "requires": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + }, "which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", @@ -2157,16 +2999,16 @@ } }, "ws": { - "version": "7.4.6", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", - "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.5.tgz", + "integrity": "sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==", "dev": true, "requires": {} }, "y18n": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", - "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", "dev": true }, "yargs": { diff --git a/package.json b/package.json index d2740cd81..fe3837a86 100644 --- a/package.json +++ b/package.json @@ -15,17 +15,17 @@ "permissions": "chown -R $USER:$USER bootstrap/cache storage public/uploads" }, "devDependencies": { - "chokidar-cli": "^3.0.0", - "esbuild": "0.12.22", + "chokidar-cli": "^3.0", + "esbuild": "0.13.12", "livereload": "^0.9.3", "npm-run-all": "^4.1.5", "punycode": "^2.1.1", - "sass": "^1.38.0" + "sass": "^1.43.4" }, "dependencies": { "clipboard": "^2.0.8", - "codemirror": "^5.62.3", - "dropzone": "^5.9.2", + "codemirror": "^5.63.3", + "dropzone": "^5.9.3", "markdown-it": "^12.2.0", "markdown-it-task-lists": "^2.1.1", "sortablejs": "^1.14.0" From 06b500984250f75b98f38a8f25ac953cb45aeee4 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Fri, 5 Nov 2021 00:26:55 +0000 Subject: [PATCH 12/59] Standardised laravel validation to be array based Converted from string-only-based validation. Array based validation works nicer once you have validation classess or advanced validation options. --- app/Api/ApiDocsGenerator.php | 8 ++----- .../Api/AttachmentApiController.php | 16 ++++++------- .../Controllers/Api/BookApiController.php | 12 +++++----- .../Api/BookshelfApiController.php | 12 +++++----- .../Controllers/Api/ChapterApiController.php | 16 ++++++------- .../Controllers/Api/PageApiController.php | 24 +++++++++---------- app/Http/Controllers/AttachmentController.php | 18 +++++++------- .../Auth/ConfirmEmailController.php | 2 +- .../Auth/ForgotPasswordController.php | 4 +++- app/Http/Controllers/Auth/LoginController.php | 8 +++---- .../Auth/MfaBackupCodesController.php | 3 +-- .../Controllers/Auth/RegisterController.php | 6 ++--- .../Controllers/Auth/UserInviteController.php | 2 +- app/Http/Controllers/BookController.php | 12 +++++----- app/Http/Controllers/BookshelfController.php | 12 +++++----- app/Http/Controllers/ChapterController.php | 2 +- app/Http/Controllers/CommentController.php | 6 ++--- app/Http/Controllers/Controller.php | 4 ++-- app/Http/Controllers/FavouriteController.php | 4 ++-- .../Images/DrawioImageController.php | 4 ++-- .../Controllers/Images/ImageController.php | 2 +- app/Http/Controllers/PageController.php | 6 ++--- app/Http/Controllers/RoleController.php | 4 ++-- app/Http/Controllers/SettingController.php | 2 +- .../Controllers/UserApiTokenController.php | 8 +++---- app/Http/Controllers/UserController.php | 18 +++++++------- 26 files changed, 106 insertions(+), 109 deletions(-) diff --git a/app/Api/ApiDocsGenerator.php b/app/Api/ApiDocsGenerator.php index 0ed7e6712..3aabfb4cc 100644 --- a/app/Api/ApiDocsGenerator.php +++ b/app/Api/ApiDocsGenerator.php @@ -95,17 +95,13 @@ class ApiDocsGenerator } $rules = $class->getValdationRules()[$methodName] ?? []; - foreach ($rules as $param => $ruleString) { - $rules[$param] = explode('|', $ruleString); - } - - return count($rules) > 0 ? $rules : null; + return empty($rules) ? null : $rules; } /** * Parse out the description text from a class method comment. */ - protected function parseDescriptionFromMethodComment(string $comment) + protected function parseDescriptionFromMethodComment(string $comment): string { $matches = []; preg_match_all('/^\s*?\*\s((?![@\s]).*?)$/m', $comment, $matches); diff --git a/app/Http/Controllers/Api/AttachmentApiController.php b/app/Http/Controllers/Api/AttachmentApiController.php index 06d9f6907..67815bc47 100644 --- a/app/Http/Controllers/Api/AttachmentApiController.php +++ b/app/Http/Controllers/Api/AttachmentApiController.php @@ -17,16 +17,16 @@ class AttachmentApiController extends ApiController protected $rules = [ 'create' => [ - 'name' => 'required|min:1|max:255|string', - 'uploaded_to' => 'required|integer|exists:pages,id', - 'file' => 'required_without:link|file', - 'link' => 'required_without:file|min:1|max:255|safe_url', + 'name' => ['required', 'min:1', 'max:255', 'string'], + 'uploaded_to' => ['required', 'integer', 'exists:pages,id'], + 'file' => ['required_without:link', 'file'], + 'link' => ['required_without:file', 'min:1', 'max:255', 'safe_url'], ], 'update' => [ - 'name' => 'min:1|max:255|string', - 'uploaded_to' => 'integer|exists:pages,id', - 'file' => 'file', - 'link' => 'min:1|max:255|safe_url', + 'name' => ['min:1', 'max:255', 'string'], + 'uploaded_to' => ['integer', 'exists:pages,id'], + 'file' => ['file'], + 'link' => ['min:1', 'max:255', 'safe_url'], ], ]; diff --git a/app/Http/Controllers/Api/BookApiController.php b/app/Http/Controllers/Api/BookApiController.php index abe23f45d..b28e3eefa 100644 --- a/app/Http/Controllers/Api/BookApiController.php +++ b/app/Http/Controllers/Api/BookApiController.php @@ -13,14 +13,14 @@ class BookApiController extends ApiController protected $rules = [ 'create' => [ - 'name' => 'required|string|max:255', - 'description' => 'string|max:1000', - 'tags' => 'array', + 'name' => ['required', 'string', 'max:255'], + 'description' => ['string', 'max:1000'], + 'tags' => ['array'], ], 'update' => [ - 'name' => 'string|min:1|max:255', - 'description' => 'string|max:1000', - 'tags' => 'array', + 'name' => ['string', 'min:1', 'max:255'], + 'description' => ['string', 'max:1000'], + 'tags' => ['array'], ], ]; diff --git a/app/Http/Controllers/Api/BookshelfApiController.php b/app/Http/Controllers/Api/BookshelfApiController.php index c29e5b0ae..de7284e61 100644 --- a/app/Http/Controllers/Api/BookshelfApiController.php +++ b/app/Http/Controllers/Api/BookshelfApiController.php @@ -18,14 +18,14 @@ class BookshelfApiController extends ApiController protected $rules = [ 'create' => [ - 'name' => 'required|string|max:255', - 'description' => 'string|max:1000', - 'books' => 'array', + 'name' => ['required', 'string', 'max:255'], + 'description' => ['string', 'max:1000'], + 'books' => ['array'], ], 'update' => [ - 'name' => 'string|min:1|max:255', - 'description' => 'string|max:1000', - 'books' => 'array', + 'name' => ['string', 'min:1', 'max:255'], + 'description' => ['string', 'max:1000'], + 'books' => ['array'], ], ]; diff --git a/app/Http/Controllers/Api/ChapterApiController.php b/app/Http/Controllers/Api/ChapterApiController.php index 13b3f9821..6b226b5f0 100644 --- a/app/Http/Controllers/Api/ChapterApiController.php +++ b/app/Http/Controllers/Api/ChapterApiController.php @@ -14,16 +14,16 @@ class ChapterApiController extends ApiController protected $rules = [ 'create' => [ - 'book_id' => 'required|integer', - 'name' => 'required|string|max:255', - 'description' => 'string|max:1000', - 'tags' => 'array', + 'book_id' => ['required', 'integer'], + 'name' => ['required', 'string', 'max:255'], + 'description' => ['string', 'max:1000'], + 'tags' => ['array'], ], 'update' => [ - 'book_id' => 'integer', - 'name' => 'string|min:1|max:255', - 'description' => 'string|max:1000', - 'tags' => 'array', + 'book_id' => ['integer'], + 'name' => ['string', 'min:1', 'max:255'], + 'description' => ['string', 'max:1000'], + 'tags' => ['array'], ], ]; diff --git a/app/Http/Controllers/Api/PageApiController.php b/app/Http/Controllers/Api/PageApiController.php index f698627a7..6f3a71e02 100644 --- a/app/Http/Controllers/Api/PageApiController.php +++ b/app/Http/Controllers/Api/PageApiController.php @@ -16,20 +16,20 @@ class PageApiController extends ApiController protected $rules = [ 'create' => [ - 'book_id' => 'required_without:chapter_id|integer', - 'chapter_id' => 'required_without:book_id|integer', - 'name' => 'required|string|max:255', - 'html' => 'required_without:markdown|string', - 'markdown' => 'required_without:html|string', - 'tags' => 'array', + 'book_id' => ['required_without:chapter_id', 'integer'], + 'chapter_id' => ['required_without:book_id', 'integer'], + 'name' => ['required', 'string', 'max:255'], + 'html' => ['required_without:markdown', 'string'], + 'markdown' => ['required_without:html', 'string'], + 'tags' => ['array'], ], 'update' => [ - 'book_id' => 'required|integer', - 'chapter_id' => 'required|integer', - 'name' => 'string|min:1|max:255', - 'html' => 'string', - 'markdown' => 'string', - 'tags' => 'array', + 'book_id' => ['required', 'integer'], + 'chapter_id' => ['required', 'integer'], + 'name' => ['string', 'min:1', 'max:255'], + 'html' => ['string'], + 'markdown' => ['string'], + 'tags' => ['array'], ], ]; diff --git a/app/Http/Controllers/AttachmentController.php b/app/Http/Controllers/AttachmentController.php index c08247dad..ec9872bcf 100644 --- a/app/Http/Controllers/AttachmentController.php +++ b/app/Http/Controllers/AttachmentController.php @@ -36,8 +36,8 @@ class AttachmentController extends Controller public function upload(Request $request) { $this->validate($request, [ - 'uploaded_to' => 'required|integer|exists:pages,id', - 'file' => 'required|file', + 'uploaded_to' => ['required', 'integer', 'exists:pages,id'], + 'file' => ['required', 'file'], ]); $pageId = $request->get('uploaded_to'); @@ -65,7 +65,7 @@ class AttachmentController extends Controller public function uploadUpdate(Request $request, $attachmentId) { $this->validate($request, [ - 'file' => 'required|file', + 'file' => ['required', 'file'], ]); /** @var Attachment $attachment */ @@ -111,8 +111,8 @@ class AttachmentController extends Controller try { $this->validate($request, [ - 'attachment_edit_name' => 'required|string|min:1|max:255', - 'attachment_edit_url' => 'string|min:1|max:255|safe_url', + 'attachment_edit_name' => ['required', 'string', 'min:1', 'max:255'], + 'attachment_edit_url' => ['string', 'min:1', 'max:255', 'safe_url'], ]); } catch (ValidationException $exception) { return response()->view('attachments.manager-edit-form', array_merge($request->only(['attachment_edit_name', 'attachment_edit_url']), [ @@ -146,9 +146,9 @@ class AttachmentController extends Controller try { $this->validate($request, [ - 'attachment_link_uploaded_to' => 'required|integer|exists:pages,id', - 'attachment_link_name' => 'required|string|min:1|max:255', - 'attachment_link_url' => 'required|string|min:1|max:255|safe_url', + 'attachment_link_uploaded_to' => ['required', 'integer', 'exists:pages,id'], + 'attachment_link_name' => ['required', 'string', 'min:1', 'max:255'], + 'attachment_link_url' => ['required', 'string', 'min:1', 'max:255', 'safe_url'], ]); } catch (ValidationException $exception) { return response()->view('attachments.manager-link-form', array_merge($request->only(['attachment_link_name', 'attachment_link_url']), [ @@ -195,7 +195,7 @@ class AttachmentController extends Controller public function sortForPage(Request $request, int $pageId) { $this->validate($request, [ - 'order' => 'required|array', + 'order' => ['required', 'array'], ]); $page = $this->pageRepo->getById($pageId); $this->checkOwnablePermission('page-update', $page); diff --git a/app/Http/Controllers/Auth/ConfirmEmailController.php b/app/Http/Controllers/Auth/ConfirmEmailController.php index 02b9ef276..c5466aecd 100644 --- a/app/Http/Controllers/Auth/ConfirmEmailController.php +++ b/app/Http/Controllers/Auth/ConfirmEmailController.php @@ -107,7 +107,7 @@ class ConfirmEmailController extends Controller public function resend(Request $request) { $this->validate($request, [ - 'email' => 'required|email|exists:users,email', + 'email' => ['required', 'email', 'exists:users,email'], ]); $user = $this->userRepo->getByEmail($request->get('email')); diff --git a/app/Http/Controllers/Auth/ForgotPasswordController.php b/app/Http/Controllers/Auth/ForgotPasswordController.php index 8eaee08a2..212bb6ab1 100644 --- a/app/Http/Controllers/Auth/ForgotPasswordController.php +++ b/app/Http/Controllers/Auth/ForgotPasswordController.php @@ -43,7 +43,9 @@ class ForgotPasswordController extends Controller */ public function sendResetLinkEmail(Request $request) { - $this->validate($request, ['email' => 'required|email']); + $this->validate($request, [ + 'email' => ['required', 'email'] + ]); // We will send the password reset link to this user. Once we have attempted // to send the link, we will examine the response then see the message we diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index d12d7c9bc..427d88a02 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -176,16 +176,16 @@ class LoginController extends Controller */ protected function validateLogin(Request $request) { - $rules = ['password' => 'required|string']; + $rules = ['password' => ['required', 'string']]; $authMethod = config('auth.method'); if ($authMethod === 'standard') { - $rules['email'] = 'required|email'; + $rules['email'] = ['required', 'email']; } if ($authMethod === 'ldap') { - $rules['username'] = 'required|string'; - $rules['email'] = 'email'; + $rules['username'] = ['required', 'string']; + $rules['email'] = ['email']; } $request->validate($rules); diff --git a/app/Http/Controllers/Auth/MfaBackupCodesController.php b/app/Http/Controllers/Auth/MfaBackupCodesController.php index d92029bf1..e24090022 100644 --- a/app/Http/Controllers/Auth/MfaBackupCodesController.php +++ b/app/Http/Controllers/Auth/MfaBackupCodesController.php @@ -73,8 +73,7 @@ class MfaBackupCodesController extends Controller $this->validate($request, [ 'code' => [ - 'required', - 'max:12', 'min:8', + 'required', 'max:12', 'min:8', function ($attribute, $value, $fail) use ($codeService, $codes) { if (!$codeService->inputCodeExistsInSet($value, $codes)) { $fail(trans('validation.backup_codes')); diff --git a/app/Http/Controllers/Auth/RegisterController.php b/app/Http/Controllers/Auth/RegisterController.php index 209827d6d..d4e7fcb8e 100644 --- a/app/Http/Controllers/Auth/RegisterController.php +++ b/app/Http/Controllers/Auth/RegisterController.php @@ -68,9 +68,9 @@ class RegisterController extends Controller protected function validator(array $data) { return Validator::make($data, [ - 'name' => 'required|min:2|max:255', - 'email' => 'required|email|max:255|unique:users', - 'password' => 'required|min:8', + 'name' => ['required', 'min:2', 'max:255'], + 'email' => ['required', 'email', 'max:255', 'unique:users'], + 'password' => ['required', 'min:8'], ]); } diff --git a/app/Http/Controllers/Auth/UserInviteController.php b/app/Http/Controllers/Auth/UserInviteController.php index bd1912b0b..b3ccf072a 100644 --- a/app/Http/Controllers/Auth/UserInviteController.php +++ b/app/Http/Controllers/Auth/UserInviteController.php @@ -58,7 +58,7 @@ class UserInviteController extends Controller public function setPassword(Request $request, string $token) { $this->validate($request, [ - 'password' => 'required|min:8', + 'password' => ['required', 'min:8'], ]); try { diff --git a/app/Http/Controllers/BookController.php b/app/Http/Controllers/BookController.php index 7c099377c..af44a6689 100644 --- a/app/Http/Controllers/BookController.php +++ b/app/Http/Controllers/BookController.php @@ -85,9 +85,9 @@ class BookController extends Controller { $this->checkPermission('book-create-all'); $this->validate($request, [ - 'name' => 'required|string|max:255', - 'description' => 'string|max:1000', - 'image' => 'nullable|' . $this->getImageValidationRules(), + 'name' => ['required', 'string', 'max:255'], + 'description' => ['string', 'max:1000'], + 'image' => array_merge(['nullable'], $this->getImageValidationRules()), ]); $bookshelf = null; @@ -156,9 +156,9 @@ class BookController extends Controller $book = $this->bookRepo->getBySlug($slug); $this->checkOwnablePermission('book-update', $book); $this->validate($request, [ - 'name' => 'required|string|max:255', - 'description' => 'string|max:1000', - 'image' => 'nullable|' . $this->getImageValidationRules(), + 'name' => ['required', 'string', 'max:255'], + 'description' => ['string', 'max:1000'], + 'image' => array_merge(['nullable'], $this->getImageValidationRules()), ]); $book = $this->bookRepo->update($book, $request->all()); diff --git a/app/Http/Controllers/BookshelfController.php b/app/Http/Controllers/BookshelfController.php index da16d7822..32248ee46 100644 --- a/app/Http/Controllers/BookshelfController.php +++ b/app/Http/Controllers/BookshelfController.php @@ -84,9 +84,9 @@ class BookshelfController extends Controller { $this->checkPermission('bookshelf-create-all'); $this->validate($request, [ - 'name' => 'required|string|max:255', - 'description' => 'string|max:1000', - 'image' => 'nullable|' . $this->getImageValidationRules(), + 'name' => ['required', 'string', 'max:255'], + 'description' => ['string', 'max:1000'], + 'image' => array_merge(['nullable'], $this->getImageValidationRules()), ]); $bookIds = explode(',', $request->get('books', '')); @@ -161,9 +161,9 @@ class BookshelfController extends Controller $shelf = $this->bookshelfRepo->getBySlug($slug); $this->checkOwnablePermission('bookshelf-update', $shelf); $this->validate($request, [ - 'name' => 'required|string|max:255', - 'description' => 'string|max:1000', - 'image' => 'nullable|' . $this->getImageValidationRules(), + 'name' => ['required', 'string', 'max:255'], + 'description' => ['string', 'max:1000'], + 'image' => array_merge(['nullable'], $this->getImageValidationRules()), ]); $bookIds = explode(',', $request->get('books', '')); diff --git a/app/Http/Controllers/ChapterController.php b/app/Http/Controllers/ChapterController.php index b27fb4f77..9d2bd2489 100644 --- a/app/Http/Controllers/ChapterController.php +++ b/app/Http/Controllers/ChapterController.php @@ -47,7 +47,7 @@ class ChapterController extends Controller public function store(Request $request, string $bookSlug) { $this->validate($request, [ - 'name' => 'required|string|max:255', + 'name' => ['required', 'string', 'max:255'], ]); $book = Book::visible()->where('slug', '=', $bookSlug)->firstOrFail(); diff --git a/app/Http/Controllers/CommentController.php b/app/Http/Controllers/CommentController.php index dfe468f5f..9804f6d39 100644 --- a/app/Http/Controllers/CommentController.php +++ b/app/Http/Controllers/CommentController.php @@ -24,8 +24,8 @@ class CommentController extends Controller public function savePageComment(Request $request, int $pageId) { $this->validate($request, [ - 'text' => 'required|string', - 'parent_id' => 'nullable|integer', + 'text' => ['required', 'string'], + 'parent_id' => ['nullable', 'integer'], ]); $page = Page::visible()->find($pageId); @@ -53,7 +53,7 @@ class CommentController extends Controller public function update(Request $request, int $commentId) { $this->validate($request, [ - 'text' => 'required|string', + 'text' => ['required', 'string'], ]); $comment = $this->commentRepo->getById($commentId); diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index d63280a23..df450d051 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -175,8 +175,8 @@ abstract class Controller extends BaseController /** * Get the validation rules for image files. */ - protected function getImageValidationRules(): string + protected function getImageValidationRules(): array { - return 'image_extension|mimes:jpeg,png,gif,webp'; + return ['image_extension', 'mimes:jpeg,png,gif,webp']; } } diff --git a/app/Http/Controllers/FavouriteController.php b/app/Http/Controllers/FavouriteController.php index a990ff825..c8ba3078c 100644 --- a/app/Http/Controllers/FavouriteController.php +++ b/app/Http/Controllers/FavouriteController.php @@ -69,8 +69,8 @@ class FavouriteController extends Controller protected function getValidatedModelFromRequest(Request $request): Favouritable { $modelInfo = $this->validate($request, [ - 'type' => 'required|string', - 'id' => 'required|integer', + 'type' => ['required', 'string'], + 'id' => ['required', 'integer'], ]); if (!class_exists($modelInfo['type'])) { diff --git a/app/Http/Controllers/Images/DrawioImageController.php b/app/Http/Controllers/Images/DrawioImageController.php index b8e4546ff..cab1c925e 100644 --- a/app/Http/Controllers/Images/DrawioImageController.php +++ b/app/Http/Controllers/Images/DrawioImageController.php @@ -44,8 +44,8 @@ class DrawioImageController extends Controller public function create(Request $request) { $this->validate($request, [ - 'image' => 'required|string', - 'uploaded_to' => 'required|integer', + 'image' => ['required', 'string'], + 'uploaded_to' => ['required', 'integer'], ]); $this->checkPermission('image-create-all'); diff --git a/app/Http/Controllers/Images/ImageController.php b/app/Http/Controllers/Images/ImageController.php index 231712d52..21ed58553 100644 --- a/app/Http/Controllers/Images/ImageController.php +++ b/app/Http/Controllers/Images/ImageController.php @@ -51,7 +51,7 @@ class ImageController extends Controller public function update(Request $request, string $id) { $this->validate($request, [ - 'name' => 'required|min:2|string', + 'name' => ['required', 'min:2', 'string'], ]); $image = $this->imageRepo->getById($id); diff --git a/app/Http/Controllers/PageController.php b/app/Http/Controllers/PageController.php index ddb15a7aa..7d5d93ffa 100644 --- a/app/Http/Controllers/PageController.php +++ b/app/Http/Controllers/PageController.php @@ -60,7 +60,7 @@ class PageController extends Controller public function createAsGuest(Request $request, string $bookSlug, string $chapterSlug = null) { $this->validate($request, [ - 'name' => 'required|string|max:255', + 'name' => ['required', 'string', 'max:255'], ]); $parent = $this->pageRepo->getParentFromSlugs($bookSlug, $chapterSlug); @@ -107,7 +107,7 @@ class PageController extends Controller public function store(Request $request, string $bookSlug, int $pageId) { $this->validate($request, [ - 'name' => 'required|string|max:255', + 'name' => ['required', 'string', 'max:255'], ]); $draftPage = $this->pageRepo->getById($pageId); $this->checkOwnablePermission('page-create', $draftPage->getParent()); @@ -234,7 +234,7 @@ class PageController extends Controller public function update(Request $request, string $bookSlug, string $pageSlug) { $this->validate($request, [ - 'name' => 'required|string|max:255', + 'name' => ['required', 'string', 'max:255'], ]); $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug); $this->checkOwnablePermission('page-update', $page); diff --git a/app/Http/Controllers/RoleController.php b/app/Http/Controllers/RoleController.php index 06a30e99d..7ba52d486 100644 --- a/app/Http/Controllers/RoleController.php +++ b/app/Http/Controllers/RoleController.php @@ -48,7 +48,7 @@ class RoleController extends Controller { $this->checkPermission('user-roles-manage'); $this->validate($request, [ - 'display_name' => 'required|min:3|max:180', + 'display_name' => ['required', 'min:3', 'max:180'], 'description' => 'max:180', ]); @@ -83,7 +83,7 @@ class RoleController extends Controller { $this->checkPermission('user-roles-manage'); $this->validate($request, [ - 'display_name' => 'required|min:3|max:180', + 'display_name' => ['required', 'min:3', 'max:180'], 'description' => 'max:180', ]); diff --git a/app/Http/Controllers/SettingController.php b/app/Http/Controllers/SettingController.php index d9f172081..b12b0e3ce 100644 --- a/app/Http/Controllers/SettingController.php +++ b/app/Http/Controllers/SettingController.php @@ -44,7 +44,7 @@ class SettingController extends Controller $this->preventAccessInDemoMode(); $this->checkPermission('settings-manage'); $this->validate($request, [ - 'app_logo' => 'nullable|' . $this->getImageValidationRules(), + 'app_logo' => array_merge(['nullable'], $this->getImageValidationRules()), ]); // Cycles through posted settings and update them diff --git a/app/Http/Controllers/UserApiTokenController.php b/app/Http/Controllers/UserApiTokenController.php index bdc25f79d..b1a043cd3 100644 --- a/app/Http/Controllers/UserApiTokenController.php +++ b/app/Http/Controllers/UserApiTokenController.php @@ -36,8 +36,8 @@ class UserApiTokenController extends Controller $this->checkPermissionOrCurrentUser('users-manage', $userId); $this->validate($request, [ - 'name' => 'required|max:250', - 'expires_at' => 'date_format:Y-m-d', + 'name' => ['required', 'max:250'], + 'expires_at' => ['date_format:Y-m-d'], ]); $user = User::query()->findOrFail($userId); @@ -86,8 +86,8 @@ class UserApiTokenController extends Controller public function update(Request $request, int $userId, int $tokenId) { $this->validate($request, [ - 'name' => 'required|max:250', - 'expires_at' => 'date_format:Y-m-d', + 'name' => ['required', 'max:250'], + 'expires_at' => ['date_format:Y-m-d'], ]); [$user, $token] = $this->checkPermissionAndFetchUserToken($userId, $tokenId); diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index 2ee303f3f..414bfefeb 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -74,18 +74,18 @@ class UserController extends Controller { $this->checkPermission('users-manage'); $validationRules = [ - 'name' => 'required', - 'email' => 'required|email|unique:users,email', + 'name' => ['required'], + 'email' => ['required', 'email', 'unique:users,email'], ]; $authMethod = config('auth.method'); $sendInvite = ($request->get('send_invite', 'false') === 'true'); if ($authMethod === 'standard' && !$sendInvite) { - $validationRules['password'] = 'required|min:6'; - $validationRules['password-confirm'] = 'required|same:password'; + $validationRules['password'] = ['required', 'min:6']; + $validationRules['password-confirm'] = ['required', 'same:password']; } elseif ($authMethod === 'ldap' || $authMethod === 'saml2' || $authMethod === 'openid') { - $validationRules['external_auth_id'] = 'required'; + $validationRules['external_auth_id'] = ['required']; } $this->validate($request, $validationRules); @@ -156,11 +156,11 @@ class UserController extends Controller $this->validate($request, [ 'name' => 'min:2', - 'email' => 'min:2|email|unique:users,email,' . $id, - 'password' => 'min:6|required_with:password_confirm', - 'password-confirm' => 'same:password|required_with:password', + 'email' => ['min:2', 'email', 'unique:users,email,' . $id], + 'password' => ['min:6', 'required_with:password_confirm'], + 'password-confirm' => ['same:password', 'required_with:password'], 'setting' => 'array', - 'profile_image' => 'nullable|' . $this->getImageValidationRules(), + 'profile_image' => array_merge(['nullable'], $this->getImageValidationRules()), ]); $user = $this->userRepo->getById($id); From d0aa10a8c3d9a374948e000f01a4c8c936d548f6 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Fri, 5 Nov 2021 00:28:41 +0000 Subject: [PATCH 13/59] Applied styleci changes --- app/Api/ApiDocsGenerator.php | 1 + app/Http/Controllers/Auth/ForgotPasswordController.php | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/Api/ApiDocsGenerator.php b/app/Api/ApiDocsGenerator.php index 3aabfb4cc..ea77ae450 100644 --- a/app/Api/ApiDocsGenerator.php +++ b/app/Api/ApiDocsGenerator.php @@ -95,6 +95,7 @@ class ApiDocsGenerator } $rules = $class->getValdationRules()[$methodName] ?? []; + return empty($rules) ? null : $rules; } diff --git a/app/Http/Controllers/Auth/ForgotPasswordController.php b/app/Http/Controllers/Auth/ForgotPasswordController.php index 212bb6ab1..5e73b232c 100644 --- a/app/Http/Controllers/Auth/ForgotPasswordController.php +++ b/app/Http/Controllers/Auth/ForgotPasswordController.php @@ -44,7 +44,7 @@ class ForgotPasswordController extends Controller public function sendResetLinkEmail(Request $request) { $this->validate($request, [ - 'email' => ['required', 'email'] + 'email' => ['required', 'email'], ]); // We will send the password reset link to this user. Once we have attempted From bc291bee783a3124aa9c123de59b3acd4719b106 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Fri, 5 Nov 2021 16:18:06 +0000 Subject: [PATCH 14/59] Added inital phpstan/larastan setup --- .github/workflows/phpstan.yml | 41 + .gitignore | 3 +- app/Api/ApiDocsGenerator.php | 2 +- app/Auth/User.php | 1 - app/Config/broadcasting.php | 86 +- app/Config/cache.php | 68 +- app/Config/database.php | 2 +- app/Console/Commands/CreateAdmin.php | 14 +- app/Entities/Repos/BookshelfRepo.php | 3 +- app/Entities/Tools/SearchOptions.php | 4 +- app/Entities/Tools/TrashCan.php | 2 + app/Http/Controllers/StatusController.php | 4 +- app/Uploads/AttachmentService.php | 8 +- app/Uploads/ImageRepo.php | 2 +- app/Uploads/ImageService.php | 9 +- bootstrap/phpstan.php | 6 + composer.json | 5 +- composer.lock | 925 +++++++++++++++++++++- phpstan.neon.dist | 23 + tests/StatusTest.php | 2 +- 20 files changed, 1086 insertions(+), 124 deletions(-) create mode 100644 .github/workflows/phpstan.yml create mode 100644 bootstrap/phpstan.php create mode 100644 phpstan.neon.dist diff --git a/.github/workflows/phpstan.yml b/.github/workflows/phpstan.yml new file mode 100644 index 000000000..da9901bdc --- /dev/null +++ b/.github/workflows/phpstan.yml @@ -0,0 +1,41 @@ +name: phpstan + +on: + push: + branches-ignore: + - l10n_master + pull_request: + branches-ignore: + - l10n_master + +jobs: + build: + runs-on: ubuntu-20.04 + strategy: + matrix: + php: ['7.3'] + steps: + - uses: actions/checkout@v1 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: gd, mbstring, json, curl, xml, mysql, ldap + + - name: Get Composer Cache Directory + id: composer-cache + run: | + echo "::set-output name=dir::$(composer config cache-files-dir)" + + - name: Cache composer packages + uses: actions/cache@v1 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ matrix.php }} + + - name: Install composer dependencies & Test + run: composer install --prefer-dist --no-interaction --ansi + + - name: Run PHPStan + run: php${{ matrix.php }} ./vendor/bin/phpstan analyse --memory-limit=2G diff --git a/.gitignore b/.gitignore index fc0f10a00..0a858681c 100644 --- a/.gitignore +++ b/.gitignore @@ -23,4 +23,5 @@ nbproject .settings/ webpack-stats.json .phpunit.result.cache -.DS_Store \ No newline at end of file +.DS_Store +phpstan.neon \ No newline at end of file diff --git a/app/Api/ApiDocsGenerator.php b/app/Api/ApiDocsGenerator.php index ea77ae450..0447cd731 100644 --- a/app/Api/ApiDocsGenerator.php +++ b/app/Api/ApiDocsGenerator.php @@ -28,7 +28,7 @@ class ApiDocsGenerator if (Cache::has($cacheKey) && config('app.env') === 'production') { $docs = Cache::get($cacheKey); } else { - $docs = (new static())->generate(); + $docs = (new ApiDocsGenerator)->generate(); Cache::put($cacheKey, $docs, 60 * 24); } diff --git a/app/Auth/User.php b/app/Auth/User.php index dc28aa9b7..540a8d7ab 100644 --- a/app/Auth/User.php +++ b/app/Auth/User.php @@ -178,7 +178,6 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon ->leftJoin('permission_role', 'ru.role_id', '=', 'permission_role.role_id') ->leftJoin('role_permissions', 'permission_role.permission_id', '=', 'role_permissions.id') ->where('ru.user_id', '=', $this->id) - ->get() ->pluck('name'); return $this->permissions; diff --git a/app/Config/broadcasting.php b/app/Config/broadcasting.php index be0d7376c..09189bb09 100644 --- a/app/Config/broadcasting.php +++ b/app/Config/broadcasting.php @@ -1,79 +1,51 @@ $memcachedServer) { - $memcachedServerDetails = explode(':', $memcachedServer); - if (count($memcachedServerDetails) < 2) { - $memcachedServerDetails[] = '11211'; - } - if (count($memcachedServerDetails) < 3) { - $memcachedServerDetails[] = '100'; - } - $memcachedServers[$index] = array_combine($memcachedServerKeys, $memcachedServerDetails); - } -} - return [ - // Default cache store to use - // Can be overridden at cache call-time - 'default' => env('CACHE_DRIVER', 'file'), + // 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' => env('BROADCAST_DRIVER', 'pusher'), - // Available caches stores - 'stores' => [ + // 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' => [ - 'apc' => [ - 'driver' => 'apc', - ], - - 'array' => [ - 'driver' => 'array', - 'serialize' => false, - ], - - 'database' => [ - 'driver' => 'database', - 'table' => 'cache', - 'connection' => null, - 'lock_connection' => null, - ], - - 'file' => [ - 'driver' => 'file', - 'path' => storage_path('framework/cache'), - ], - - 'memcached' => [ - 'driver' => 'memcached', - 'servers' => env('CACHE_DRIVER') === 'memcached' ? $memcachedServers : [], - 'options' => [], + 'pusher' => [ + 'driver' => 'pusher', + 'key' => env('PUSHER_APP_KEY'), + 'secret' => env('PUSHER_APP_SECRET'), + 'app_id' => env('PUSHER_APP_ID'), + 'options' => [ + 'cluster' => env('PUSHER_APP_CLUSTER'), + 'useTLS' => true, + ], ], 'redis' => [ - 'driver' => 'redis', - 'connection' => 'default', - 'lock_connection' => 'default', + 'driver' => 'redis', + 'connection' => 'default', ], - 'octane' => [ - 'driver' => 'octane', + 'log' => [ + 'driver' => 'log', + ], + + 'null' => [ + 'driver' => 'null', ], ], - // Cache key prefix - // Used to prevent collisions in shared cache systems. - 'prefix' => env('CACHE_PREFIX', 'bookstack_cache'), - -]; +]; \ No newline at end of file diff --git a/app/Config/cache.php b/app/Config/cache.php index 6fd4807da..ded1dcae6 100644 --- a/app/Config/cache.php +++ b/app/Config/cache.php @@ -2,35 +2,37 @@ use Illuminate\Support\Str; +/** + * Caching 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. + */ + +// MEMCACHED - Split out configuration into an array +if (env('CACHE_DRIVER') === 'memcached') { + $memcachedServerKeys = ['host', 'port', 'weight']; + $memcachedServers = explode(',', trim(env('MEMCACHED_SERVERS', '127.0.0.1:11211:100'), ',')); + foreach ($memcachedServers as $index => $memcachedServer) { + $memcachedServerDetails = explode(':', $memcachedServer); + if (count($memcachedServerDetails) < 2) { + $memcachedServerDetails[] = '11211'; + } + if (count($memcachedServerDetails) < 3) { + $memcachedServerDetails[] = '100'; + } + $memcachedServers[$index] = array_combine($memcachedServerKeys, $memcachedServerDetails); + } +} + return [ - /* - |-------------------------------------------------------------------------- - | Default Cache Store - |-------------------------------------------------------------------------- - | - | This option controls the default cache connection that gets used while - | using this caching library. This connection is used when another is - | not explicitly specified when executing a given caching function. - | - */ - + // Default cache store to use + // Can be overridden at cache call-time 'default' => env('CACHE_DRIVER', 'file'), - /* - |-------------------------------------------------------------------------- - | Cache Stores - |-------------------------------------------------------------------------- - | - | Here you may define all of the cache "stores" for your application as - | well as their drivers. You may even define multiple stores for the - | same cache driver to group types of items stored in your caches. - | - | Supported drivers: "apc", "array", "database", "file", - | "memcached", "redis", "dynamodb", "octane", "null" - | - */ - + // Available caches stores 'stores' => [ 'apc' => [ @@ -56,15 +58,10 @@ return [ 'memcached' => [ 'driver' => 'memcached', - 'persistent_id' => env('MEMCACHED_PERSISTENT_ID'), - 'sasl' => [ - env('MEMCACHED_USERNAME'), - env('MEMCACHED_PASSWORD'), - ], 'options' => [ // Memcached::OPT_CONNECT_TIMEOUT => 2000, ], - 'servers' => env('CACHE_DRIVER') === 'memcached' ? $memcachedServers : [], + 'servers' => $memcachedServers ?? [], ], 'redis' => [ @@ -73,15 +70,6 @@ return [ 'lock_connection' => 'default', ], - 'dynamodb' => [ - 'driver' => 'dynamodb', - 'key' => env('AWS_ACCESS_KEY_ID'), - 'secret' => env('AWS_SECRET_ACCESS_KEY'), - 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), - 'table' => env('DYNAMODB_CACHE_TABLE', 'cache'), - 'endpoint' => env('DYNAMODB_ENDPOINT'), - ], - 'octane' => [ 'driver' => 'octane', ], diff --git a/app/Config/database.php b/app/Config/database.php index 0c6966095..59ac0f31b 100644 --- a/app/Config/database.php +++ b/app/Config/database.php @@ -105,6 +105,6 @@ return [ 'migrations' => 'migrations', // Redis configuration to use if set - 'redis' => env('REDIS_SERVERS', false) ? $redisConfig : [], + 'redis' => $redisConfig ?? [], ]; diff --git a/app/Console/Commands/CreateAdmin.php b/app/Console/Commands/CreateAdmin.php index a0fb8f315..b421c3add 100644 --- a/app/Console/Commands/CreateAdmin.php +++ b/app/Console/Commands/CreateAdmin.php @@ -4,6 +4,7 @@ namespace BookStack\Console\Commands; use BookStack\Auth\UserRepo; use Illuminate\Console\Command; +use Symfony\Component\Console\Command\Command as SymfonyCommand; class CreateAdmin extends Command { @@ -49,11 +50,13 @@ class CreateAdmin extends Command $email = $this->ask('Please specify an email address for the new admin user'); } if (mb_strlen($email) < 5 || !filter_var($email, FILTER_VALIDATE_EMAIL)) { - return $this->error('Invalid email address provided'); + $this->error('Invalid email address provided'); + return SymfonyCommand::FAILURE; } if ($this->userRepo->getByEmail($email) !== null) { - return $this->error('A user with the provided email already exists!'); + $this->error('A user with the provided email already exists!'); + return SymfonyCommand::FAILURE; } $name = trim($this->option('name')); @@ -61,7 +64,8 @@ class CreateAdmin extends Command $name = $this->ask('Please specify an name for the new admin user'); } if (mb_strlen($name) < 2) { - return $this->error('Invalid name provided'); + $this->error('Invalid name provided'); + return SymfonyCommand::FAILURE; } $password = trim($this->option('password')); @@ -69,7 +73,8 @@ class CreateAdmin extends Command $password = $this->secret('Please specify a password for the new admin user'); } if (mb_strlen($password) < 5) { - return $this->error('Invalid password provided, Must be at least 5 characters'); + $this->error('Invalid password provided, Must be at least 5 characters'); + return SymfonyCommand::FAILURE; } $user = $this->userRepo->create(['email' => $email, 'name' => $name, 'password' => $password]); @@ -79,5 +84,6 @@ class CreateAdmin extends Command $user->save(); $this->info("Admin account with email \"{$user->email}\" successfully created!"); + return SymfonyCommand::SUCCESS; } } diff --git a/app/Entities/Repos/BookshelfRepo.php b/app/Entities/Repos/BookshelfRepo.php index 3990bfbdc..3146c7cba 100644 --- a/app/Entities/Repos/BookshelfRepo.php +++ b/app/Entities/Repos/BookshelfRepo.php @@ -124,7 +124,8 @@ class BookshelfRepo $syncData = Book::visible() ->whereIn('id', $bookIds) - ->get(['id'])->pluck('id')->mapWithKeys(function ($bookId) use ($numericIDs) { + ->pluck('id') + ->mapWithKeys(function ($bookId) use ($numericIDs) { return [$bookId => ['order' => $numericIDs->search($bookId)]]; }); diff --git a/app/Entities/Tools/SearchOptions.php b/app/Entities/Tools/SearchOptions.php index 5ce64cc65..216f79b9c 100644 --- a/app/Entities/Tools/SearchOptions.php +++ b/app/Entities/Tools/SearchOptions.php @@ -32,7 +32,7 @@ class SearchOptions public static function fromString(string $search): self { $decoded = static::decode($search); - $instance = new static(); + $instance = new SearchOptions; foreach ($decoded as $type => $value) { $instance->$type = $value; } @@ -55,7 +55,7 @@ class SearchOptions return static::fromString($request->get('term')); } - $instance = new static(); + $instance = new SearchOptions; $inputs = $request->only(['search', 'types', 'filters', 'exact', 'tags']); $instance->searches = explode(' ', $inputs['search'] ?? []); $instance->exacts = array_filter($inputs['exact'] ?? []); diff --git a/app/Entities/Tools/TrashCan.php b/app/Entities/Tools/TrashCan.php index 82569278e..8327c9489 100644 --- a/app/Entities/Tools/TrashCan.php +++ b/app/Entities/Tools/TrashCan.php @@ -323,6 +323,8 @@ class TrashCan if ($entity instanceof Bookshelf) { return $this->destroyShelf($entity); } + + return 0; } /** diff --git a/app/Http/Controllers/StatusController.php b/app/Http/Controllers/StatusController.php index 336e063ab..ab4f67d0a 100644 --- a/app/Http/Controllers/StatusController.php +++ b/app/Http/Controllers/StatusController.php @@ -20,9 +20,9 @@ class StatusController extends Controller }), 'cache' => $this->trueWithoutError(function () { $rand = Str::random(); - Cache::set('status_test', $rand); + Cache::add('status_test', $rand); - return Cache::get('status_test') === $rand; + return Cache::pull('status_test') === $rand; }), 'session' => $this->trueWithoutError(function () { $rand = Str::random(); diff --git a/app/Uploads/AttachmentService.php b/app/Uploads/AttachmentService.php index 52954d24f..e62a18c82 100644 --- a/app/Uploads/AttachmentService.php +++ b/app/Uploads/AttachmentService.php @@ -4,9 +4,9 @@ namespace BookStack\Uploads; use BookStack\Exceptions\FileUploadException; use Exception; -use Illuminate\Contracts\Filesystem\Factory as FileSystem; use Illuminate\Contracts\Filesystem\FileNotFoundException; -use Illuminate\Contracts\Filesystem\Filesystem as FileSystemInstance; +use Illuminate\Contracts\Filesystem\Filesystem as Storage; +use Illuminate\Filesystem\FilesystemManager; use Illuminate\Support\Facades\Log; use Illuminate\Support\Str; use League\Flysystem\Util; @@ -19,7 +19,7 @@ class AttachmentService /** * AttachmentService constructor. */ - public function __construct(FileSystem $fileSystem) + public function __construct(FilesystemManager $fileSystem) { $this->fileSystem = $fileSystem; } @@ -27,7 +27,7 @@ class AttachmentService /** * Get the storage that will be used for storing files. */ - protected function getStorageDisk(): FileSystemInstance + protected function getStorageDisk(): Storage { return $this->fileSystem->disk($this->getStorageDiskName()); } diff --git a/app/Uploads/ImageRepo.php b/app/Uploads/ImageRepo.php index 5c6228b37..2a4ea424f 100644 --- a/app/Uploads/ImageRepo.php +++ b/app/Uploads/ImageRepo.php @@ -103,7 +103,7 @@ class ImageRepo if ($filterType === 'page') { $query->where('uploaded_to', '=', $contextPage->id); } elseif ($filterType === 'book') { - $validPageIds = $contextPage->book->pages()->visible()->get(['id'])->pluck('id')->toArray(); + $validPageIds = $contextPage->book->pages()->visible()->pluck('id')->toArray(); $query->whereIn('uploaded_to', $validPageIds); } }; diff --git a/app/Uploads/ImageService.php b/app/Uploads/ImageService.php index 644269731..6d4902589 100644 --- a/app/Uploads/ImageService.php +++ b/app/Uploads/ImageService.php @@ -6,10 +6,9 @@ use BookStack\Exceptions\ImageUploadException; use ErrorException; use Exception; use Illuminate\Contracts\Cache\Repository as Cache; -use Illuminate\Contracts\Filesystem\Factory as FileSystem; use Illuminate\Contracts\Filesystem\FileNotFoundException; -use Illuminate\Contracts\Filesystem\Filesystem as FileSystemInstance; use Illuminate\Contracts\Filesystem\Filesystem as Storage; +use Illuminate\Filesystem\FilesystemManager; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Log; use Illuminate\Support\Str; @@ -33,7 +32,7 @@ class ImageService /** * ImageService constructor. */ - public function __construct(Image $image, ImageManager $imageTool, FileSystem $fileSystem, Cache $cache) + public function __construct(Image $image, ImageManager $imageTool, FilesystemManager $fileSystem, Cache $cache) { $this->image = $image; $this->imageTool = $imageTool; @@ -44,7 +43,7 @@ class ImageService /** * Get the storage that will be used for storing images. */ - protected function getStorageDisk(string $imageType = ''): FileSystemInstance + protected function getStorageDisk(string $imageType = ''): Storage { return $this->fileSystem->disk($this->getStorageDiskName($imageType)); } @@ -352,7 +351,7 @@ class ImageService /** * Check whether a folder is empty. */ - protected function isFolderEmpty(FileSystemInstance $storage, string $path): bool + protected function isFolderEmpty(Storage $storage, string $path): bool { $files = $storage->files($path); $folders = $storage->directories($path); diff --git a/bootstrap/phpstan.php b/bootstrap/phpstan.php new file mode 100644 index 000000000..1505fdb20 --- /dev/null +++ b/bootstrap/phpstan.php @@ -0,0 +1,6 @@ +set([ + 'filesystems.default' => 'local', +]); diff --git a/composer.json b/composer.json index 07111d985..1efbbe1ac 100644 --- a/composer.json +++ b/composer.json @@ -47,9 +47,10 @@ "fakerphp/faker": "^1.16", "itsgoingd/clockwork": "^5.1", "mockery/mockery": "^1.4", + "nunomaduro/collision": "^5.10", + "nunomaduro/larastan": "^1.0", "phpunit/phpunit": "^9.5", - "symfony/dom-crawler": "^5.3", - "nunomaduro/collision": "^5.10" + "symfony/dom-crawler": "^5.3" }, "autoload": { "psr-4": { diff --git a/composer.lock b/composer.lock index 4323d89d5..ab0da94cd 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "d7893ec647ed43e272a21c9c01a9b2cb", + "content-hash": "eff5a582fd0ffe2924664e933365a7b9", "packages": [ { "name": "aws/aws-crt-php", @@ -7452,6 +7452,473 @@ } ], "packages-dev": [ + { + "name": "composer/ca-bundle", + "version": "1.3.1", + "source": { + "type": "git", + "url": "https://github.com/composer/ca-bundle.git", + "reference": "4c679186f2aca4ab6a0f1b0b9cf9252decb44d0b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/ca-bundle/zipball/4c679186f2aca4ab6a0f1b0b9cf9252decb44d0b", + "reference": "4c679186f2aca4ab6a0f1b0b9cf9252decb44d0b", + "shasum": "" + }, + "require": { + "ext-openssl": "*", + "ext-pcre": "*", + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^0.12.55", + "psr/log": "^1.0", + "symfony/phpunit-bridge": "^4.2 || ^5", + "symfony/process": "^2.5 || ^3.0 || ^4.0 || ^5.0 || ^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\CaBundle\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.", + "keywords": [ + "cabundle", + "cacert", + "certificate", + "ssl", + "tls" + ], + "support": { + "irc": "irc://irc.freenode.org/composer", + "issues": "https://github.com/composer/ca-bundle/issues", + "source": "https://github.com/composer/ca-bundle/tree/1.3.1" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2021-10-28T20:44:15+00:00" + }, + { + "name": "composer/composer", + "version": "2.1.11", + "source": { + "type": "git", + "url": "https://github.com/composer/composer.git", + "reference": "ddc81bb4718747cc93330ccf832e6be8a6c1d015" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/composer/zipball/ddc81bb4718747cc93330ccf832e6be8a6c1d015", + "reference": "ddc81bb4718747cc93330ccf832e6be8a6c1d015", + "shasum": "" + }, + "require": { + "composer/ca-bundle": "^1.0", + "composer/metadata-minifier": "^1.0", + "composer/semver": "^3.0", + "composer/spdx-licenses": "^1.2", + "composer/xdebug-handler": "^2.0", + "justinrainbow/json-schema": "^5.2.11", + "php": "^5.3.2 || ^7.0 || ^8.0", + "psr/log": "^1.0 || ^2.0", + "react/promise": "^1.2 || ^2.7", + "seld/jsonlint": "^1.4", + "seld/phar-utils": "^1.0", + "symfony/console": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0", + "symfony/filesystem": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0", + "symfony/finder": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0", + "symfony/process": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0" + }, + "require-dev": { + "phpspec/prophecy": "^1.10", + "symfony/phpunit-bridge": "^4.2 || ^5.0 || ^6.0" + }, + "suggest": { + "ext-openssl": "Enabling the openssl extension allows you to access https URLs for repositories and packages", + "ext-zip": "Enabling the zip extension allows you to unzip archives", + "ext-zlib": "Allow gzip compression of HTTP requests" + }, + "bin": [ + "bin/composer" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.1-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\": "src/Composer" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "https://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "https://seld.be" + } + ], + "description": "Composer helps you declare, manage and install dependencies of PHP projects. It ensures you have the right stack everywhere.", + "homepage": "https://getcomposer.org/", + "keywords": [ + "autoload", + "dependency", + "package" + ], + "support": { + "irc": "ircs://irc.libera.chat:6697/composer", + "issues": "https://github.com/composer/composer/issues", + "source": "https://github.com/composer/composer/tree/2.1.11" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2021-11-02T11:10:26+00:00" + }, + { + "name": "composer/metadata-minifier", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/composer/metadata-minifier.git", + "reference": "c549d23829536f0d0e984aaabbf02af91f443207" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/metadata-minifier/zipball/c549d23829536f0d0e984aaabbf02af91f443207", + "reference": "c549d23829536f0d0e984aaabbf02af91f443207", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "composer/composer": "^2", + "phpstan/phpstan": "^0.12.55", + "symfony/phpunit-bridge": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\MetadataMinifier\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "Small utility library that handles metadata minification and expansion.", + "keywords": [ + "composer", + "compression" + ], + "support": { + "issues": "https://github.com/composer/metadata-minifier/issues", + "source": "https://github.com/composer/metadata-minifier/tree/1.0.0" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2021-04-07T13:37:33+00:00" + }, + { + "name": "composer/semver", + "version": "3.2.6", + "source": { + "type": "git", + "url": "https://github.com/composer/semver.git", + "reference": "83e511e247de329283478496f7a1e114c9517506" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/semver/zipball/83e511e247de329283478496f7a1e114c9517506", + "reference": "83e511e247de329283478496f7a1e114c9517506", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^0.12.54", + "symfony/phpunit-bridge": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Semver\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl" + } + ], + "description": "Semver library that offers utilities, version constraint parsing and validation.", + "keywords": [ + "semantic", + "semver", + "validation", + "versioning" + ], + "support": { + "irc": "irc://irc.freenode.org/composer", + "issues": "https://github.com/composer/semver/issues", + "source": "https://github.com/composer/semver/tree/3.2.6" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2021-10-25T11:34:17+00:00" + }, + { + "name": "composer/spdx-licenses", + "version": "1.5.5", + "source": { + "type": "git", + "url": "https://github.com/composer/spdx-licenses.git", + "reference": "de30328a7af8680efdc03e396aad24befd513200" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/spdx-licenses/zipball/de30328a7af8680efdc03e396aad24befd513200", + "reference": "de30328a7af8680efdc03e396aad24befd513200", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || 6.5 - 7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Spdx\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl" + } + ], + "description": "SPDX licenses list and validation library.", + "keywords": [ + "license", + "spdx", + "validator" + ], + "support": { + "irc": "irc://irc.freenode.org/composer", + "issues": "https://github.com/composer/spdx-licenses/issues", + "source": "https://github.com/composer/spdx-licenses/tree/1.5.5" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2020-12-03T16:04:16+00:00" + }, + { + "name": "composer/xdebug-handler", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/composer/xdebug-handler.git", + "reference": "84674dd3a7575ba617f5a76d7e9e29a7d3891339" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/84674dd3a7575ba617f5a76d7e9e29a7d3891339", + "reference": "84674dd3a7575ba617f5a76d7e9e29a7d3891339", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0", + "psr/log": "^1 || ^2 || ^3" + }, + "require-dev": { + "phpstan/phpstan": "^0.12.55", + "symfony/phpunit-bridge": "^4.2 || ^5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Composer\\XdebugHandler\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "John Stevenson", + "email": "john-stevenson@blueyonder.co.uk" + } + ], + "description": "Restarts a process without Xdebug.", + "keywords": [ + "Xdebug", + "performance" + ], + "support": { + "irc": "irc://irc.freenode.org/composer", + "issues": "https://github.com/composer/xdebug-handler/issues", + "source": "https://github.com/composer/xdebug-handler/tree/2.0.2" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2021-07-31T17:03:58+00:00" + }, { "name": "doctrine/instantiator", "version": "1.4.0", @@ -7759,6 +8226,76 @@ ], "time": "2021-11-01T17:38:35+00:00" }, + { + "name": "justinrainbow/json-schema", + "version": "5.2.11", + "source": { + "type": "git", + "url": "https://github.com/justinrainbow/json-schema.git", + "reference": "2ab6744b7296ded80f8cc4f9509abbff393399aa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/2ab6744b7296ded80f8cc4f9509abbff393399aa", + "reference": "2ab6744b7296ded80f8cc4f9509abbff393399aa", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "~2.2.20||~2.15.1", + "json-schema/json-schema-test-suite": "1.2.0", + "phpunit/phpunit": "^4.8.35" + }, + "bin": [ + "bin/validate-json" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "JsonSchema\\": "src/JsonSchema/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bruno Prieto Reis", + "email": "bruno.p.reis@gmail.com" + }, + { + "name": "Justin Rainbow", + "email": "justin.rainbow@gmail.com" + }, + { + "name": "Igor Wiedler", + "email": "igor@wiedler.ch" + }, + { + "name": "Robert Schönthal", + "email": "seroscho@googlemail.com" + } + ], + "description": "A library to validate a json schema.", + "homepage": "https://github.com/justinrainbow/json-schema", + "keywords": [ + "json", + "schema" + ], + "support": { + "issues": "https://github.com/justinrainbow/json-schema/issues", + "source": "https://github.com/justinrainbow/json-schema/tree/5.2.11" + }, + "time": "2021-07-22T09:24:00+00:00" + }, { "name": "mockery/mockery", "version": "1.4.4", @@ -7976,6 +8513,104 @@ ], "time": "2021-09-20T15:06:32+00:00" }, + { + "name": "nunomaduro/larastan", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/nunomaduro/larastan.git", + "reference": "a5a6bdae060c72a5909479fb37c04a7f9fd84533" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nunomaduro/larastan/zipball/a5a6bdae060c72a5909479fb37c04a7f9fd84533", + "reference": "a5a6bdae060c72a5909479fb37c04a7f9fd84533", + "shasum": "" + }, + "require": { + "composer/composer": "^1.0 || ^2.0", + "ext-json": "*", + "illuminate/console": "^6.0 || ^7.0 || ^8.0 || ^9.0", + "illuminate/container": "^6.0 || ^7.0 || ^8.0 || ^9.0", + "illuminate/contracts": "^6.0 || ^7.0 || ^8.0 || ^9.0", + "illuminate/database": "^6.0 || ^7.0 || ^8.0 || ^9.0", + "illuminate/http": "^6.0 || ^7.0 || ^8.0 || ^9.0", + "illuminate/pipeline": "^6.0 || ^7.0 || ^8.0 || ^9.0", + "illuminate/support": "^6.0 || ^7.0 || ^8.0 || ^9.0", + "mockery/mockery": "^0.9 || ^1.0", + "php": "^7.2 || ^8.0", + "phpstan/phpstan": "^1.0", + "symfony/process": "^4.3 || ^5.0 || ^6.0" + }, + "require-dev": { + "nikic/php-parser": "^4.13.0", + "orchestra/testbench": "^4.0 || ^5.0 || ^6.0 || ^7.0", + "phpunit/phpunit": "^7.3 || ^8.2 || ^9.3" + }, + "suggest": { + "orchestra/testbench": "Using Larastan for analysing a package needs Testbench" + }, + "type": "phpstan-extension", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + }, + "phpstan": { + "includes": [ + "extension.neon" + ] + } + }, + "autoload": { + "psr-4": { + "NunoMaduro\\Larastan\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "Larastan - Discover bugs in your code without running it. A phpstan/phpstan wrapper for Laravel", + "keywords": [ + "PHPStan", + "code analyse", + "code analysis", + "larastan", + "laravel", + "package", + "php", + "static analysis" + ], + "support": { + "issues": "https://github.com/nunomaduro/larastan/issues", + "source": "https://github.com/nunomaduro/larastan/tree/1.0.0" + }, + "funding": [ + { + "url": "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=66BYDWAT92N6L", + "type": "custom" + }, + { + "url": "https://github.com/canvural", + "type": "github" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + }, + { + "url": "https://www.patreon.com/nunomaduro", + "type": "patreon" + } + ], + "time": "2021-11-01T12:39:49+00:00" + }, { "name": "phar-io/manifest", "version": "2.0.3", @@ -8314,6 +8949,70 @@ }, "time": "2021-09-10T09:02:12+00:00" }, + { + "name": "phpstan/phpstan", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "e9e2a501102ba0b126b2f63a7f0a3b151056fe91" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/e9e2a501102ba0b126b2f63a7f0a3b151056fe91", + "reference": "e9e2a501102ba0b126b2f63a7f0a3b151056fe91", + "shasum": "" + }, + "require": { + "php": "^7.1|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan - PHP Static Analysis Tool", + "support": { + "issues": "https://github.com/phpstan/phpstan/issues", + "source": "https://github.com/phpstan/phpstan/tree/1.0.2" + }, + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", + "type": "github" + }, + { + "url": "https://www.patreon.com/phpstan", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", + "type": "tidelift" + } + ], + "time": "2021-11-03T16:09:51+00:00" + }, { "name": "phpunit/php-code-coverage", "version": "9.2.8", @@ -8735,6 +9434,56 @@ ], "time": "2021-09-25T07:38:51+00:00" }, + { + "name": "react/promise", + "version": "v2.8.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/promise.git", + "reference": "f3cff96a19736714524ca0dd1d4130de73dbbbc4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/promise/zipball/f3cff96a19736714524ca0dd1d4130de73dbbbc4", + "reference": "f3cff96a19736714524ca0dd1d4130de73dbbbc4", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^7.0 || ^6.5 || ^5.7 || ^4.8.36" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\Promise\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com" + } + ], + "description": "A lightweight implementation of CommonJS Promises/A for PHP", + "keywords": [ + "promise", + "promises" + ], + "support": { + "issues": "https://github.com/reactphp/promise/issues", + "source": "https://github.com/reactphp/promise/tree/v2.8.0" + }, + "time": "2020-05-12T15:16:56+00:00" + }, { "name": "sebastian/cli-parser", "version": "1.0.1", @@ -9699,6 +10448,117 @@ ], "time": "2020-09-28T06:39:44+00:00" }, + { + "name": "seld/jsonlint", + "version": "1.8.3", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/jsonlint.git", + "reference": "9ad6ce79c342fbd44df10ea95511a1b24dee5b57" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/9ad6ce79c342fbd44df10ea95511a1b24dee5b57", + "reference": "9ad6ce79c342fbd44df10ea95511a1b24dee5b57", + "shasum": "" + }, + "require": { + "php": "^5.3 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" + }, + "bin": [ + "bin/jsonlint" + ], + "type": "library", + "autoload": { + "psr-4": { + "Seld\\JsonLint\\": "src/Seld/JsonLint/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "JSON Linter", + "keywords": [ + "json", + "linter", + "parser", + "validator" + ], + "support": { + "issues": "https://github.com/Seldaek/jsonlint/issues", + "source": "https://github.com/Seldaek/jsonlint/tree/1.8.3" + }, + "funding": [ + { + "url": "https://github.com/Seldaek", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/seld/jsonlint", + "type": "tidelift" + } + ], + "time": "2020-11-11T09:19:24+00:00" + }, + { + "name": "seld/phar-utils", + "version": "1.1.2", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/phar-utils.git", + "reference": "749042a2315705d2dfbbc59234dd9ceb22bf3ff0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/phar-utils/zipball/749042a2315705d2dfbbc59234dd9ceb22bf3ff0", + "reference": "749042a2315705d2dfbbc59234dd9ceb22bf3ff0", + "shasum": "" + }, + "require": { + "php": ">=5.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Seld\\PharUtils\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be" + } + ], + "description": "PHAR file format utilities, for when PHP phars you up", + "keywords": [ + "phar" + ], + "support": { + "issues": "https://github.com/Seldaek/phar-utils/issues", + "source": "https://github.com/Seldaek/phar-utils/tree/1.1.2" + }, + "time": "2021-08-19T21:01:38+00:00" + }, { "name": "symfony/dom-crawler", "version": "v5.3.7", @@ -9774,6 +10634,69 @@ ], "time": "2021-08-29T19:32:13+00:00" }, + { + "name": "symfony/filesystem", + "version": "v5.3.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "343f4fe324383ca46792cae728a3b6e2f708fb32" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/343f4fe324383ca46792cae728a3b6e2f708fb32", + "reference": "343f4fe324383ca46792cae728a3b6e2f708fb32", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-php80": "^1.16" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides basic utilities for the filesystem", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/filesystem/tree/v5.3.4" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-07-21T12:40:44+00:00" + }, { "name": "theseer/tokenizer", "version": "1.2.1", diff --git a/phpstan.neon.dist b/phpstan.neon.dist new file mode 100644 index 000000000..815b1c187 --- /dev/null +++ b/phpstan.neon.dist @@ -0,0 +1,23 @@ +includes: + - ./vendor/nunomaduro/larastan/extension.neon + +parameters: + + paths: + - app + + # The level 8 is the highest level + level: 1 + + phpVersion: 70300 + + bootstrapFiles: + - bootstrap/phpstan.php + + ignoreErrors: +# - '#Unsafe usage of new static#' + + excludePaths: + - ./Config/**/*.php + + checkMissingIterableValueType: false \ No newline at end of file diff --git a/tests/StatusTest.php b/tests/StatusTest.php index 09882759c..37b1b15a1 100644 --- a/tests/StatusTest.php +++ b/tests/StatusTest.php @@ -34,7 +34,7 @@ class StatusTest extends TestCase { $mockStore = Mockery::mock(new ArrayStore())->makePartial(); Cache::swap($mockStore); - $mockStore->shouldReceive('get')->andReturn('cat'); + $mockStore->shouldReceive('pull')->andReturn('cat'); $resp = $this->get('/status'); $resp->assertStatus(500); From 5c6a6b50a0c4d42fa245fa7aa8c2e7315d56e3ff Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Fri, 5 Nov 2021 16:27:59 +0000 Subject: [PATCH 15/59] Applied StyleCI changes, added php/larastan to attribution --- .github/workflows/phpstan.yml | 2 +- .github/workflows/phpunit.yml | 2 +- app/Api/ApiDocsGenerator.php | 2 +- app/Config/broadcasting.php | 2 +- app/Config/cache.php | 4 ++-- app/Console/Commands/CreateAdmin.php | 5 +++++ app/Entities/Tools/SearchOptions.php | 4 ++-- readme.md | 3 ++- 8 files changed, 15 insertions(+), 9 deletions(-) diff --git a/.github/workflows/phpstan.yml b/.github/workflows/phpstan.yml index da9901bdc..c7f3179d0 100644 --- a/.github/workflows/phpstan.yml +++ b/.github/workflows/phpstan.yml @@ -34,7 +34,7 @@ jobs: path: ${{ steps.composer-cache.outputs.dir }} key: ${{ runner.os }}-composer-${{ matrix.php }} - - name: Install composer dependencies & Test + - name: Install composer dependencies run: composer install --prefer-dist --no-interaction --ansi - name: Run PHPStan diff --git a/.github/workflows/phpunit.yml b/.github/workflows/phpunit.yml index 7cb1307a1..6c3333502 100644 --- a/.github/workflows/phpunit.yml +++ b/.github/workflows/phpunit.yml @@ -45,7 +45,7 @@ jobs: mysql -uroot -proot -e "GRANT ALL ON \`bookstack-test\`.* TO 'bookstack-test'@'localhost';" mysql -uroot -proot -e 'FLUSH PRIVILEGES;' - - name: Install composer dependencies & Test + - name: Install composer dependencies run: composer install --prefer-dist --no-interaction --ansi - name: Migrate and seed the database diff --git a/app/Api/ApiDocsGenerator.php b/app/Api/ApiDocsGenerator.php index 0447cd731..d130304de 100644 --- a/app/Api/ApiDocsGenerator.php +++ b/app/Api/ApiDocsGenerator.php @@ -28,7 +28,7 @@ class ApiDocsGenerator if (Cache::has($cacheKey) && config('app.env') === 'production') { $docs = Cache::get($cacheKey); } else { - $docs = (new ApiDocsGenerator)->generate(); + $docs = (new ApiDocsGenerator())->generate(); Cache::put($cacheKey, $docs, 60 * 24); } diff --git a/app/Config/broadcasting.php b/app/Config/broadcasting.php index 09189bb09..5e929d373 100644 --- a/app/Config/broadcasting.php +++ b/app/Config/broadcasting.php @@ -48,4 +48,4 @@ return [ ], -]; \ No newline at end of file +]; diff --git a/app/Config/cache.php b/app/Config/cache.php index ded1dcae6..86297b236 100644 --- a/app/Config/cache.php +++ b/app/Config/cache.php @@ -58,10 +58,10 @@ return [ 'memcached' => [ 'driver' => 'memcached', - 'options' => [ + 'options' => [ // Memcached::OPT_CONNECT_TIMEOUT => 2000, ], - 'servers' => $memcachedServers ?? [], + 'servers' => $memcachedServers ?? [], ], 'redis' => [ diff --git a/app/Console/Commands/CreateAdmin.php b/app/Console/Commands/CreateAdmin.php index b421c3add..149444420 100644 --- a/app/Console/Commands/CreateAdmin.php +++ b/app/Console/Commands/CreateAdmin.php @@ -51,11 +51,13 @@ class CreateAdmin extends Command } if (mb_strlen($email) < 5 || !filter_var($email, FILTER_VALIDATE_EMAIL)) { $this->error('Invalid email address provided'); + return SymfonyCommand::FAILURE; } if ($this->userRepo->getByEmail($email) !== null) { $this->error('A user with the provided email already exists!'); + return SymfonyCommand::FAILURE; } @@ -65,6 +67,7 @@ class CreateAdmin extends Command } if (mb_strlen($name) < 2) { $this->error('Invalid name provided'); + return SymfonyCommand::FAILURE; } @@ -74,6 +77,7 @@ class CreateAdmin extends Command } if (mb_strlen($password) < 5) { $this->error('Invalid password provided, Must be at least 5 characters'); + return SymfonyCommand::FAILURE; } @@ -84,6 +88,7 @@ class CreateAdmin extends Command $user->save(); $this->info("Admin account with email \"{$user->email}\" successfully created!"); + return SymfonyCommand::SUCCESS; } } diff --git a/app/Entities/Tools/SearchOptions.php b/app/Entities/Tools/SearchOptions.php index 216f79b9c..39074fb38 100644 --- a/app/Entities/Tools/SearchOptions.php +++ b/app/Entities/Tools/SearchOptions.php @@ -32,7 +32,7 @@ class SearchOptions public static function fromString(string $search): self { $decoded = static::decode($search); - $instance = new SearchOptions; + $instance = new SearchOptions(); foreach ($decoded as $type => $value) { $instance->$type = $value; } @@ -55,7 +55,7 @@ class SearchOptions return static::fromString($request->get('term')); } - $instance = new SearchOptions; + $instance = new SearchOptions(); $inputs = $request->only(['search', 'types', 'filters', 'exact', 'tags']); $instance->searches = explode(' ', $inputs['search'] ?? []); $instance->exacts = array_filter($inputs['exact'] ?? []); diff --git a/readme.md b/readme.md index 92bbe2c5c..2f88be96a 100644 --- a/readme.md +++ b/readme.md @@ -217,4 +217,5 @@ These are the great open-source projects used to help build BookStack: * [pragmarx/google2fa](https://github.com/antonioribeiro/google2fa) * [Bacon/BaconQrCode](https://github.com/Bacon/BaconQrCode) * [phpseclib](https://github.com/phpseclib/phpseclib) -* [Clockwork](https://github.com/itsgoingd/clockwork) \ No newline at end of file +* [Clockwork](https://github.com/itsgoingd/clockwork) +* [PHPStan](https://phpstan.org/) & [Larastan](https://github.com/nunomaduro/larastan) \ No newline at end of file From 8d7c8ac8bfe8deba66386e002ec6ae46d5c63013 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 6 Nov 2021 00:32:01 +0000 Subject: [PATCH 16/59] Done a round of phpstan fixes --- app/Actions/CommentRepo.php | 5 +-- app/Auth/Access/Guards/LdapSessionGuard.php | 2 +- app/Auth/Access/Ldap.php | 20 +++-------- app/Console/Commands/ResetMfa.php | 3 +- app/Entities/Models/Chapter.php | 11 +++--- app/Entities/Models/Deletion.php | 10 ++++-- app/Entities/Models/Page.php | 2 +- app/Entities/Models/PageRevision.php | 2 ++ app/Entities/Tools/PageEditActivity.php | 8 ++++- app/Entities/Tools/SearchRunner.php | 8 +++-- app/Entities/Tools/SiblingFetcher.php | 11 +++--- app/Entities/Tools/SlugGenerator.php | 4 ++- .../Auth/ConfirmEmailController.php | 35 +++++-------------- app/Http/Controllers/Controller.php | 2 +- app/Http/Controllers/FavouriteController.php | 2 +- .../Middleware/CheckUserHasPermission.php | 2 +- app/Interfaces/Sluggable.php | 6 ---- app/Model.php | 5 +-- app/Traits/HasCreatorAndUpdater.php | 4 +-- app/Traits/HasOwner.php | 2 +- app/Uploads/ImageRepo.php | 2 +- app/Uploads/ImageService.php | 3 ++ app/Util/HtmlContentFilter.php | 5 ++- phpstan.neon.dist | 2 +- 24 files changed, 72 insertions(+), 84 deletions(-) diff --git a/app/Actions/CommentRepo.php b/app/Actions/CommentRepo.php index 8121dfc5c..8061c4542 100644 --- a/app/Actions/CommentRepo.php +++ b/app/Actions/CommentRepo.php @@ -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; } } diff --git a/app/Auth/Access/Guards/LdapSessionGuard.php b/app/Auth/Access/Guards/LdapSessionGuard.php index 7f6965937..078487224 100644 --- a/app/Auth/Access/Guards/LdapSessionGuard.php +++ b/app/Auth/Access/Guards/LdapSessionGuard.php @@ -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); } diff --git a/app/Auth/Access/Ldap.php b/app/Auth/Access/Ldap.php index b5c70e498..6259de0ae 100644 --- a/app/Auth/Access/Ldap.php +++ b/app/Auth/Access/Ldap.php @@ -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); } diff --git a/app/Console/Commands/ResetMfa.php b/app/Console/Commands/ResetMfa.php index 031bec04b..9074a4a46 100644 --- a/app/Console/Commands/ResetMfa.php +++ b/app/Console/Commands/ResetMfa.php @@ -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(); diff --git a/app/Entities/Models/Chapter.php b/app/Entities/Models/Chapter.php index abf496b44..75630832b 100644 --- a/app/Entities/Models/Chapter.php +++ b/app/Entities/Models/Chapter.php @@ -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 $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', diff --git a/app/Entities/Models/Deletion.php b/app/Entities/Models/Deletion.php index dab89ce37..3face841b 100644 --- a/app/Entities/Models/Deletion.php +++ b/app/Entities/Models/Deletion.php @@ -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})"; } /** diff --git a/app/Entities/Models/Page.php b/app/Entities/Models/Page.php index fbe0db41b..27d5dc6a4 100644 --- a/app/Entities/Models/Page.php +++ b/app/Entities/Models/Page.php @@ -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', diff --git a/app/Entities/Models/PageRevision.php b/app/Entities/Models/PageRevision.php index b994e7a04..336fd67da 100644 --- a/app/Entities/Models/PageRevision.php +++ b/app/Entities/Models/PageRevision.php @@ -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 { diff --git a/app/Entities/Tools/PageEditActivity.php b/app/Entities/Tools/PageEditActivity.php index ef6c085ac..9981a6ed7 100644 --- a/app/Entities/Tools/PageEditActivity.php +++ b/app/Entities/Tools/PageEditActivity.php @@ -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]); diff --git a/app/Entities/Tools/SearchRunner.php b/app/Entities/Tools/SearchRunner.php index df566eb0b..223494d46 100644 --- a/app/Entities/Tools/SearchRunner.php +++ b/app/Entities/Tools/SearchRunner.php @@ -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); } diff --git a/app/Entities/Tools/SiblingFetcher.php b/app/Entities/Tools/SiblingFetcher.php index e9dad0e13..249e0038e 100644 --- a/app/Entities/Tools/SiblingFetcher.php +++ b/app/Entities/Tools/SiblingFetcher.php @@ -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(); } diff --git a/app/Entities/Tools/SlugGenerator.php b/app/Entities/Tools/SlugGenerator.php index 52e5700da..e715f769f 100644 --- a/app/Entities/Tools/SlugGenerator.php +++ b/app/Entities/Tools/SlugGenerator.php @@ -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 { diff --git a/app/Http/Controllers/Auth/ConfirmEmailController.php b/app/Http/Controllers/Auth/ConfirmEmailController.php index c5466aecd..3e7d4a836 100644 --- a/app/Http/Controllers/Auth/ConfirmEmailController.php +++ b/app/Http/Controllers/Auth/ConfirmEmailController.php @@ -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) { diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index df450d051..047e0bed9 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -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 { diff --git a/app/Http/Controllers/FavouriteController.php b/app/Http/Controllers/FavouriteController.php index c8ba3078c..8643073c9 100644 --- a/app/Http/Controllers/FavouriteController.php +++ b/app/Http/Controllers/FavouriteController.php @@ -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'], diff --git a/app/Http/Middleware/CheckUserHasPermission.php b/app/Http/Middleware/CheckUserHasPermission.php index 4a6a06468..b5678e734 100644 --- a/app/Http/Middleware/CheckUserHasPermission.php +++ b/app/Http/Middleware/CheckUserHasPermission.php @@ -12,7 +12,7 @@ class CheckUserHasPermission * * @param \Illuminate\Http\Request $request * @param \Closure $next - * @param $permission + * @param string $permission * * @return mixed */ diff --git a/app/Interfaces/Sluggable.php b/app/Interfaces/Sluggable.php index 24ee1bab2..2d56e847e 100644 --- a/app/Interfaces/Sluggable.php +++ b/app/Interfaces/Sluggable.php @@ -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 { diff --git a/app/Model.php b/app/Model.php index 8520060f4..bd524332c 100644 --- a/app/Model.php +++ b/app/Model.php @@ -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); } diff --git a/app/Traits/HasCreatorAndUpdater.php b/app/Traits/HasCreatorAndUpdater.php index a48936bc8..7c60be750 100644 --- a/app/Traits/HasCreatorAndUpdater.php +++ b/app/Traits/HasCreatorAndUpdater.php @@ -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 { diff --git a/app/Traits/HasOwner.php b/app/Traits/HasOwner.php index 6700ff4df..c0fefafa9 100644 --- a/app/Traits/HasOwner.php +++ b/app/Traits/HasOwner.php @@ -6,7 +6,7 @@ use BookStack\Auth\User; use Illuminate\Database\Eloquent\Relations\BelongsTo; /** - * @property int owned_by + * @property int $owned_by */ trait HasOwner { diff --git a/app/Uploads/ImageRepo.php b/app/Uploads/ImageRepo.php index 2a4ea424f..494ff3ac0 100644 --- a/app/Uploads/ImageRepo.php +++ b/app/Uploads/ImageRepo.php @@ -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(); diff --git a/app/Uploads/ImageService.php b/app/Uploads/ImageService.php index 6d4902589..b8477eb40 100644 --- a/app/Uploads/ImageService.php +++ b/app/Uploads/ImageService.php @@ -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 diff --git a/app/Util/HtmlContentFilter.php b/app/Util/HtmlContentFilter.php index 1943aa780..08dde7048 100644 --- a/app/Util/HtmlContentFilter.php +++ b/app/Util/HtmlContentFilter.php @@ -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); } } } diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 815b1c187..f3aa47e12 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -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 From 929c8312bd40cffd7914ccc283cd576d68fb7bad Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 6 Nov 2021 16:30:20 +0000 Subject: [PATCH 17/59] Started build of tag view - Created listing - Allows drilldown to tag name - Shows totals Not yet covered via testing --- app/Actions/TagRepo.php | 52 +++++++++--- app/Http/Controllers/TagController.php | 18 ++++ resources/icons/info-filled.svg | 1 - resources/icons/leaderboard.svg | 1 + resources/lang/en/common.php | 2 + resources/lang/en/entities.php | 7 ++ resources/sass/_blocks.scss | 31 ++++++- resources/sass/_tables.scss | 8 +- resources/views/entities/tag-list.blade.php | 10 +-- resources/views/entities/tag.blade.php | 9 ++ .../views/form/request-query-inputs.blade.php | 8 ++ resources/views/tags/index.blade.php | 85 +++++++++++++++++++ routes/web.php | 9 +- 13 files changed, 213 insertions(+), 28 deletions(-) create mode 100644 resources/icons/leaderboard.svg create mode 100644 resources/views/entities/tag.blade.php create mode 100644 resources/views/form/request-query-inputs.blade.php create mode 100644 resources/views/tags/index.blade.php diff --git a/app/Actions/TagRepo.php b/app/Actions/TagRepo.php index b892efe57..06a1b893d 100644 --- a/app/Actions/TagRepo.php +++ b/app/Actions/TagRepo.php @@ -4,6 +4,7 @@ namespace BookStack\Actions; use BookStack\Auth\Permissions\PermissionService; use BookStack\Entities\Models\Entity; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Support\Collection; use Illuminate\Support\Facades\DB; @@ -12,22 +13,51 @@ class TagRepo protected $tag; protected $permissionService; - /** - * TagRepo constructor. - */ - public function __construct(Tag $tag, PermissionService $ps) + public function __construct(PermissionService $ps) { - $this->tag = $tag; $this->permissionService = $ps; } + /** + * Start a query against all tags in the system. + */ + public function queryWithTotals(string $searchTerm, string $nameFilter): Builder + { + $groupingAttribute = $nameFilter ? 'value' : 'name'; + $query = Tag::query() + ->select([ + 'name', + ($searchTerm || $nameFilter) ? 'value' : DB::raw('COUNT(distinct value) as `values`'), + DB::raw('COUNT(id) as usages'), + DB::raw('SUM(IF(entity_type = \'BookStack\\\\Page\', 1, 0)) as page_count'), + DB::raw('SUM(IF(entity_type = \'BookStack\\\\Chapter\', 1, 0)) as chapter_count'), + DB::raw('SUM(IF(entity_type = \'BookStack\\\\Book\', 1, 0)) as book_count'), + DB::raw('SUM(IF(entity_type = \'BookStack\\\\BookShelf\', 1, 0)) as shelf_count'), + ]) + ->groupBy($groupingAttribute) + ->orderBy($groupingAttribute); + + if ($nameFilter) { + $query->where('name', '=', $nameFilter); + } + + if ($searchTerm) { + $query->where(function(Builder $query) use ($searchTerm) { + $query->where('name', 'like', '%' . $searchTerm . '%') + ->orWhere('value', 'like', '%' . $searchTerm . '%'); + }); + } + + return $this->permissionService->filterRestrictedEntityRelations($query, 'tags', 'entity_id', 'entity_type'); + } + /** * Get tag name suggestions from scanning existing tag names. * If no search term is given the 50 most popular tag names are provided. */ public function getNameSuggestions(?string $searchTerm): Collection { - $query = $this->tag->newQuery() + $query = Tag::query() ->select('*', DB::raw('count(*) as count')) ->groupBy('name'); @@ -49,7 +79,7 @@ class TagRepo */ public function getValueSuggestions(?string $searchTerm, ?string $tagName): Collection { - $query = $this->tag->newQuery() + $query = Tag::query() ->select('*', DB::raw('count(*) as count')) ->groupBy('value'); @@ -90,9 +120,9 @@ class TagRepo */ protected function newInstanceFromInput(array $input): Tag { - $name = trim($input['name']); - $value = isset($input['value']) ? trim($input['value']) : ''; - - return $this->tag->newInstance(['name' => $name, 'value' => $value]); + return new Tag([ + 'name' => trim($input['name']), + 'value' => trim($input['value'] ?? ''), + ]); } } diff --git a/app/Http/Controllers/TagController.php b/app/Http/Controllers/TagController.php index b0065af70..c8292a16b 100644 --- a/app/Http/Controllers/TagController.php +++ b/app/Http/Controllers/TagController.php @@ -17,6 +17,24 @@ class TagController extends Controller $this->tagRepo = $tagRepo; } + /** + * Show a listing of existing tags in the system. + */ + public function index(Request $request) + { + $search = $request->get('search', ''); + $nameFilter = $request->get('name', ''); + $tags = $this->tagRepo + ->queryWithTotals($search, $nameFilter) + ->paginate(20); + + return view('tags.index', [ + 'tags' => $tags, + 'search' => $search, + 'nameFilter' => $nameFilter, + ]); + } + /** * Get tag name suggestions from a given search term. */ diff --git a/resources/icons/info-filled.svg b/resources/icons/info-filled.svg index 4c91c86b7..0597dbdf2 100644 --- a/resources/icons/info-filled.svg +++ b/resources/icons/info-filled.svg @@ -1,4 +1,3 @@ - \ No newline at end of file diff --git a/resources/icons/leaderboard.svg b/resources/icons/leaderboard.svg new file mode 100644 index 000000000..9083330dc --- /dev/null +++ b/resources/icons/leaderboard.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources/lang/en/common.php b/resources/lang/en/common.php index 161891bf4..722bf00db 100644 --- a/resources/lang/en/common.php +++ b/resources/lang/en/common.php @@ -45,6 +45,8 @@ return [ 'unfavourite' => 'Unfavourite', 'next' => 'Next', 'previous' => 'Previous', + 'filter_active' => 'Active Filter:', + 'filter_clear' => 'Clear Filter', // Sort Options 'sort_options' => 'Sort Options', diff --git a/resources/lang/en/entities.php b/resources/lang/en/entities.php index 4871b6225..71d062a02 100644 --- a/resources/lang/en/entities.php +++ b/resources/lang/en/entities.php @@ -258,6 +258,13 @@ return [ 'tags_explain' => "Add some tags to better categorise your content. \n You can assign a value to a tag for more in-depth organisation.", 'tags_add' => 'Add another tag', 'tags_remove' => 'Remove this tag', + 'tags_usages' => 'Total tag usages', + 'tags_assigned_pages' => 'Assigned to Pages', + 'tags_assigned_chapters' => 'Assigned to Chapters', + 'tags_assigned_books' => 'Assigned to Books', + 'tags_assigned_shelves' => 'Assigned to Shelves', + 'tags_x_unique_values' => ':count unique values', + 'tags_all_values' => 'All values', 'attachments' => 'Attachments', 'attachments_explain' => 'Upload some files or attach some links to display on your page. These are visible in the page sidebar.', 'attachments_explain_instant_save' => 'Changes here are saved instantly.', diff --git a/resources/sass/_blocks.scss b/resources/sass/_blocks.scss index f9c206154..ef03699f1 100644 --- a/resources/sass/_blocks.scss +++ b/resources/sass/_blocks.scss @@ -245,7 +245,7 @@ @include lightDark(border-color, #CCC, #666); a, span, a:hover, a:active { padding: 4px 8px; - @include lightDark(color, rgba(0, 0, 0, 0.6), rgba(255, 255, 255, 0.8)); + @include lightDark(color, rgba(0, 0, 0, 0.7), rgba(255, 255, 255, 0.8)); transition: background-color ease-in-out 80ms; text-decoration: none; } @@ -266,6 +266,35 @@ margin-bottom: 0; } +td .tag-item { + margin-bottom: 0; +} + +/** + * Pill boxes + */ + +.pill { + display: inline-block; + border: 1px solid currentColor; + padding: .2em .8em; + font-size: 0.8em; + border-radius: 1rem; + position: relative; + overflow: hidden; + line-height: 1.4; + &:before { + content: ''; + background-color: currentColor; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + opacity: 0.1; + } +} + /** * API Docs */ diff --git a/resources/sass/_tables.scss b/resources/sass/_tables.scss index c78e13446..dd585733c 100644 --- a/resources/sass/_tables.scss +++ b/resources/sass/_tables.scss @@ -35,7 +35,7 @@ table.table { font-weight: bold; } tr:hover { - @include lightDark(background-color, #eee, #333); + @include lightDark(background-color, #F2F2F2, #333); } .text-right { text-align: end; @@ -49,6 +49,12 @@ table.table { a { display: inline-block; } + &.expand-to-padding { + margin-left: -$-s; + margin-right: -$-s; + width: calc(100% + (2*#{$-s})); + max-width: calc(100% + (2*#{$-s})); + } } table.no-style { diff --git a/resources/views/entities/tag-list.blade.php b/resources/views/entities/tag-list.blade.php index ffbd5c330..a49eef31b 100644 --- a/resources/views/entities/tag-list.blade.php +++ b/resources/views/entities/tag-list.blade.php @@ -1,11 +1,3 @@ @foreach($entity->tags as $tag) -
- @if($linked ?? true) - - @if($tag->value) @endif - @else -
@icon('tag'){{ $tag->name }}
- @if($tag->value)
{{$tag->value}}
@endif - @endif -
+ @include('entities.tag', ['tag' => $tag]) @endforeach \ No newline at end of file diff --git a/resources/views/entities/tag.blade.php b/resources/views/entities/tag.blade.php new file mode 100644 index 000000000..057c70921 --- /dev/null +++ b/resources/views/entities/tag.blade.php @@ -0,0 +1,9 @@ +
+ @if($linked ?? true) + + @if($tag->value) @endif + @else +
@icon('tag'){{ $tag->name }}
+ @if($tag->value)
{{$tag->value}}
@endif + @endif +
\ No newline at end of file diff --git a/resources/views/form/request-query-inputs.blade.php b/resources/views/form/request-query-inputs.blade.php new file mode 100644 index 000000000..4f2fa061e --- /dev/null +++ b/resources/views/form/request-query-inputs.blade.php @@ -0,0 +1,8 @@ +{{-- +$params - The query paramters to convert to inputs. +--}} +@foreach(array_intersect_key(request()->query(), array_flip($params)) as $name => $value) + @if ($value) + + @endif +@endforeach \ No newline at end of file diff --git a/resources/views/tags/index.blade.php b/resources/views/tags/index.blade.php new file mode 100644 index 000000000..de231493e --- /dev/null +++ b/resources/views/tags/index.blade.php @@ -0,0 +1,85 @@ +@extends('layouts.simple') + +@section('body') +
+ +
+ +
+

{{ trans('entities.tags') }}

+ +
+
+
+ @include('form.request-query-inputs', ['params' => ['page', 'name']]) + +
+
+
+
+ + @if($nameFilter) +
+ {{ trans('common.filter_active') }} + @include('entities.tag', ['tag' => new \BookStack\Actions\Tag(['name' => $nameFilter])]) +
+ @include('form.request-query-inputs', ['params' => ['search']]) + +
+
+ @endif + + + + @foreach($tags as $tag) + + + + + + + + + + @endforeach +
+ @include('entities.tag', ['tag' => $tag]) + + @icon('leaderboard'){{ $tag->usages }} + + @icon('page'){{ $tag->page_count }} + + @icon('chapter'){{ $tag->chapter_count }} + + @icon('book'){{ $tag->book_count }} + + @icon('bookshelf'){{ $tag->shelf_count }} + + @if($tag->values ?? false) + {{ trans('entities.tags_x_unique_values', ['count' => $tag->values]) }} + @elseif(empty($nameFilter)) + {{ trans('entities.tags_all_values') }} + @endif +
+ +
+ {{ $tags->links() }} +
+
+ +
+ +@stop diff --git a/routes/web.php b/routes/web.php index 419a1e7f5..646201d55 100644 --- a/routes/web.php +++ b/routes/web.php @@ -165,11 +165,10 @@ Route::middleware('auth')->group(function () { Route::get('/ajax/page/{id}', [PageController::class, 'getPageAjax']); Route::delete('/ajax/page/{id}', [PageController::class, 'ajaxDestroy']); - // Tag routes (AJAX) - Route::prefix('ajax/tags')->group(function () { - Route::get('/suggest/names', [TagController::class, 'getNameSuggestions']); - Route::get('/suggest/values', [TagController::class, 'getValueSuggestions']); - }); + // Tag routes + Route::get('/tags', [TagController::class, 'index']); + Route::get('/ajax/tags/suggest/names', [TagController::class, 'getNameSuggestions']); + Route::get('/ajax/tags/suggest/values', [TagController::class, 'getValueSuggestions']); Route::get('/ajax/search/entities', [SearchController::class, 'searchEntitiesAjax']); From f8f9e74992e7f0e3369d97b3e35f22f1a9bd678e Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 6 Nov 2021 20:21:11 +0000 Subject: [PATCH 18/59] Added links to tag page - Added from books/shelves listings and within the tag-edit view for all entities. --- resources/lang/en/entities.php | 2 ++ resources/views/books/index.blade.php | 5 +++++ resources/views/entities/tag-manager.blade.php | 15 +++++++++------ resources/views/shelves/index.blade.php | 6 ++++++ 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/resources/lang/en/entities.php b/resources/lang/en/entities.php index 71d062a02..1244fe82a 100644 --- a/resources/lang/en/entities.php +++ b/resources/lang/en/entities.php @@ -265,6 +265,8 @@ return [ 'tags_assigned_shelves' => 'Assigned to Shelves', 'tags_x_unique_values' => ':count unique values', 'tags_all_values' => 'All values', + 'tags_view_tags' => 'View Tags', + 'tags_view_existing_tags' => 'View existing tags', 'attachments' => 'Attachments', 'attachments_explain' => 'Upload some files or attach some links to display on your page. These are visible in the page sidebar.', 'attachments_explain_instant_save' => 'Changes here are saved instantly.', diff --git a/resources/views/books/index.blade.php b/resources/views/books/index.blade.php index 5f1bd3743..6573bbe6a 100644 --- a/resources/views/books/index.blade.php +++ b/resources/views/books/index.blade.php @@ -44,6 +44,11 @@ @endif @include('entities.view-toggle', ['view' => $view, 'type' => 'books']) + + + @icon('tag') + {{ trans('entities.tags_view_tags') }} + diff --git a/resources/views/entities/tag-manager.blade.php b/resources/views/entities/tag-manager.blade.php index 5975c4bd9..803def037 100644 --- a/resources/views/entities/tag-manager.blade.php +++ b/resources/views/entities/tag-manager.blade.php @@ -5,12 +5,15 @@ refs="tag-manager@add-remove" class="tags"> -

{!! nl2br(e(trans('entities.tags_explain'))) !!}

+

+ {!! nl2br(e(trans('entities.tags_explain'))) !!}
+ {{ trans('entities.tags_view_existing_tags') }}. +

-
- @include('entities.tag-manager-list', ['tags' => $entity ? $entity->tags->all() : []]) -
+
+ @include('entities.tag-manager-list', ['tags' => $entity ? $entity->tags->all() : []]) +
- + \ No newline at end of file diff --git a/resources/views/shelves/index.blade.php b/resources/views/shelves/index.blade.php index 5c25356b0..ee52769aa 100644 --- a/resources/views/shelves/index.blade.php +++ b/resources/views/shelves/index.blade.php @@ -15,7 +15,13 @@ {{ trans('entities.shelves_new_action') }} @endif + @include('entities.view-toggle', ['view' => $view, 'type' => 'shelves']) + + + @icon('tag') + {{ trans('entities.tags_view_tags') }} + From 899349c4b497cbc22013bad60667222da1945763 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 6 Nov 2021 21:54:02 +0000 Subject: [PATCH 19/59] Added testing coverage for tag index Also: - Extracted out index table row to its own view. - Added empty state. - Ensured query params are set on pagination links. --- app/Http/Controllers/TagController.php | 6 +- resources/lang/en/entities.php | 1 + resources/views/tags/index.blade.php | 63 ++++--------- .../views/tags/parts/table-row.blade.php | 37 ++++++++ tests/Entity/TagTest.php | 92 +++++++++++++++++++ tests/TestResponse.php | 20 ++++ 6 files changed, 172 insertions(+), 47 deletions(-) create mode 100644 resources/views/tags/parts/table-row.blade.php diff --git a/app/Http/Controllers/TagController.php b/app/Http/Controllers/TagController.php index c8292a16b..aaf0cb9b2 100644 --- a/app/Http/Controllers/TagController.php +++ b/app/Http/Controllers/TagController.php @@ -26,7 +26,11 @@ class TagController extends Controller $nameFilter = $request->get('name', ''); $tags = $this->tagRepo ->queryWithTotals($search, $nameFilter) - ->paginate(20); + ->paginate(50) + ->appends(array_filter([ + 'search' => $search, + 'name' => $nameFilter + ])); return view('tags.index', [ 'tags' => $tags, diff --git a/resources/lang/en/entities.php b/resources/lang/en/entities.php index 1244fe82a..5cf47629a 100644 --- a/resources/lang/en/entities.php +++ b/resources/lang/en/entities.php @@ -267,6 +267,7 @@ return [ 'tags_all_values' => 'All values', 'tags_view_tags' => 'View Tags', 'tags_view_existing_tags' => 'View existing tags', + 'tags_list_empty_hint' => 'Tags can be assigned via the page editor sidebar or while editing the details of a book, chapter or shelf.', 'attachments' => 'Attachments', 'attachments_explain' => 'Upload some files or attach some links to display on your page. These are visible in the page sidebar.', 'attachments_explain_instant_save' => 'Changes here are saved instantly.', diff --git a/resources/views/tags/index.blade.php b/resources/views/tags/index.blade.php index de231493e..c88449ce7 100644 --- a/resources/views/tags/index.blade.php +++ b/resources/views/tags/index.blade.php @@ -11,7 +11,7 @@
- @include('form.request-query-inputs', ['params' => ['page', 'name']]) + @include('form.request-query-inputs', ['params' => ['name']]) @endif + @if(count($tags) > 0) + + @foreach($tags as $tag) + @include('tags.parts.table-row', ['tag' => $tag, 'nameFilter' => $nameFilter]) + @endforeach +
- - @foreach($tags as $tag) - - - - - - - - - - @endforeach -
- @include('entities.tag', ['tag' => $tag]) - - @icon('leaderboard'){{ $tag->usages }} - - @icon('page'){{ $tag->page_count }} - - @icon('chapter'){{ $tag->chapter_count }} - - @icon('book'){{ $tag->book_count }} - - @icon('bookshelf'){{ $tag->shelf_count }} - - @if($tag->values ?? false) - {{ trans('entities.tags_x_unique_values', ['count' => $tag->values]) }} - @elseif(empty($nameFilter)) - {{ trans('entities.tags_all_values') }} - @endif -
- -
- {{ $tags->links() }} -
+
+ {{ $tags->links() }} +
+ @else +

+ {{ trans('common.no_items') }}. +
+ {{ trans('entities.tags_list_empty_hint') }} +

+ @endif
diff --git a/resources/views/tags/parts/table-row.blade.php b/resources/views/tags/parts/table-row.blade.php new file mode 100644 index 000000000..aa04959a9 --- /dev/null +++ b/resources/views/tags/parts/table-row.blade.php @@ -0,0 +1,37 @@ + + + @include('entities.tag', ['tag' => $tag]) + + + @icon('leaderboard'){{ $tag->usages }} + + + @icon('page'){{ $tag->page_count }} + + + @icon('chapter'){{ $tag->chapter_count }} + + + @icon('book'){{ $tag->book_count }} + + + @icon('bookshelf'){{ $tag->shelf_count }} + + + @if($tag->values ?? false) + {{ trans('entities.tags_x_unique_values', ['count' => $tag->values]) }} + @elseif(empty($nameFilter)) + {{ trans('entities.tags_all_values') }} + @endif + + \ No newline at end of file diff --git a/tests/Entity/TagTest.php b/tests/Entity/TagTest.php index 9b3fb1532..db76cae5f 100644 --- a/tests/Entity/TagTest.php +++ b/tests/Entity/TagTest.php @@ -3,6 +3,7 @@ namespace Tests\Entity; use BookStack\Actions\Tag; +use BookStack\Entities\Models\Book; use BookStack\Entities\Models\Entity; use BookStack\Entities\Models\Page; use Tests\TestCase; @@ -98,4 +99,95 @@ class TagTest extends TestCase $resp->assertElementContains('[href="' . $page->getUrl() . '"]', 'color'); $resp->assertElementContains('[href="' . $page->getUrl() . '"]', 'red'); } + + public function test_tags_index_shows_tag_name_as_expected_with_right_counts() + { + /** @var Page $page */ + $page = Page::query()->first(); + $page->tags()->create(['name' => 'Category', 'value' => 'GreatTestContent']); + $page->tags()->create(['name' => 'Category', 'value' => 'OtherTestContent']); + + $resp = $this->asEditor()->get('/tags'); + $resp->assertSee('Category'); + $resp->assertElementCount('.tag-item', 1); + $resp->assertDontSee('GreatTestContent'); + $resp->assertDontSee('OtherTestContent'); + $resp->assertElementContains('a[title="Total tag usages"]', '2'); + $resp->assertElementContains('a[title="Assigned to Pages"]', '2'); + $resp->assertElementContains('a[title="Assigned to Books"]', '0'); + $resp->assertElementContains('a[title="Assigned to Chapters"]', '0'); + $resp->assertElementContains('a[title="Assigned to Shelves"]', '0'); + $resp->assertElementContains('a[href$="/tags?name=Category"]', '2 unique values'); + + /** @var Book $book */ + $book = Book::query()->first(); + $book->tags()->create(['name' => 'Category', 'value' => 'GreatTestContent']); + $resp = $this->asEditor()->get('/tags'); + $resp->assertElementContains('a[title="Total tag usages"]', '3'); + $resp->assertElementContains('a[title="Assigned to Books"]', '1'); + $resp->assertElementContains('a[href$="/tags?name=Category"]', '2 unique values'); + } + + public function test_tag_index_can_be_searched() + { + /** @var Page $page */ + $page = Page::query()->first(); + $page->tags()->create(['name' => 'Category', 'value' => 'GreatTestContent']); + + $resp = $this->asEditor()->get('/tags?search=cat'); + $resp->assertElementContains('.tag-item .tag-name', 'Category'); + + $resp = $this->asEditor()->get('/tags?search=content'); + $resp->assertElementContains('.tag-item .tag-name', 'Category'); + $resp->assertElementContains('.tag-item .tag-value', 'GreatTestContent'); + + $resp = $this->asEditor()->get('/tags?search=other'); + $resp->assertElementNotExists('.tag-item .tag-name'); + } + + public function test_tag_index_can_be_scoped_to_specific_tag_name() + { + /** @var Page $page */ + $page = Page::query()->first(); + $page->tags()->create(['name' => 'Category', 'value' => 'GreatTestContent']); + $page->tags()->create(['name' => 'Category', 'value' => 'OtherTestContent']); + $page->tags()->create(['name' => 'OtherTagName', 'value' => 'OtherValue']); + + $resp = $this->asEditor()->get('/tags?name=Category'); + $resp->assertSee('Category'); + $resp->assertSee('GreatTestContent'); + $resp->assertSee('OtherTestContent'); + $resp->assertDontSee('OtherTagName'); + $resp->assertElementCount('table .tag-item', 2); + $resp->assertSee('Active Filter:'); + $resp->assertElementContains('form[action$="/tags"]', 'Clear Filter'); + } + + public function test_tags_index_adheres_to_page_permissions() + { + /** @var Page $page */ + $page = Page::query()->first(); + $page->tags()->create(['name' => 'SuperCategory', 'value' => 'GreatTestContent']); + + $resp = $this->asEditor()->get('/tags'); + $resp->assertSee('SuperCategory'); + $resp = $this->get('/tags?name=SuperCategory'); + $resp->assertSee('GreatTestContent'); + + $page->restricted = true; + $this->regenEntityPermissions($page); + + $resp = $this->asEditor()->get('/tags'); + $resp->assertDontSee('SuperCategory'); + $resp = $this->get('/tags?name=SuperCategory'); + $resp->assertDontSee('GreatTestContent'); + } + + public function test_tag_index_shows_message_on_no_results() + { + /** @var Page $page */ + $resp = $this->asEditor()->get('/tags?search=testingval'); + $resp->assertSee('No items available'); + $resp->assertSee('Tags can be assigned via the page editor sidebar'); + } } diff --git a/tests/TestResponse.php b/tests/TestResponse.php index 5e2be3ac3..4e53aa020 100644 --- a/tests/TestResponse.php +++ b/tests/TestResponse.php @@ -53,6 +53,26 @@ class TestResponse extends BaseTestResponse return $this; } + /** + * Assert the response contains the given count of elements + * that match the given css selector. + * + * @return $this + */ + public function assertElementCount(string $selector, int $count) + { + $elements = $this->crawler()->filter($selector); + PHPUnit::assertTrue( + $elements->count() === $count, + 'Unable to ' . $count . ' element(s) matching the selector: ' . PHP_EOL . PHP_EOL . + "[{$selector}]" . PHP_EOL . PHP_EOL . + 'found ' . $elements->count() . ' within' . PHP_EOL . PHP_EOL . + "[{$this->getContent()}]." + ); + + return $this; + } + /** * Assert the response does not contain the specified element. * From f2b1d2e1e7b9863b47ed862027479d57fb1da6d6 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 6 Nov 2021 22:00:33 +0000 Subject: [PATCH 20/59] Applied latest StyleCI changes --- app/Actions/TagRepo.php | 2 +- app/Auth/Access/Ldap.php | 1 + app/Entities/Models/Chapter.php | 2 +- app/Entities/Models/PageRevision.php | 1 - app/Entities/Tools/SlugGenerator.php | 1 + app/Http/Controllers/TagController.php | 6 +++--- app/Model.php | 1 + 7 files changed, 8 insertions(+), 6 deletions(-) diff --git a/app/Actions/TagRepo.php b/app/Actions/TagRepo.php index 06a1b893d..ab1b40677 100644 --- a/app/Actions/TagRepo.php +++ b/app/Actions/TagRepo.php @@ -42,7 +42,7 @@ class TagRepo } if ($searchTerm) { - $query->where(function(Builder $query) use ($searchTerm) { + $query->where(function (Builder $query) use ($searchTerm) { $query->where('name', 'like', '%' . $searchTerm . '%') ->orWhere('value', 'like', '%' . $searchTerm . '%'); }); diff --git a/app/Auth/Access/Ldap.php b/app/Auth/Access/Ldap.php index 6259de0ae..4bf6db474 100644 --- a/app/Auth/Access/Ldap.php +++ b/app/Auth/Access/Ldap.php @@ -11,6 +11,7 @@ class Ldap { /** * Connect to an LDAP server. + * * @return resource */ public function connect(string $hostName, int $port) diff --git a/app/Entities/Models/Chapter.php b/app/Entities/Models/Chapter.php index 75630832b..0e2917af3 100644 --- a/app/Entities/Models/Chapter.php +++ b/app/Entities/Models/Chapter.php @@ -10,7 +10,7 @@ use Illuminate\Support\Collection; * Class Chapter. * * @property Collection $pages - * @property string $description + * @property string $description */ class Chapter extends BookChild { diff --git a/app/Entities/Models/PageRevision.php b/app/Entities/Models/PageRevision.php index 336fd67da..6856c23e1 100644 --- a/app/Entities/Models/PageRevision.php +++ b/app/Entities/Models/PageRevision.php @@ -22,7 +22,6 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo; * @property string $html * @property int $revision_number * @property Page $page - * * @property-read ?User $createdBy */ class PageRevision extends Model diff --git a/app/Entities/Tools/SlugGenerator.php b/app/Entities/Tools/SlugGenerator.php index e715f769f..9fd9036ad 100644 --- a/app/Entities/Tools/SlugGenerator.php +++ b/app/Entities/Tools/SlugGenerator.php @@ -39,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 diff --git a/app/Http/Controllers/TagController.php b/app/Http/Controllers/TagController.php index aaf0cb9b2..1fe32e5ca 100644 --- a/app/Http/Controllers/TagController.php +++ b/app/Http/Controllers/TagController.php @@ -29,12 +29,12 @@ class TagController extends Controller ->paginate(50) ->appends(array_filter([ 'search' => $search, - 'name' => $nameFilter + 'name' => $nameFilter, ])); return view('tags.index', [ - 'tags' => $tags, - 'search' => $search, + 'tags' => $tags, + 'search' => $search, 'nameFilter' => $nameFilter, ]); } diff --git a/app/Model.php b/app/Model.php index bd524332c..6fdc25097 100644 --- a/app/Model.php +++ b/app/Model.php @@ -9,6 +9,7 @@ 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. + * * @return mixed */ public function getRawAttribute(string $key) From e1b8fe45b0271e66adbcc06c7d75ddb1a80b4556 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Mon, 8 Nov 2021 11:04:27 +0000 Subject: [PATCH 21/59] Refactored search runner a little to be neater --- app/Entities/Tools/SearchRunner.php | 85 ++++++++++--------------- database/seeders/LargeContentSeeder.php | 10 ++- 2 files changed, 39 insertions(+), 56 deletions(-) diff --git a/app/Entities/Tools/SearchRunner.php b/app/Entities/Tools/SearchRunner.php index 223494d46..dc54649be 100644 --- a/app/Entities/Tools/SearchRunner.php +++ b/app/Entities/Tools/SearchRunner.php @@ -6,11 +6,12 @@ use BookStack\Auth\Permissions\PermissionService; use BookStack\Auth\User; use BookStack\Entities\EntityProvider; use BookStack\Entities\Models\Entity; -use Illuminate\Database\Connection; use Illuminate\Database\Eloquent\Builder as EloquentBuilder; +use Illuminate\Database\Eloquent\Collection as EloquentCollection; use Illuminate\Database\Query\Builder; use Illuminate\Database\Query\JoinClause; use Illuminate\Support\Collection; +use Illuminate\Support\Facades\DB; use Illuminate\Support\Str; class SearchRunner @@ -20,11 +21,6 @@ class SearchRunner */ protected $entityProvider; - /** - * @var Connection - */ - protected $db; - /** * @var PermissionService */ @@ -37,10 +33,9 @@ class SearchRunner */ protected $queryOperators = ['<=', '>=', '=', '<', '>', 'like', '!=']; - public function __construct(EntityProvider $entityProvider, Connection $db, PermissionService $permissionService) + public function __construct(EntityProvider $entityProvider, PermissionService $permissionService) { $this->entityProvider = $entityProvider; - $this->db = $db; $this->permissionService = $permissionService; } @@ -69,16 +64,16 @@ class SearchRunner continue; } - $search = $this->searchEntityTable($searchOpts, $entityType, $page, $count, $action); - /** @var int $entityTotal */ - $entityTotal = $this->searchEntityTable($searchOpts, $entityType, $page, $count, $action, true); + $searchQuery = $this->buildQuery($searchOpts, $entityType, $action); + $entityTotal = $searchQuery->count(); + $searchResults = $this->getPageOfDataFromQuery($searchQuery, $page, $count); if ($entityTotal > ($page * $count)) { $hasMore = true; } $total += $entityTotal; - $results = $results->merge($search); + $results = $results->merge($searchResults); } return [ @@ -103,7 +98,7 @@ class SearchRunner if (!in_array($entityType, $entityTypes)) { continue; } - $search = $this->buildEntitySearchQuery($opts, $entityType)->where('book_id', '=', $bookId)->take(20)->get(); + $search = $this->buildQuery($opts, $entityType)->where('book_id', '=', $bookId)->take(20)->get(); $results = $results->merge($search); } @@ -116,49 +111,41 @@ class SearchRunner public function searchChapter(int $chapterId, string $searchString): Collection { $opts = SearchOptions::fromString($searchString); - $pages = $this->buildEntitySearchQuery($opts, 'page')->where('chapter_id', '=', $chapterId)->take(20)->get(); + $pages = $this->buildQuery($opts, 'page')->where('chapter_id', '=', $chapterId)->take(20)->get(); return $pages->sortByDesc('score'); } /** - * Search across a particular entity type. - * Setting getCount = true will return the total - * matching instead of the items themselves. - * - * @return \Illuminate\Database\Eloquent\Collection|int|static[] + * Get a page of result data from the given query based on the provided page parameters. */ - protected function searchEntityTable(SearchOptions $searchOpts, string $entityType = 'page', int $page = 1, int $count = 20, string $action = 'view', bool $getCount = false) + protected function getPageOfDataFromQuery(EloquentBuilder $query, int $page = 1, int $count = 20): EloquentCollection { - $query = $this->buildEntitySearchQuery($searchOpts, $entityType, $action); - if ($getCount) { - return $query->count(); - } - - $query = $query->skip(($page - 1) * $count)->take($count); - - return $query->get(); + return $query->clone() + ->skip(($page - 1) * $count) + ->take($count) + ->get(); } /** * Create a search query for an entity. */ - protected function buildEntitySearchQuery(SearchOptions $searchOpts, string $entityType = 'page', string $action = 'view'): EloquentBuilder + protected function buildQuery(SearchOptions $searchOpts, string $entityType = 'page', string $action = 'view'): EloquentBuilder { $entity = $this->entityProvider->get($entityType); $entitySelect = $entity->newQuery(); // Handle normal search terms if (count($searchOpts->searches) > 0) { - $rawScoreSum = $this->db->raw('SUM(score) as score'); - $subQuery = $this->db->table('search_terms')->select('entity_id', 'entity_type', $rawScoreSum); + $rawScoreSum = DB::raw('SUM(score) as score'); + $subQuery = DB::table('search_terms')->select('entity_id', 'entity_type', $rawScoreSum); $subQuery->where('entity_type', '=', $entity->getMorphClass()); $subQuery->where(function (Builder $query) use ($searchOpts) { foreach ($searchOpts->searches as $inputTerm) { $query->orWhere('term', 'like', $inputTerm . '%'); } })->groupBy('entity_type', 'entity_id'); - $entitySelect->join($this->db->raw('(' . $subQuery->toSql() . ') as s'), function (JoinClause $join) { + $entitySelect->join(DB::raw('(' . $subQuery->toSql() . ') as s'), function (JoinClause $join) { $join->on('id', '=', 'entity_id'); })->addSelect($entity->getTable() . '.*') ->selectRaw('s.score') @@ -238,44 +225,36 @@ class SearchRunner /** * Custom entity search filters. */ - protected function filterUpdatedAfter(EloquentBuilder $query, Entity $model, $input) + protected function filterUpdatedAfter(EloquentBuilder $query, Entity $model, $input): void { try { $date = date_create($input); - } catch (\Exception $e) { - return; - } - $query->where('updated_at', '>=', $date); + $query->where('updated_at', '>=', $date); + } catch (\Exception $e) {} } - protected function filterUpdatedBefore(EloquentBuilder $query, Entity $model, $input) + protected function filterUpdatedBefore(EloquentBuilder $query, Entity $model, $input): void { try { $date = date_create($input); - } catch (\Exception $e) { - return; - } - $query->where('updated_at', '<', $date); + $query->where('updated_at', '<', $date); + } catch (\Exception $e) {} } - protected function filterCreatedAfter(EloquentBuilder $query, Entity $model, $input) + protected function filterCreatedAfter(EloquentBuilder $query, Entity $model, $input): void { try { $date = date_create($input); - } catch (\Exception $e) { - return; - } - $query->where('created_at', '>=', $date); + $query->where('created_at', '>=', $date); + } catch (\Exception $e) {} } protected function filterCreatedBefore(EloquentBuilder $query, Entity $model, $input) { try { $date = date_create($input); - } catch (\Exception $e) { - return; - } - $query->where('created_at', '<', $date); + $query->where('created_at', '<', $date); + } catch (\Exception $e) {} } protected function filterCreatedBy(EloquentBuilder $query, Entity $model, $input) @@ -352,9 +331,9 @@ class SearchRunner */ protected function sortByLastCommented(EloquentBuilder $query, Entity $model) { - $commentsTable = $this->db->getTablePrefix() . 'comments'; + $commentsTable = DB::getTablePrefix() . 'comments'; $morphClass = str_replace('\\', '\\\\', $model->getMorphClass()); - $commentQuery = $this->db->raw('(SELECT c1.entity_id, c1.entity_type, c1.created_at as last_commented FROM ' . $commentsTable . ' c1 LEFT JOIN ' . $commentsTable . ' c2 ON (c1.entity_id = c2.entity_id AND c1.entity_type = c2.entity_type AND c1.created_at < c2.created_at) WHERE c1.entity_type = \'' . $morphClass . '\' AND c2.created_at IS NULL) as comments'); + $commentQuery = DB::raw('(SELECT c1.entity_id, c1.entity_type, c1.created_at as last_commented FROM ' . $commentsTable . ' c1 LEFT JOIN ' . $commentsTable . ' c2 ON (c1.entity_id = c2.entity_id AND c1.entity_type = c2.entity_type AND c1.created_at < c2.created_at) WHERE c1.entity_type = \'' . $morphClass . '\' AND c2.created_at IS NULL) as comments'); $query->join($commentQuery, $model->getTable() . '.id', '=', 'comments.entity_id')->orderBy('last_commented', 'desc'); } diff --git a/database/seeders/LargeContentSeeder.php b/database/seeders/LargeContentSeeder.php index 2fbf4a5c9..e8b6d74f6 100644 --- a/database/seeders/LargeContentSeeder.php +++ b/database/seeders/LargeContentSeeder.php @@ -5,6 +5,7 @@ namespace Database\Seeders; use BookStack\Auth\Permissions\PermissionService; use BookStack\Auth\Role; use BookStack\Auth\User; +use BookStack\Entities\Models\Book; use BookStack\Entities\Models\Chapter; use BookStack\Entities\Models\Page; use BookStack\Entities\Tools\SearchIndex; @@ -25,12 +26,15 @@ class LargeContentSeeder extends Seeder $editorRole = Role::getRole('editor'); $editorUser->attachRole($editorRole); - $largeBook = \BookStack\Entities\Models\Book::factory()->create(['name' => 'Large book' . Str::random(10), 'created_by' => $editorUser->id, 'updated_by' => $editorUser->id]); + /** @var Book $largeBook */ + $largeBook = Book::factory()->create(['name' => 'Large book' . Str::random(10), 'created_by' => $editorUser->id, 'updated_by' => $editorUser->id]); $pages = Page::factory()->count(200)->make(['created_by' => $editorUser->id, 'updated_by' => $editorUser->id]); $chapters = Chapter::factory()->count(50)->make(['created_by' => $editorUser->id, 'updated_by' => $editorUser->id]); + $largeBook->pages()->saveMany($pages); $largeBook->chapters()->saveMany($chapters); - app(PermissionService::class)->buildJointPermissions(); - app(SearchIndex::class)->indexAllEntities(); + + app()->make(PermissionService::class)->buildJointPermissions(); + app()->make(SearchIndex::class)->indexAllEntities(); } } From 9e0164f4f45cb68f9dccf96db28c8b05ed493be7 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Mon, 8 Nov 2021 11:29:25 +0000 Subject: [PATCH 22/59] Further search system refactorings - Moved search term querying to its own method. - Updated Large content seeder to be more performant --- app/Entities/Tools/SearchIndex.php | 2 +- app/Entities/Tools/SearchRunner.php | 56 +++++++++++++++---------- database/seeders/LargeContentSeeder.php | 5 ++- 3 files changed, 39 insertions(+), 24 deletions(-) diff --git a/app/Entities/Tools/SearchIndex.php b/app/Entities/Tools/SearchIndex.php index cc0b32d6a..541f06994 100644 --- a/app/Entities/Tools/SearchIndex.php +++ b/app/Entities/Tools/SearchIndex.php @@ -46,7 +46,7 @@ class SearchIndex * * @param Entity[] $entities */ - protected function indexEntities(array $entities) + public function indexEntities(array $entities) { $terms = []; foreach ($entities as $entity) { diff --git a/app/Entities/Tools/SearchRunner.php b/app/Entities/Tools/SearchRunner.php index dc54649be..6296c70e7 100644 --- a/app/Entities/Tools/SearchRunner.php +++ b/app/Entities/Tools/SearchRunner.php @@ -133,29 +133,14 @@ class SearchRunner protected function buildQuery(SearchOptions $searchOpts, string $entityType = 'page', string $action = 'view'): EloquentBuilder { $entity = $this->entityProvider->get($entityType); - $entitySelect = $entity->newQuery(); + $entityQuery = $entity->newQuery(); // Handle normal search terms - if (count($searchOpts->searches) > 0) { - $rawScoreSum = DB::raw('SUM(score) as score'); - $subQuery = DB::table('search_terms')->select('entity_id', 'entity_type', $rawScoreSum); - $subQuery->where('entity_type', '=', $entity->getMorphClass()); - $subQuery->where(function (Builder $query) use ($searchOpts) { - foreach ($searchOpts->searches as $inputTerm) { - $query->orWhere('term', 'like', $inputTerm . '%'); - } - })->groupBy('entity_type', 'entity_id'); - $entitySelect->join(DB::raw('(' . $subQuery->toSql() . ') as s'), function (JoinClause $join) { - $join->on('id', '=', 'entity_id'); - })->addSelect($entity->getTable() . '.*') - ->selectRaw('s.score') - ->orderBy('score', 'desc'); - $entitySelect->mergeBindings($subQuery); - } + $this->applyTermSearch($entityQuery, $searchOpts->searches, $entity); // Handle exact term matching foreach ($searchOpts->exacts as $inputTerm) { - $entitySelect->where(function (EloquentBuilder $query) use ($inputTerm, $entity) { + $entityQuery->where(function (EloquentBuilder $query) use ($inputTerm, $entity) { $query->where('name', 'like', '%' . $inputTerm . '%') ->orWhere($entity->textField, 'like', '%' . $inputTerm . '%'); }); @@ -163,18 +148,47 @@ class SearchRunner // Handle tag searches foreach ($searchOpts->tags as $inputTerm) { - $this->applyTagSearch($entitySelect, $inputTerm); + $this->applyTagSearch($entityQuery, $inputTerm); } // Handle filters foreach ($searchOpts->filters as $filterTerm => $filterValue) { $functionName = Str::camel('filter_' . $filterTerm); if (method_exists($this, $functionName)) { - $this->$functionName($entitySelect, $entity, $filterValue); + $this->$functionName($entityQuery, $entity, $filterValue); } } - return $this->permissionService->enforceEntityRestrictions($entity, $entitySelect, $action); + return $this->permissionService->enforceEntityRestrictions($entity, $entityQuery, $action); + } + + /** + * For the given search query, apply the queries for handling the regular search terms. + */ + protected function applyTermSearch(EloquentBuilder $entityQuery, array $terms, Entity $entity): void + { + if (count($terms) === 0) { + return; + } + + $subQuery = DB::table('search_terms')->select([ + 'entity_id', + 'entity_type', + DB::raw('SUM(score) as score'), + ]); + + $subQuery->where('entity_type', '=', $entity->getMorphClass()); + $subQuery->where(function (Builder $query) use ($terms) { + foreach ($terms as $inputTerm) { + $query->orWhere('term', 'like', $inputTerm . '%'); + } + })->groupBy('entity_type', 'entity_id'); + $entityQuery->join(DB::raw('(' . $subQuery->toSql() . ') as s'), function (JoinClause $join) { + $join->on('id', '=', 'entity_id'); + })->addSelect($entity->getTable() . '.*') + ->selectRaw('s.score') + ->orderBy('score', 'desc'); + $entityQuery->mergeBindings($subQuery); } /** diff --git a/database/seeders/LargeContentSeeder.php b/database/seeders/LargeContentSeeder.php index e8b6d74f6..dd9165978 100644 --- a/database/seeders/LargeContentSeeder.php +++ b/database/seeders/LargeContentSeeder.php @@ -33,8 +33,9 @@ class LargeContentSeeder extends Seeder $largeBook->pages()->saveMany($pages); $largeBook->chapters()->saveMany($chapters); + $all = array_merge([$largeBook], array_values($pages->all()), array_values($chapters->all())); - app()->make(PermissionService::class)->buildJointPermissions(); - app()->make(SearchIndex::class)->indexAllEntities(); + app()->make(PermissionService::class)->buildJointPermissionsForEntity($largeBook); + app()->make(SearchIndex::class)->indexEntities($all); } } From b0b6f466c18f88ba0474778624195e1719c82532 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Mon, 8 Nov 2021 11:41:14 +0000 Subject: [PATCH 23/59] Reduced data retreived from database on page search --- app/Entities/Tools/SearchRunner.php | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/app/Entities/Tools/SearchRunner.php b/app/Entities/Tools/SearchRunner.php index 6296c70e7..aa129eb3c 100644 --- a/app/Entities/Tools/SearchRunner.php +++ b/app/Entities/Tools/SearchRunner.php @@ -6,6 +6,7 @@ use BookStack\Auth\Permissions\PermissionService; use BookStack\Auth\User; use BookStack\Entities\EntityProvider; use BookStack\Entities\Models\Entity; +use BookStack\Entities\Models\Page; use Illuminate\Database\Eloquent\Builder as EloquentBuilder; use Illuminate\Database\Eloquent\Collection as EloquentCollection; use Illuminate\Database\Query\Builder; @@ -135,6 +136,10 @@ class SearchRunner $entity = $this->entityProvider->get($entityType); $entityQuery = $entity->newQuery(); + if ($entity instanceof Page) { + $entityQuery->select($entity::$listAttributes); + } + // Handle normal search terms $this->applyTermSearch($entityQuery, $searchOpts->searches, $entity); @@ -178,16 +183,19 @@ class SearchRunner ]); $subQuery->where('entity_type', '=', $entity->getMorphClass()); + $subQuery->where(function (Builder $query) use ($terms) { foreach ($terms as $inputTerm) { $query->orWhere('term', 'like', $inputTerm . '%'); } })->groupBy('entity_type', 'entity_id'); + $entityQuery->join(DB::raw('(' . $subQuery->toSql() . ') as s'), function (JoinClause $join) { - $join->on('id', '=', 'entity_id'); - })->addSelect($entity->getTable() . '.*') - ->selectRaw('s.score') + $join->on('id', '=', 'entity_id'); + }) + ->addSelect(DB::raw('s.score')) ->orderBy('score', 'desc'); + $entityQuery->mergeBindings($subQuery); } From 7405613f8d800999713f14f125bacd1132e14818 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Mon, 8 Nov 2021 14:12:40 +0000 Subject: [PATCH 24/59] Added search term score popularity adjustment Adds adjustment of search term 'score' (Using in result ranking) so that a relative 0.3 to 1.3 mulitplier is applied based upon relative popularity within the whole database. At this point the term popularity is still done via a prefix match against the search term. Uses a SUM(IF(cond, a, IF(cond, a, ...))) chain to produce the scoring result in the select query. --- app/Entities/Tools/SearchRunner.php | 110 +++++++++++++++++++++++++--- 1 file changed, 98 insertions(+), 12 deletions(-) diff --git a/app/Entities/Tools/SearchRunner.php b/app/Entities/Tools/SearchRunner.php index aa129eb3c..3dd0e6b6e 100644 --- a/app/Entities/Tools/SearchRunner.php +++ b/app/Entities/Tools/SearchRunner.php @@ -7,13 +7,14 @@ use BookStack\Auth\User; use BookStack\Entities\EntityProvider; use BookStack\Entities\Models\Entity; use BookStack\Entities\Models\Page; +use BookStack\Entities\Models\SearchTerm; use Illuminate\Database\Eloquent\Builder as EloquentBuilder; use Illuminate\Database\Eloquent\Collection as EloquentCollection; use Illuminate\Database\Query\Builder; -use Illuminate\Database\Query\JoinClause; use Illuminate\Support\Collection; use Illuminate\Support\Facades\DB; use Illuminate\Support\Str; +use SplObjectStorage; class SearchRunner { @@ -34,10 +35,19 @@ class SearchRunner */ protected $queryOperators = ['<=', '>=', '=', '<', '>', 'like', '!=']; + /** + * Retain a cache of score adjusted terms for specific search options. + * From PHP>=8 this can be made into a WeakMap instead. + * + * @var SplObjectStorage + */ + protected $termAdjustmentCache; + public function __construct(EntityProvider $entityProvider, PermissionService $permissionService) { $this->entityProvider = $entityProvider; $this->permissionService = $permissionService; + $this->termAdjustmentCache = new SplObjectStorage(); } /** @@ -138,10 +148,12 @@ class SearchRunner if ($entity instanceof Page) { $entityQuery->select($entity::$listAttributes); + } else { + $entityQuery->select(['*']); } // Handle normal search terms - $this->applyTermSearch($entityQuery, $searchOpts->searches, $entity); + $this->applyTermSearch($entityQuery, $searchOpts, $entity); // Handle exact term matching foreach ($searchOpts->exacts as $inputTerm) { @@ -170,33 +182,107 @@ class SearchRunner /** * For the given search query, apply the queries for handling the regular search terms. */ - protected function applyTermSearch(EloquentBuilder $entityQuery, array $terms, Entity $entity): void + protected function applyTermSearch(EloquentBuilder $entityQuery, SearchOptions $options, Entity $entity): void { + $terms = $options->searches; if (count($terms) === 0) { return; } + $scoredTerms = $this->getTermAdjustments($options); + $scoreSelect = $this->selectForScoredTerms($scoredTerms); + $subQuery = DB::table('search_terms')->select([ 'entity_id', 'entity_type', - DB::raw('SUM(score) as score'), + DB::raw($scoreSelect['statement']), ]); - $subQuery->where('entity_type', '=', $entity->getMorphClass()); + $subQuery->addBinding($scoreSelect['bindings'], 'select'); + $subQuery->where('entity_type', '=', $entity->getMorphClass()); $subQuery->where(function (Builder $query) use ($terms) { foreach ($terms as $inputTerm) { $query->orWhere('term', 'like', $inputTerm . '%'); } - })->groupBy('entity_type', 'entity_id'); + }); + $subQuery->groupBy('entity_type', 'entity_id'); - $entityQuery->join(DB::raw('(' . $subQuery->toSql() . ') as s'), function (JoinClause $join) { - $join->on('id', '=', 'entity_id'); - }) - ->addSelect(DB::raw('s.score')) - ->orderBy('score', 'desc'); + $entityQuery->joinSub($subQuery, 's', 'id', '=', 'entity_id'); + $entityQuery->addSelect('s.score'); + $entityQuery->orderBy('score', 'desc'); + } - $entityQuery->mergeBindings($subQuery); + /** + * Create a select statement, with prepared bindings, for the given + * set of scored search terms. + * @return array{statement: string, bindings: string[]} + */ + protected function selectForScoredTerms(array $scoredTerms): array + { + // Within this we walk backwards to create the chain of 'if' statements + // so that each previous statement is used in the 'else' condition of + // the next (earlier) to be built. We start at '0' to have no score + // on no match (Should never actually get to this case). + $ifChain = '0'; + $bindings = []; + foreach ($scoredTerms as $term => $score) { + $ifChain = 'IF(term like ?, score * ' . (float)$score . ', ' . $ifChain . ')'; + $bindings[] = $term . '%'; + } + + return [ + 'statement' => 'SUM(' . $ifChain . ') as score', + 'bindings' => array_reverse($bindings), + ]; + } + + protected function getTermAdjustments(SearchOptions $options): array + { + if (isset($this->termAdjustmentCache[$options])) { + return $this->termAdjustmentCache[$options]; + } + + $termQuery = SearchTerm::query()->toBase(); + $whenStatements = []; + $whenBindings = []; + + foreach ($options->searches as $term) { + $whenStatements[] = 'WHEN term LIKE ? THEN ?'; + $whenBindings[] = $term . '%'; + $whenBindings[] = $term; + + $termQuery->orWhere('term', 'like', $term . '%'); + } + + $case = 'CASE ' . implode(' ', $whenStatements) . ' END'; + $termQuery->selectRaw( $case . ' as term', $whenBindings); + $termQuery->selectRaw('COUNT(*) as count'); + $termQuery->groupByRaw($case, $whenBindings); + + $termCounts = $termQuery->get()->pluck('count', 'term')->toArray(); + $adjusted = $this->rawTermCountsToAdjustments($termCounts); + + $this->termAdjustmentCache[$options] = $adjusted; + return $this->termAdjustmentCache[$options]; + } + + /** + * Convert counts of terms into a relative-count normalised multiplier. + * @param array $termCounts + * @return array + */ + protected function rawTermCountsToAdjustments(array $termCounts): array + { + $multipliers = []; + $max = max(array_values($termCounts)); + + foreach ($termCounts as $term => $count) { + $percent = round($count / $max, 5); + $multipliers[$term] = 1.3 - $percent; + } + + return $multipliers; } /** From b3e1c7da73a5a5279b84d16b2efd170f4b7702f9 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Mon, 8 Nov 2021 15:00:47 +0000 Subject: [PATCH 25/59] Applied styleci fixes and pluck improvement as per larastan --- app/Entities/Tools/SearchRunner.php | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/app/Entities/Tools/SearchRunner.php b/app/Entities/Tools/SearchRunner.php index 3dd0e6b6e..a251fbc4d 100644 --- a/app/Entities/Tools/SearchRunner.php +++ b/app/Entities/Tools/SearchRunner.php @@ -216,6 +216,7 @@ class SearchRunner /** * Create a select statement, with prepared bindings, for the given * set of scored search terms. + * * @return array{statement: string, bindings: string[]} */ protected function selectForScoredTerms(array $scoredTerms): array @@ -227,13 +228,13 @@ class SearchRunner $ifChain = '0'; $bindings = []; foreach ($scoredTerms as $term => $score) { - $ifChain = 'IF(term like ?, score * ' . (float)$score . ', ' . $ifChain . ')'; + $ifChain = 'IF(term like ?, score * ' . (float) $score . ', ' . $ifChain . ')'; $bindings[] = $term . '%'; } return [ 'statement' => 'SUM(' . $ifChain . ') as score', - 'bindings' => array_reverse($bindings), + 'bindings' => array_reverse($bindings), ]; } @@ -256,24 +257,31 @@ class SearchRunner } $case = 'CASE ' . implode(' ', $whenStatements) . ' END'; - $termQuery->selectRaw( $case . ' as term', $whenBindings); + $termQuery->selectRaw($case . ' as term', $whenBindings); $termQuery->selectRaw('COUNT(*) as count'); $termQuery->groupByRaw($case, $whenBindings); - $termCounts = $termQuery->get()->pluck('count', 'term')->toArray(); + $termCounts = $termQuery->pluck('count', 'term')->toArray(); $adjusted = $this->rawTermCountsToAdjustments($termCounts); $this->termAdjustmentCache[$options] = $adjusted; + return $this->termAdjustmentCache[$options]; } /** * Convert counts of terms into a relative-count normalised multiplier. + * * @param array $termCounts + * * @return array */ protected function rawTermCountsToAdjustments(array $termCounts): array { + if (empty($termCounts)) { + return []; + } + $multipliers = []; $max = max(array_values($termCounts)); @@ -338,7 +346,8 @@ class SearchRunner try { $date = date_create($input); $query->where('updated_at', '>=', $date); - } catch (\Exception $e) {} + } catch (\Exception $e) { + } } protected function filterUpdatedBefore(EloquentBuilder $query, Entity $model, $input): void @@ -346,7 +355,8 @@ class SearchRunner try { $date = date_create($input); $query->where('updated_at', '<', $date); - } catch (\Exception $e) {} + } catch (\Exception $e) { + } } protected function filterCreatedAfter(EloquentBuilder $query, Entity $model, $input): void @@ -354,7 +364,8 @@ class SearchRunner try { $date = date_create($input); $query->where('created_at', '>=', $date); - } catch (\Exception $e) {} + } catch (\Exception $e) { + } } protected function filterCreatedBefore(EloquentBuilder $query, Entity $model, $input) @@ -362,7 +373,8 @@ class SearchRunner try { $date = date_create($input); $query->where('created_at', '<', $date); - } catch (\Exception $e) {} + } catch (\Exception $e) { + } } protected function filterCreatedBy(EloquentBuilder $query, Entity $model, $input) From bc472ca2d7f0f01b035cb17a414c9e7eef9a5576 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Mon, 8 Nov 2021 15:24:49 +0000 Subject: [PATCH 26/59] Improved relation loading during search Relations now loaded during back-end query phase instead of being lazy loaded one-by-one within views. Reduced queries in testing from ~60 to ~20. Need to check other areas list-item.php's "showPath" option is used to ensure relations are properly loaded for those listings. --- app/Entities/Tools/SearchRunner.php | 50 ++++++++++++++------ resources/views/entities/list-item.blade.php | 4 +- 2 files changed, 37 insertions(+), 17 deletions(-) diff --git a/app/Entities/Tools/SearchRunner.php b/app/Entities/Tools/SearchRunner.php index a251fbc4d..3bcd6c054 100644 --- a/app/Entities/Tools/SearchRunner.php +++ b/app/Entities/Tools/SearchRunner.php @@ -5,11 +5,13 @@ namespace BookStack\Entities\Tools; use BookStack\Auth\Permissions\PermissionService; use BookStack\Auth\User; use BookStack\Entities\EntityProvider; +use BookStack\Entities\Models\BookChild; use BookStack\Entities\Models\Entity; use BookStack\Entities\Models\Page; use BookStack\Entities\Models\SearchTerm; use Illuminate\Database\Eloquent\Builder as EloquentBuilder; use Illuminate\Database\Eloquent\Collection as EloquentCollection; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Query\Builder; use Illuminate\Support\Collection; use Illuminate\Support\Facades\DB; @@ -75,9 +77,10 @@ class SearchRunner continue; } - $searchQuery = $this->buildQuery($searchOpts, $entityType, $action); + $entityModelInstance = $this->entityProvider->get($entityType); + $searchQuery = $this->buildQuery($searchOpts, $entityModelInstance, $action); $entityTotal = $searchQuery->count(); - $searchResults = $this->getPageOfDataFromQuery($searchQuery, $page, $count); + $searchResults = $this->getPageOfDataFromQuery($searchQuery, $entityModelInstance, $page, $count); if ($entityTotal > ($page * $count)) { $hasMore = true; @@ -109,7 +112,9 @@ class SearchRunner if (!in_array($entityType, $entityTypes)) { continue; } - $search = $this->buildQuery($opts, $entityType)->where('book_id', '=', $bookId)->take(20)->get(); + + $entityModelInstance = $this->entityProvider->get($entityType); + $search = $this->buildQuery($opts, $entityModelInstance)->where('book_id', '=', $bookId)->take(20)->get(); $results = $results->merge($search); } @@ -122,7 +127,8 @@ class SearchRunner public function searchChapter(int $chapterId, string $searchString): Collection { $opts = SearchOptions::fromString($searchString); - $pages = $this->buildQuery($opts, 'page')->where('chapter_id', '=', $chapterId)->take(20)->get(); + $entityModelInstance = $this->entityProvider->get('page'); + $pages = $this->buildQuery($opts, $entityModelInstance)->where('chapter_id', '=', $chapterId)->take(20)->get(); return $pages->sortByDesc('score'); } @@ -130,9 +136,24 @@ class SearchRunner /** * Get a page of result data from the given query based on the provided page parameters. */ - protected function getPageOfDataFromQuery(EloquentBuilder $query, int $page = 1, int $count = 20): EloquentCollection + protected function getPageOfDataFromQuery(EloquentBuilder $query, Entity $entityModelInstance, int $page = 1, int $count = 20): EloquentCollection { + $relations = ['tags']; + + if ($entityModelInstance instanceof BookChild) { + $relations['book'] = function(BelongsTo $query) { + $query->visible(); + }; + } + + if ($entityModelInstance instanceof Page) { + $relations['chapter'] = function(BelongsTo $query) { + $query->visible(); + }; + } + return $query->clone() + ->with(array_filter($relations)) ->skip(($page - 1) * $count) ->take($count) ->get(); @@ -141,25 +162,24 @@ class SearchRunner /** * Create a search query for an entity. */ - protected function buildQuery(SearchOptions $searchOpts, string $entityType = 'page', string $action = 'view'): EloquentBuilder + protected function buildQuery(SearchOptions $searchOpts, Entity $entityModelInstance, string $action = 'view'): EloquentBuilder { - $entity = $this->entityProvider->get($entityType); - $entityQuery = $entity->newQuery(); + $entityQuery = $entityModelInstance->newQuery(); - if ($entity instanceof Page) { - $entityQuery->select($entity::$listAttributes); + if ($entityModelInstance instanceof Page) { + $entityQuery->select($entityModelInstance::$listAttributes); } else { $entityQuery->select(['*']); } // Handle normal search terms - $this->applyTermSearch($entityQuery, $searchOpts, $entity); + $this->applyTermSearch($entityQuery, $searchOpts, $entityModelInstance); // Handle exact term matching foreach ($searchOpts->exacts as $inputTerm) { - $entityQuery->where(function (EloquentBuilder $query) use ($inputTerm, $entity) { + $entityQuery->where(function (EloquentBuilder $query) use ($inputTerm, $entityModelInstance) { $query->where('name', 'like', '%' . $inputTerm . '%') - ->orWhere($entity->textField, 'like', '%' . $inputTerm . '%'); + ->orWhere($entityModelInstance->textField, 'like', '%' . $inputTerm . '%'); }); } @@ -172,11 +192,11 @@ class SearchRunner foreach ($searchOpts->filters as $filterTerm => $filterValue) { $functionName = Str::camel('filter_' . $filterTerm); if (method_exists($this, $functionName)) { - $this->$functionName($entityQuery, $entity, $filterValue); + $this->$functionName($entityQuery, $entityModelInstance, $filterValue); } } - return $this->permissionService->enforceEntityRestrictions($entity, $entityQuery, $action); + return $this->permissionService->enforceEntityRestrictions($entityModelInstance, $entityQuery, $action); } /** diff --git a/resources/views/entities/list-item.blade.php b/resources/views/entities/list-item.blade.php index 8b5eb20b0..c757b0691 100644 --- a/resources/views/entities/list-item.blade.php +++ b/resources/views/entities/list-item.blade.php @@ -3,9 +3,9 @@
@if($showPath ?? false) - @if($entity->book_id) + @if($entity->relationLoaded('book') && $entity->book) {{ $entity->book->getShortName(42) }} - @if($entity->chapter_id) + @if($entity->relationLoaded('chapter') && $entity->chapter) @icon('chevron-right') {{ $entity->chapter->getShortName(42) }} @endif @endif From da17004c3ee95a13afd1ea1b460ac2eae4262e87 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Tue, 9 Nov 2021 15:05:02 +0000 Subject: [PATCH 27/59] Added test to cover search frquency rank changes --- tests/Entity/EntitySearchTest.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/Entity/EntitySearchTest.php b/tests/Entity/EntitySearchTest.php index 8d2ef0fde..c30bb1d99 100644 --- a/tests/Entity/EntitySearchTest.php +++ b/tests/Entity/EntitySearchTest.php @@ -302,4 +302,22 @@ class EntitySearchTest extends TestCase $search->assertSeeText($page->name); $search->assertSee($page->getUrl()); } + + public function test_search_ranks_common_words_lower() + { + $this->newPage(['name' => 'Test page A', 'html' => '

dog biscuit dog dog

']); + $this->newPage(['name' => 'Test page B', 'html' => '

cat biscuit

']); + + $search = $this->asEditor()->get('/search?term=cat+dog+biscuit'); + $search->assertElementContains('.entity-list > .page', 'Test page A', 1); + $search->assertElementContains('.entity-list > .page', 'Test page B', 2); + + for ($i = 0; $i < 2; $i++) { + $this->newPage(['name' => 'Test page ' . $i, 'html' => '

dog

']); + } + + $search = $this->asEditor()->get('/search?term=cat+dog+biscuit'); + $search->assertElementContains('.entity-list > .page', 'Test page B', 1); + $search->assertElementContains('.entity-list > .page', 'Test page A', 2); + } } From 0ddd0528181fde31e9d3a45f3ec5c2efaba44995 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Tue, 9 Nov 2021 15:13:15 +0000 Subject: [PATCH 28/59] Added missing comments or types Checked over latest changes for potential SQL injection, all variable usages are either (from trusted sourced AND case) or using parameters/bindings to ensure it's handled at driver/lib level. --- app/Entities/Tools/SearchRunner.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/Entities/Tools/SearchRunner.php b/app/Entities/Tools/SearchRunner.php index 3bcd6c054..afe5e9f19 100644 --- a/app/Entities/Tools/SearchRunner.php +++ b/app/Entities/Tools/SearchRunner.php @@ -237,6 +237,8 @@ class SearchRunner * Create a select statement, with prepared bindings, for the given * set of scored search terms. * + * @param array $scoredTerms + * * @return array{statement: string, bindings: string[]} */ protected function selectForScoredTerms(array $scoredTerms): array @@ -258,6 +260,13 @@ class SearchRunner ]; } + /** + * For the terms in the given search options, query their popularity across all + * search terms then provide that back as score adjustment multiplier applicable + * for their rarity. Returns an array of float multipliers, keyed by term. + * + * @return array + */ protected function getTermAdjustments(SearchOptions $options): array { if (isset($this->termAdjustmentCache[$options])) { From 9f3261398207d3c4d77d20f54ac160f61209c1e1 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Thu, 11 Nov 2021 13:36:49 +0000 Subject: [PATCH 29/59] Refactored search indexer, Increase title/name score boost - Title score boost changed from 5 to 40 (8x increase). - Extracted entity parsing to its own function --- app/Entities/Tools/SearchIndex.php | 52 +++++++++++++++++------------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/app/Entities/Tools/SearchIndex.php b/app/Entities/Tools/SearchIndex.php index 541f06994..16f261a37 100644 --- a/app/Entities/Tools/SearchIndex.php +++ b/app/Entities/Tools/SearchIndex.php @@ -9,19 +9,14 @@ use Illuminate\Support\Collection; class SearchIndex { - /** - * @var SearchTerm - */ - protected $searchTerm; /** * @var EntityProvider */ protected $entityProvider; - public function __construct(SearchTerm $searchTerm, EntityProvider $entityProvider) + public function __construct(EntityProvider $entityProvider) { - $this->searchTerm = $searchTerm; $this->entityProvider = $entityProvider; } @@ -31,14 +26,8 @@ class SearchIndex public function indexEntity(Entity $entity) { $this->deleteEntityTerms($entity); - $nameTerms = $this->generateTermArrayFromText($entity->name, 5 * $entity->searchFactor); - $bodyTerms = $this->generateTermArrayFromText($entity->getText(), 1 * $entity->searchFactor); - $terms = array_merge($nameTerms, $bodyTerms); - foreach ($terms as $index => $term) { - $terms[$index]['entity_type'] = $entity->getMorphClass(); - $terms[$index]['entity_id'] = $entity->id; - } - $this->searchTerm->newQuery()->insert($terms); + $terms = $this->entityToTermDataArray($entity); + SearchTerm::query()->insert($terms); } /** @@ -50,18 +39,13 @@ class SearchIndex { $terms = []; foreach ($entities as $entity) { - $nameTerms = $this->generateTermArrayFromText($entity->name, 5 * $entity->searchFactor); - $bodyTerms = $this->generateTermArrayFromText($entity->getText(), 1 * $entity->searchFactor); - foreach (array_merge($nameTerms, $bodyTerms) as $term) { - $term['entity_id'] = $entity->id; - $term['entity_type'] = $entity->getMorphClass(); - $terms[] = $term; - } + $entityTerms = $this->entityToTermDataArray($entity); + array_push($terms, ...$entityTerms); } $chunkedTerms = array_chunk($terms, 500); foreach ($chunkedTerms as $termChunk) { - $this->searchTerm->newQuery()->insert($termChunk); + SearchTerm::query()->insert($termChunk); } } @@ -70,7 +54,7 @@ class SearchIndex */ public function indexAllEntities() { - $this->searchTerm->newQuery()->truncate(); + SearchTerm::query()->truncate(); foreach ($this->entityProvider->all() as $entityModel) { $selectFields = ['id', 'name', $entityModel->textField]; @@ -93,6 +77,8 @@ class SearchIndex /** * Create a scored term array from the given text. + * + * @returns array{term: string, score: float} */ protected function generateTermArrayFromText(string $text, int $scoreAdjustment = 1): array { @@ -118,4 +104,24 @@ class SearchIndex return $terms; } + + /** + * For the given entity, Generate an array of term data details. + * Is the raw term data, not instances of SearchTerm models. + * + * @returns array{term: string, score: float}[] + */ + protected function entityToTermDataArray(Entity $entity): array + { + $nameTerms = $this->generateTermArrayFromText($entity->name, 40 * $entity->searchFactor); + $bodyTerms = $this->generateTermArrayFromText($entity->getText(), 1 * $entity->searchFactor); + $termData = array_merge($nameTerms, $bodyTerms); + + foreach ($termData as $index => $term) { + $termData[$index]['entity_type'] = $entity->getMorphClass(); + $termData[$index]['entity_id'] = $entity->id; + } + + return $termData; + } } From 820be162f5bfb31f69f0122a61755fdd8623275f Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Thu, 11 Nov 2021 14:10:11 +0000 Subject: [PATCH 30/59] Updated regen-search command to show some level of progress --- app/Console/Commands/RegenerateSearch.php | 13 +++++++++-- app/Entities/Tools/SearchIndex.php | 27 ++++++++++++++++++----- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/app/Console/Commands/RegenerateSearch.php b/app/Console/Commands/RegenerateSearch.php index 50e81a2b8..62ee88fc0 100644 --- a/app/Console/Commands/RegenerateSearch.php +++ b/app/Console/Commands/RegenerateSearch.php @@ -2,6 +2,7 @@ namespace BookStack\Console\Commands; +use BookStack\Entities\Models\Entity; use BookStack\Entities\Tools\SearchIndex; use Illuminate\Console\Command; use Illuminate\Support\Facades\DB; @@ -22,6 +23,9 @@ class RegenerateSearch extends Command */ protected $description = 'Re-index all content for searching'; + /** + * @var SearchIndex + */ protected $searchIndex; /** @@ -45,8 +49,13 @@ class RegenerateSearch extends Command DB::setDefaultConnection($this->option('database')); } - $this->searchIndex->indexAllEntities(); + $this->searchIndex->indexAllEntities(function (Entity $model, int $processed, int $total) { + $this->info('Indexed ' . class_basename($model) . ' entries (' . $processed . '/' . $total . ')'); + }); + DB::setDefaultConnection($connection); - $this->comment('Search index regenerated'); + $this->line('Search index regenerated!'); + + return static::SUCCESS; } } diff --git a/app/Entities/Tools/SearchIndex.php b/app/Entities/Tools/SearchIndex.php index 16f261a37..50e471bc9 100644 --- a/app/Entities/Tools/SearchIndex.php +++ b/app/Entities/Tools/SearchIndex.php @@ -51,19 +51,36 @@ class SearchIndex /** * Delete and re-index the terms for all entities in the system. + * Can take a callback which is used for reporting progress. + * Callback receives three arguments: + * - An instance of the model being processed + * - The number that have been processed so far. + * - The total number of that model to be processed. + * + * @param callable(Entity, int, int)|null $progressCallback */ - public function indexAllEntities() + public function indexAllEntities(?callable $progressCallback = null) { SearchTerm::query()->truncate(); foreach ($this->entityProvider->all() as $entityModel) { $selectFields = ['id', 'name', $entityModel->textField]; + $total = $entityModel->newQuery()->withTrashed()->count(); + $chunkSize = 250; + $processed = 0; + + $chunkCallback = function (Collection $entities) use ($progressCallback, &$processed, $total, $chunkSize, $entityModel) { + $this->indexEntities($entities->all()); + $processed = min($processed + $chunkSize, $total); + + if (is_callable($progressCallback)) { + $progressCallback($entityModel, $processed, $total); + } + }; + $entityModel->newQuery() - ->withTrashed() ->select($selectFields) - ->chunk(1000, function (Collection $entities) { - $this->indexEntities($entities->all()); - }); + ->chunk($chunkSize, $chunkCallback); } } From f28daa01d9d43d36c12b075bddca92be9e8f85e4 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Fri, 12 Nov 2021 13:47:23 +0000 Subject: [PATCH 31/59] Added page content parsing to up-rank header text in search This adds parsing of page content so that headers apply a boost to scores in the search term index. Additionally, this merges title and content terms to reduce the amount of stored terms a little. Includes testing to cover. --- app/Entities/Models/Book.php | 2 +- app/Entities/Models/Bookshelf.php | 2 +- app/Entities/Models/Chapter.php | 2 +- app/Entities/Models/Entity.php | 10 +-- app/Entities/Models/Page.php | 6 +- app/Entities/Repos/PageRepo.php | 2 +- app/Entities/Tools/SearchIndex.php | 132 ++++++++++++++++++++++++----- tests/Entity/EntitySearchTest.php | 40 +++++++++ 8 files changed, 158 insertions(+), 38 deletions(-) diff --git a/app/Entities/Models/Book.php b/app/Entities/Models/Book.php index 982df5c90..359f7961c 100644 --- a/app/Entities/Models/Book.php +++ b/app/Entities/Models/Book.php @@ -24,7 +24,7 @@ class Book extends Entity implements HasCoverImage { use HasFactory; - public $searchFactor = 2; + public $searchFactor = 1.5; protected $fillable = ['name', 'description']; protected $hidden = ['restricted', 'pivot', 'image_id', 'deleted_at']; diff --git a/app/Entities/Models/Bookshelf.php b/app/Entities/Models/Bookshelf.php index 8fe9dbe41..b426858c3 100644 --- a/app/Entities/Models/Bookshelf.php +++ b/app/Entities/Models/Bookshelf.php @@ -13,7 +13,7 @@ class Bookshelf extends Entity implements HasCoverImage protected $table = 'bookshelves'; - public $searchFactor = 3; + public $searchFactor = 1.5; protected $fillable = ['name', 'description', 'image_id']; diff --git a/app/Entities/Models/Chapter.php b/app/Entities/Models/Chapter.php index 0e2917af3..f4d1a281d 100644 --- a/app/Entities/Models/Chapter.php +++ b/app/Entities/Models/Chapter.php @@ -16,7 +16,7 @@ class Chapter extends BookChild { use HasFactory; - public $searchFactor = 1.3; + public $searchFactor = 1.5; protected $fillable = ['name', 'description', 'priority', 'book_id']; protected $hidden = ['restricted', 'pivot', 'deleted_at']; diff --git a/app/Entities/Models/Entity.php b/app/Entities/Models/Entity.php index f5f9d91f0..4c4e55bb8 100644 --- a/app/Entities/Models/Entity.php +++ b/app/Entities/Models/Entity.php @@ -238,20 +238,12 @@ abstract class Entity extends Model implements Sluggable, Favouritable, Viewable return mb_substr($this->name, 0, $length - 3) . '...'; } - /** - * Get the body text of this entity. - */ - public function getText(): string - { - return $this->{$this->textField} ?? ''; - } - /** * Get an excerpt of this entity's descriptive content to the specified length. */ public function getExcerpt(int $length = 100): string { - $text = $this->getText(); + $text = $this->{$this->textField} ?? ''; if (mb_strlen($text) > $length) { $text = mb_substr($text, 0, $length - 3) . '...'; diff --git a/app/Entities/Models/Page.php b/app/Entities/Models/Page.php index 27d5dc6a4..c28b9a305 100644 --- a/app/Entities/Models/Page.php +++ b/app/Entities/Models/Page.php @@ -3,13 +3,13 @@ namespace BookStack\Entities\Models; use BookStack\Entities\Tools\PageContent; +use BookStack\Facades\Permissions; use BookStack\Uploads\Attachment; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\HasMany; -use Permissions; /** * Class Page. @@ -64,10 +64,8 @@ class Page extends BookChild /** * Check if this page has a chapter. - * - * @return bool */ - public function hasChapter() + public function hasChapter(): bool { return $this->chapter()->count() > 0; } diff --git a/app/Entities/Repos/PageRepo.php b/app/Entities/Repos/PageRepo.php index ffa06d459..98fe4ef55 100644 --- a/app/Entities/Repos/PageRepo.php +++ b/app/Entities/Repos/PageRepo.php @@ -157,8 +157,8 @@ class PageRepo */ public function publishDraft(Page $draft, array $input): Page { - $this->baseRepo->update($draft, $input); $this->updateTemplateStatusAndContentFromInput($draft, $input); + $this->baseRepo->update($draft, $input); $draft->draft = false; $draft->revision_count = 1; diff --git a/app/Entities/Tools/SearchIndex.php b/app/Entities/Tools/SearchIndex.php index 50e471bc9..bde5ef860 100644 --- a/app/Entities/Tools/SearchIndex.php +++ b/app/Entities/Tools/SearchIndex.php @@ -4,7 +4,10 @@ namespace BookStack\Entities\Tools; use BookStack\Entities\EntityProvider; use BookStack\Entities\Models\Entity; +use BookStack\Entities\Models\Page; use BookStack\Entities\Models\SearchTerm; +use DOMDocument; +use DOMNode; use Illuminate\Support\Collection; class SearchIndex @@ -64,7 +67,8 @@ class SearchIndex SearchTerm::query()->truncate(); foreach ($this->entityProvider->all() as $entityModel) { - $selectFields = ['id', 'name', $entityModel->textField]; + $indexContentField = $entityModel instanceof Page ? 'html' : 'description'; + $selectFields = ['id', 'name', $indexContentField]; $total = $entityModel->newQuery()->withTrashed()->count(); $chunkSize = 250; $processed = 0; @@ -93,11 +97,70 @@ class SearchIndex } /** - * Create a scored term array from the given text. + * Create a scored term array from the given text, where the keys are the terms + * and the values are their scores. * - * @returns array{term: string, score: float} + * @returns array */ - protected function generateTermArrayFromText(string $text, int $scoreAdjustment = 1): array + protected function generateTermScoreMapFromText(string $text, int $scoreAdjustment = 1): array + { + $termMap = $this->textToTermCountMap($text); + + foreach ($termMap as $term => $count) { + $termMap[$term] = $count * $scoreAdjustment; + } + + return $termMap; + } + + /** + * Create a scored term array from the given HTML, where the keys are the terms + * and the values are their scores. + * + * @returns array + */ + protected function generateTermScoreMapFromHtml(string $html): array + { + if (empty($html)) { + return []; + } + + $scoresByTerm = []; + $elementScoreAdjustmentMap = [ + 'h1' => 10, + 'h2' => 5, + 'h3' => 4, + 'h4' => 3, + 'h5' => 2, + 'h6' => 1.5, + ]; + + $html = '' . $html . ''; + libxml_use_internal_errors(true); + $doc = new DOMDocument(); + $doc->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8')); + + $topElems = $doc->documentElement->childNodes->item(0)->childNodes; + /** @var DOMNode $child */ + foreach ($topElems as $child) { + $nodeName = $child->nodeName; + $termCounts = $this->textToTermCountMap(trim($child->textContent)); + foreach ($termCounts as $term => $count) { + $scoreChange = $count * ($elementScoreAdjustmentMap[$nodeName] ?? 1); + $scoresByTerm[$term] = ($scoresByTerm[$term] ?? 0) + $scoreChange; + } + } + + return $scoresByTerm; + } + + /** + * For the given text, return an array where the keys are the unique term words + * and the values are the frequency of that term. + * + * @returns array + */ + protected function textToTermCountMap(string $text): array { $tokenMap = []; // {TextToken => OccurrenceCount} $splitChars = " \n\t.,!?:;()[]{}<>`'\""; @@ -111,34 +174,61 @@ class SearchIndex $token = strtok($splitChars); } - $terms = []; - foreach ($tokenMap as $token => $count) { - $terms[] = [ - 'term' => $token, - 'score' => $count * $scoreAdjustment, - ]; - } - - return $terms; + return $tokenMap; } /** * For the given entity, Generate an array of term data details. * Is the raw term data, not instances of SearchTerm models. * - * @returns array{term: string, score: float}[] + * @returns array{term: string, score: float, entity_id: int, entity_type: string}[] */ protected function entityToTermDataArray(Entity $entity): array { - $nameTerms = $this->generateTermArrayFromText($entity->name, 40 * $entity->searchFactor); - $bodyTerms = $this->generateTermArrayFromText($entity->getText(), 1 * $entity->searchFactor); - $termData = array_merge($nameTerms, $bodyTerms); + $nameTermsMap = $this->generateTermScoreMapFromText($entity->name, 40 * $entity->searchFactor); - foreach ($termData as $index => $term) { - $termData[$index]['entity_type'] = $entity->getMorphClass(); - $termData[$index]['entity_id'] = $entity->id; + if ($entity instanceof Page) { + $bodyTermsMap = $this->generateTermScoreMapFromHtml($entity->html); + } else { + $bodyTermsMap = $this->generateTermScoreMapFromText($entity->description, $entity->searchFactor); } - return $termData; + $mergedScoreMap = $this->mergeTermScoreMaps($nameTermsMap, $bodyTermsMap); + + $dataArray = []; + $entityId = $entity->id; + $entityType = $entity->getMorphClass(); + foreach ($mergedScoreMap as $term => $score) { + $dataArray[] = [ + 'term' => $term, + 'score' => $score, + 'entity_type' => $entityType, + 'entity_id' => $entityId, + ]; + } + + return $dataArray; + } + + + /** + * For the given term data arrays, Merge their contents by term + * while combining any scores. + * + * @param array[] ...$scoreMaps + * + * @returns array + */ + protected function mergeTermScoreMaps(...$scoreMaps): array + { + $mergedMap = []; + + foreach ($scoreMaps as $scoreMap) { + foreach ($scoreMap as $term => $score) { + $mergedMap[$term] = ($mergedMap[$term] ?? 0) + $score; + } + } + + return $mergedMap; } } diff --git a/tests/Entity/EntitySearchTest.php b/tests/Entity/EntitySearchTest.php index c30bb1d99..bd50a13ac 100644 --- a/tests/Entity/EntitySearchTest.php +++ b/tests/Entity/EntitySearchTest.php @@ -7,6 +7,7 @@ use BookStack\Entities\Models\Book; use BookStack\Entities\Models\Bookshelf; use BookStack\Entities\Models\Chapter; use BookStack\Entities\Models\Page; +use BookStack\Entities\Models\SearchTerm; use Tests\TestCase; class EntitySearchTest extends TestCase @@ -320,4 +321,43 @@ class EntitySearchTest extends TestCase $search->assertElementContains('.entity-list > .page', 'Test page B', 1); $search->assertElementContains('.entity-list > .page', 'Test page A', 2); } + + public function test_terms_in_headers_have_an_adjusted_index_score() + { + $page = $this->newPage(['name' => 'Test page A', 'html' => ' +

TermA

+

TermB TermNested

+

TermC

+

TermD

+

TermE

+
TermF
+
TermG
+ ']); + + $entityRelationCols = ['entity_id' => $page->id, 'entity_type' => 'BookStack\\Page']; + $scoreByTerm = SearchTerm::query()->where($entityRelationCols)->pluck('score', 'term'); + + $this->assertEquals(1, $scoreByTerm->get('TermA')); + $this->assertEquals(10, $scoreByTerm->get('TermB')); + $this->assertEquals(10, $scoreByTerm->get('TermNested')); + $this->assertEquals(5, $scoreByTerm->get('TermC')); + $this->assertEquals(4, $scoreByTerm->get('TermD')); + $this->assertEquals(3, $scoreByTerm->get('TermE')); + $this->assertEquals(2, $scoreByTerm->get('TermF')); + // Is 1.5 but stored as integer, rounding up + $this->assertEquals(2, $scoreByTerm->get('TermG')); + } + + public function test_name_and_content_terms_are_merged_to_single_score() + { + $page = $this->newPage(['name' => 'TermA', 'html' => ' +

TermA

+ ']); + + $entityRelationCols = ['entity_id' => $page->id, 'entity_type' => 'BookStack\\Page']; + $scoreByTerm = SearchTerm::query()->where($entityRelationCols)->pluck('score', 'term'); + + // Scores 40 for being in the name then 1 for being in the content + $this->assertEquals(41, $scoreByTerm->get('TermA')); + } } From 99587a0be63556a6915ac2728d8236da2f61c288 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Fri, 12 Nov 2021 17:06:01 +0000 Subject: [PATCH 32/59] Added tag values as part of the indexed search terms This allows finding content via tag name/values when just searching using normal seach terms. Added testing to cover. Related to #1577 --- app/Actions/Tag.php | 6 ++++++ app/Entities/Models/Book.php | 2 +- app/Entities/Models/Bookshelf.php | 2 +- app/Entities/Models/Chapter.php | 2 +- app/Entities/Tools/SearchIndex.php | 29 ++++++++++++++++++++++++++++- tests/Entity/EntitySearchTest.php | 19 +++++++++++++++---- 6 files changed, 52 insertions(+), 8 deletions(-) diff --git a/app/Actions/Tag.php b/app/Actions/Tag.php index db9328b7d..609c299ad 100644 --- a/app/Actions/Tag.php +++ b/app/Actions/Tag.php @@ -6,6 +6,12 @@ use BookStack\Model; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\MorphTo; +/** + * @property int $id + * @property string $name + * @property string $value + * @property int $order + */ class Tag extends Model { use HasFactory; diff --git a/app/Entities/Models/Book.php b/app/Entities/Models/Book.php index 359f7961c..735d25a99 100644 --- a/app/Entities/Models/Book.php +++ b/app/Entities/Models/Book.php @@ -24,7 +24,7 @@ class Book extends Entity implements HasCoverImage { use HasFactory; - public $searchFactor = 1.5; + public $searchFactor = 1.2; protected $fillable = ['name', 'description']; protected $hidden = ['restricted', 'pivot', 'image_id', 'deleted_at']; diff --git a/app/Entities/Models/Bookshelf.php b/app/Entities/Models/Bookshelf.php index b426858c3..e4d9775b7 100644 --- a/app/Entities/Models/Bookshelf.php +++ b/app/Entities/Models/Bookshelf.php @@ -13,7 +13,7 @@ class Bookshelf extends Entity implements HasCoverImage protected $table = 'bookshelves'; - public $searchFactor = 1.5; + public $searchFactor = 1.2; protected $fillable = ['name', 'description', 'image_id']; diff --git a/app/Entities/Models/Chapter.php b/app/Entities/Models/Chapter.php index f4d1a281d..224ded935 100644 --- a/app/Entities/Models/Chapter.php +++ b/app/Entities/Models/Chapter.php @@ -16,7 +16,7 @@ class Chapter extends BookChild { use HasFactory; - public $searchFactor = 1.5; + public $searchFactor = 1.2; protected $fillable = ['name', 'description', 'priority', 'book_id']; protected $hidden = ['restricted', 'pivot', 'deleted_at']; diff --git a/app/Entities/Tools/SearchIndex.php b/app/Entities/Tools/SearchIndex.php index bde5ef860..05de341f9 100644 --- a/app/Entities/Tools/SearchIndex.php +++ b/app/Entities/Tools/SearchIndex.php @@ -2,6 +2,7 @@ namespace BookStack\Entities\Tools; +use BookStack\Actions\Tag; use BookStack\Entities\EntityProvider; use BookStack\Entities\Models\Entity; use BookStack\Entities\Models\Page; @@ -84,6 +85,7 @@ class SearchIndex $entityModel->newQuery() ->select($selectFields) + ->with(['tags:id,name,value,entity_id,entity_type']) ->chunk($chunkSize, $chunkCallback); } } @@ -154,6 +156,30 @@ class SearchIndex return $scoresByTerm; } + /** + * Create a scored term map from the given set of entity tags. + * + * @param Tag[] $tags + * + * @returns array + */ + protected function generateTermScoreMapFromTags(array $tags): array + { + $scoreMap = []; + $names = []; + $values = []; + + foreach($tags as $tag) { + $names[] = $tag->name; + $values[] = $tag->value; + } + + $nameMap = $this->generateTermScoreMapFromText(implode(' ', $names), 3); + $valueMap = $this->generateTermScoreMapFromText(implode(' ', $values), 5); + + return $this->mergeTermScoreMaps($nameMap, $valueMap); + } + /** * For the given text, return an array where the keys are the unique term words * and the values are the frequency of that term. @@ -186,6 +212,7 @@ class SearchIndex protected function entityToTermDataArray(Entity $entity): array { $nameTermsMap = $this->generateTermScoreMapFromText($entity->name, 40 * $entity->searchFactor); + $tagTermsMap = $this->generateTermScoreMapFromTags($entity->tags->all()); if ($entity instanceof Page) { $bodyTermsMap = $this->generateTermScoreMapFromHtml($entity->html); @@ -193,7 +220,7 @@ class SearchIndex $bodyTermsMap = $this->generateTermScoreMapFromText($entity->description, $entity->searchFactor); } - $mergedScoreMap = $this->mergeTermScoreMaps($nameTermsMap, $bodyTermsMap); + $mergedScoreMap = $this->mergeTermScoreMaps($nameTermsMap, $bodyTermsMap, $tagTermsMap); $dataArray = []; $entityId = $entity->id; diff --git a/tests/Entity/EntitySearchTest.php b/tests/Entity/EntitySearchTest.php index bd50a13ac..08fabba0c 100644 --- a/tests/Entity/EntitySearchTest.php +++ b/tests/Entity/EntitySearchTest.php @@ -334,8 +334,7 @@ class EntitySearchTest extends TestCase
TermG
']); - $entityRelationCols = ['entity_id' => $page->id, 'entity_type' => 'BookStack\\Page']; - $scoreByTerm = SearchTerm::query()->where($entityRelationCols)->pluck('score', 'term'); + $scoreByTerm = $page->searchTerms()->pluck('score', 'term'); $this->assertEquals(1, $scoreByTerm->get('TermA')); $this->assertEquals(10, $scoreByTerm->get('TermB')); @@ -354,10 +353,22 @@ class EntitySearchTest extends TestCase

TermA

']); - $entityRelationCols = ['entity_id' => $page->id, 'entity_type' => 'BookStack\\Page']; - $scoreByTerm = SearchTerm::query()->where($entityRelationCols)->pluck('score', 'term'); + $scoreByTerm = $page->searchTerms()->pluck('score', 'term'); // Scores 40 for being in the name then 1 for being in the content $this->assertEquals(41, $scoreByTerm->get('TermA')); } + + public function test_tag_names_and_values_are_indexed_for_search() + { + $page = $this->newPage(['name' => 'PageA', 'html' => '

content

', 'tags' => [ + ['name' => 'Animal', 'value' => 'MeowieCat'], + ['name' => 'SuperImportant'], + ]]); + + $scoreByTerm = $page->searchTerms()->pluck('score', 'term'); + $this->assertEquals(5, $scoreByTerm->get('MeowieCat')); + $this->assertEquals(3, $scoreByTerm->get('Animal')); + $this->assertEquals(3, $scoreByTerm->get('SuperImportant')); + } } From 7d0724e2888f768149b425efcdc185a1c7a4be02 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Fri, 12 Nov 2021 18:03:44 +0000 Subject: [PATCH 33/59] Added auto-conversion of search terms to exact values Will occur when a search term contains a character that's used to split content into search terms. Added testing to cover. --- app/Entities/Tools/SearchIndex.php | 8 ++++- app/Entities/Tools/SearchOptions.php | 47 +++++++++++++++++++++++----- tests/Entity/EntitySearchTest.php | 12 +++++++ 3 files changed, 59 insertions(+), 8 deletions(-) diff --git a/app/Entities/Tools/SearchIndex.php b/app/Entities/Tools/SearchIndex.php index 05de341f9..3c4b5a247 100644 --- a/app/Entities/Tools/SearchIndex.php +++ b/app/Entities/Tools/SearchIndex.php @@ -13,6 +13,12 @@ use Illuminate\Support\Collection; class SearchIndex { + /** + * A list of delimiter characters used to break-up parsed content into terms for indexing. + * + * @var string + */ + public static $delimiters = " \n\t.,!?:;()[]{}<>`'\""; /** * @var EntityProvider @@ -189,7 +195,7 @@ class SearchIndex protected function textToTermCountMap(string $text): array { $tokenMap = []; // {TextToken => OccurrenceCount} - $splitChars = " \n\t.,!?:;()[]{}<>`'\""; + $splitChars = static::$delimiters; $token = strtok($text, $splitChars); while ($token !== false) { diff --git a/app/Entities/Tools/SearchOptions.php b/app/Entities/Tools/SearchOptions.php index 39074fb38..9f1b9742d 100644 --- a/app/Entities/Tools/SearchOptions.php +++ b/app/Entities/Tools/SearchOptions.php @@ -57,15 +57,22 @@ class SearchOptions $instance = new SearchOptions(); $inputs = $request->only(['search', 'types', 'filters', 'exact', 'tags']); - $instance->searches = explode(' ', $inputs['search'] ?? []); - $instance->exacts = array_filter($inputs['exact'] ?? []); + + $parsedStandardTerms = static::parseStandardTermString($inputs['search'] ?? ''); + $instance->searches = $parsedStandardTerms['terms']; + $instance->exacts = $parsedStandardTerms['exacts']; + + array_push($instance->exacts, ...array_filter($inputs['exact'] ?? [])); + $instance->tags = array_filter($inputs['tags'] ?? []); + foreach (($inputs['filters'] ?? []) as $filterKey => $filterVal) { if (empty($filterVal)) { continue; } $instance->filters[$filterKey] = $filterVal === 'true' ? '' : $filterVal; } + if (isset($inputs['types']) && count($inputs['types']) < 4) { $instance->filters['type'] = implode('|', $inputs['types']); } @@ -102,11 +109,9 @@ class SearchOptions } // Parse standard terms - foreach (explode(' ', trim($searchString)) as $searchTerm) { - if ($searchTerm !== '') { - $terms['searches'][] = $searchTerm; - } - } + $parsedStandardTerms = static::parseStandardTermString($searchString); + array_push($terms['searches'], ...$parsedStandardTerms['terms']); + array_push($terms['exacts'], ...$parsedStandardTerms['exacts']); // Split filter values out $splitFilters = []; @@ -119,6 +124,34 @@ class SearchOptions return $terms; } + + /** + * Parse a standard search term string into individual search terms and + * extract any exact terms searches to be made. + * + * @return array{terms: array, exacts: array} + */ + protected static function parseStandardTermString(string $termString): array + { + $terms = explode(' ', $termString); + $indexDelimiters = SearchIndex::$delimiters; + $parsed = [ + 'terms' => [], + 'exacts' => [], + ]; + + foreach ($terms as $searchTerm) { + if ($searchTerm === '') { + continue; + } + + $parsedList = (strpbrk($searchTerm, $indexDelimiters) === false) ? 'terms' : 'exacts'; + $parsed[$parsedList][] = $searchTerm; + } + + return $parsed; + } + /** * Encode this instance to a search string. */ diff --git a/tests/Entity/EntitySearchTest.php b/tests/Entity/EntitySearchTest.php index 08fabba0c..f69dba211 100644 --- a/tests/Entity/EntitySearchTest.php +++ b/tests/Entity/EntitySearchTest.php @@ -119,6 +119,18 @@ class EntitySearchTest extends TestCase $exactSearchB->assertStatus(200)->assertDontSee($page->name); } + public function test_search_terms_with_delimiters_are_converted_to_exact_matches() + { + $this->asEditor(); + $page = $this->newPage(['name' => 'Delimiter test', 'html' => '

1.1 2,2 3?3 4:4 5;5 (8) <9> "10" \'11\' `12`

']); + $terms = explode(' ', '1.1 2,2 3?3 4:4 5;5 (8) <9> "10" \'11\' `12`'); + + foreach ($terms as $term) { + $search = $this->get('/search?term=' . urlencode($term)); + $search->assertSee($page->name); + } + } + public function test_search_filters() { $page = $this->newPage(['name' => 'My new test quaffleachits', 'html' => 'this is about an orange donkey danzorbhsing']); From f30b937bb02eea92c078ea9644e3b70bd63974d8 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Fri, 12 Nov 2021 22:57:50 +0000 Subject: [PATCH 34/59] Added search result preview text highlighting Created a new class to manage formatting of content for search results. Turned out to be quite a complex task. This only does the preview text so far, not titles or tags. Not yet tested. --- app/Entities/Tools/SearchResultsFormatter.php | 173 ++++++++++++++++++ app/Http/Controllers/SearchController.php | 11 +- resources/views/entities/list-item.blade.php | 2 +- 3 files changed, 178 insertions(+), 8 deletions(-) create mode 100644 app/Entities/Tools/SearchResultsFormatter.php diff --git a/app/Entities/Tools/SearchResultsFormatter.php b/app/Entities/Tools/SearchResultsFormatter.php new file mode 100644 index 000000000..aaa5c129d --- /dev/null +++ b/app/Entities/Tools/SearchResultsFormatter.php @@ -0,0 +1,173 @@ +setSearchPreview($result, $options); + } + } + + /** + * Update the given entity model to set attributes used for previews of the item + * primarily within search result lists. + */ + protected function setSearchPreview(Entity $entity, SearchOptions $options) + { + $textProperty = $entity->textField; + $textContent = $entity->$textProperty; + $terms = array_merge($options->exacts, $options->searches); + + $matchRefs = $this->getMatchPositions($textContent, $terms); + $mergedRefs = $this->sortAndMergeMatchPositions($matchRefs); + $content = $this->formatTextUsingMatchPositions($mergedRefs, $textContent); + + $entity->setAttribute('preview_content', new HtmlString($content)); + } + + /** + * Get positions of the given terms within the given text. + * Is in the array format of [int $startIndex => int $endIndex] where the indexes + * are positions within the provided text. + * + * @return array + */ + protected function getMatchPositions(string $text, array $terms): array + { + $matchRefs = []; + $text = strtolower($text); + + foreach ($terms as $term) { + $offset = 0; + $term = strtolower($term); + $pos = strpos($text, $term, $offset); + while ($pos !== false) { + $end = $pos + strlen($term); + $matchRefs[$pos] = $end; + $offset = $end; + $pos = strpos($text, $term, $offset); + } + } + + return $matchRefs; + } + + /** + * Sort the given match positions before merging them where they're + * adjacent or where they overlap. + * + * @param array $matchPositions + * @return array + */ + protected function sortAndMergeMatchPositions(array $matchPositions): array + { + ksort($matchPositions); + $mergedRefs = []; + $lastStart = 0; + $lastEnd = 0; + + foreach ($matchPositions as $start => $end) { + if ($start > $lastEnd) { + $mergedRefs[$start] = $end; + $lastStart = $start; + $lastEnd = $end; + } else if ($end > $lastEnd) { + $mergedRefs[$lastStart] = $end; + $lastEnd = $end; + } + } + + return $mergedRefs; + } + + /** + * Format the given original text, returning a version where terms are highlighted within. + * Returned content is in HTML text format. + */ + protected function formatTextUsingMatchPositions(array $matchPositions, string $originalText): string + { + $contextRange = 32; + $targetLength = 260; + $maxEnd = strlen($originalText); + $lastEnd = 0; + $firstStart = null; + $content = ''; + + foreach ($matchPositions as $start => $end) { + // Get our outer text ranges for the added context we want to show upon the result. + $contextStart = max($start - $contextRange, 0, $lastEnd); + $contextEnd = min($end + $contextRange, $maxEnd); + + // Adjust the start if we're going to be touching the previous match. + $startDiff = $start - $lastEnd; + if ($startDiff < 0) { + $contextStart = $start; + $content = substr($content, 0, strlen($content) + $startDiff); + } + + // Add ellipsis between results + if ($contextStart !== 0 && $contextStart !== $start) { + $content .= ' ...'; + } + + // Add our content including the bolded matching text + $content .= e(substr($originalText, $contextStart, $start - $contextStart)); + $content .= '' . e(substr($originalText, $start, $end - $start)) . ''; + $content .= e(substr($originalText, $end, $contextEnd - $end)); + + // Update our last end position + $lastEnd = $contextEnd; + + // Update the first start position if it's not already been set + if (is_null($firstStart)) { + $firstStart = $contextStart; + } + + // Stop if we're near our target + if (strlen($content) >= $targetLength - 10) { + break; + } + } + + // Just copy out the content if we haven't moved along anywhere. + if ($lastEnd === 0) { + $content = e(substr($originalText, 0, $targetLength)); + $lastEnd = $targetLength; + } + + // Pad out the end if we're low + $remainder = $targetLength - strlen($content); + if ($remainder > 10) { + $content .= e(substr($originalText, $lastEnd, $remainder)); + $lastEnd += $remainder; + } + + // Pad out the start if we're still low + $remainder = $targetLength - strlen($content); + $firstStart = $firstStart ?: 0; + if ($remainder > 10 && $firstStart !== 0) { + $padStart = max(0, $firstStart - $remainder); + $content = ($padStart === 0 ? '' : '...') . e(substr($originalText, $padStart, $firstStart - $padStart)) . substr($content, 4); + } + + // Add ellipsis if we're not at the end + if ($lastEnd < $maxEnd) { + $content .= '...'; + } + + return $content; + } + +} \ No newline at end of file diff --git a/app/Http/Controllers/SearchController.php b/app/Http/Controllers/SearchController.php index d12c23b5a..040c04ece 100644 --- a/app/Http/Controllers/SearchController.php +++ b/app/Http/Controllers/SearchController.php @@ -4,8 +4,8 @@ namespace BookStack\Http\Controllers; use BookStack\Entities\Queries\Popular; use BookStack\Entities\Tools\SearchOptions; +use BookStack\Entities\Tools\SearchResultsFormatter; use BookStack\Entities\Tools\SearchRunner; -use BookStack\Entities\Tools\ShelfContext; use BookStack\Entities\Tools\SiblingFetcher; use Illuminate\Http\Request; @@ -14,18 +14,14 @@ class SearchController extends Controller protected $searchRunner; protected $entityContextManager; - public function __construct( - SearchRunner $searchRunner, - ShelfContext $entityContextManager - ) { + public function __construct(SearchRunner $searchRunner) { $this->searchRunner = $searchRunner; - $this->entityContextManager = $entityContextManager; } /** * Searches all entities. */ - public function search(Request $request) + public function search(Request $request, SearchResultsFormatter $formatter) { $searchOpts = SearchOptions::fromRequest($request); $fullSearchString = $searchOpts->toString(); @@ -35,6 +31,7 @@ class SearchController extends Controller $nextPageLink = url('/search?term=' . urlencode($fullSearchString) . '&page=' . ($page + 1)); $results = $this->searchRunner->searchEntities($searchOpts, 'all', $page, 20); + $formatter->format($results['results']->all(), $searchOpts); return view('search.all', [ 'entities' => $results['results'], diff --git a/resources/views/entities/list-item.blade.php b/resources/views/entities/list-item.blade.php index c757b0691..aa4f6c1e8 100644 --- a/resources/views/entities/list-item.blade.php +++ b/resources/views/entities/list-item.blade.php @@ -11,7 +11,7 @@ @endif @endif -

{{ $entity->getExcerpt() }}

+

{{ $entity->preview_content ?? $entity->getExcerpt() }}

@if(($showTags ?? false) && $entity->tags->count() > 0) From ab4e99bb187fb4273dcad2fa3c731ba46e49a585 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 13 Nov 2021 12:44:27 +0000 Subject: [PATCH 35/59] Added name highlighting in search results --- app/Entities/Tools/SearchResultsFormatter.php | 14 ++++++++++---- resources/views/entities/list-item-basic.blade.php | 2 +- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/app/Entities/Tools/SearchResultsFormatter.php b/app/Entities/Tools/SearchResultsFormatter.php index aaa5c129d..24dc820a4 100644 --- a/app/Entities/Tools/SearchResultsFormatter.php +++ b/app/Entities/Tools/SearchResultsFormatter.php @@ -30,11 +30,17 @@ class SearchResultsFormatter $textContent = $entity->$textProperty; $terms = array_merge($options->exacts, $options->searches); - $matchRefs = $this->getMatchPositions($textContent, $terms); - $mergedRefs = $this->sortAndMergeMatchPositions($matchRefs); - $content = $this->formatTextUsingMatchPositions($mergedRefs, $textContent); + $originalContentByNewAttribute = [ + 'preview_name' => $entity->name, + 'preview_content' => $textContent, + ]; - $entity->setAttribute('preview_content', new HtmlString($content)); + foreach ($originalContentByNewAttribute as $attributeName => $content) { + $matchRefs = $this->getMatchPositions($content, $terms); + $mergedRefs = $this->sortAndMergeMatchPositions($matchRefs); + $formatted = $this->formatTextUsingMatchPositions($mergedRefs, $content); + $entity->setAttribute($attributeName, new HtmlString($formatted)); + } } /** diff --git a/resources/views/entities/list-item-basic.blade.php b/resources/views/entities/list-item-basic.blade.php index 2ec4bee5c..398c33b93 100644 --- a/resources/views/entities/list-item-basic.blade.php +++ b/resources/views/entities/list-item-basic.blade.php @@ -2,7 +2,7 @@ @icon($type)
-

{{ $entity->name }}

+

{{ $entity->preview_name ?? $entity->name }}

{{ $slot ?? '' }}
\ No newline at end of file From 339518e2a6ad1cee717d821afe9238d0ac9792ed Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 13 Nov 2021 13:02:32 +0000 Subject: [PATCH 36/59] Added tag highlighting in search Using basic match of name or value containing a general term. --- app/Entities/Tools/SearchResultsFormatter.php | 29 +++++++++++++++++++ resources/sass/_blocks.scss | 4 +++ resources/views/entities/tag.blade.php | 8 ++--- 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/app/Entities/Tools/SearchResultsFormatter.php b/app/Entities/Tools/SearchResultsFormatter.php index 24dc820a4..1ddee5830 100644 --- a/app/Entities/Tools/SearchResultsFormatter.php +++ b/app/Entities/Tools/SearchResultsFormatter.php @@ -2,6 +2,7 @@ namespace BookStack\Entities\Tools; +use BookStack\Actions\Tag; use BookStack\Entities\Models\Entity; use Illuminate\Support\HtmlString; @@ -41,6 +42,34 @@ class SearchResultsFormatter $formatted = $this->formatTextUsingMatchPositions($mergedRefs, $content); $entity->setAttribute($attributeName, new HtmlString($formatted)); } + + $tags = $entity->relationLoaded('tags') ? $entity->tags->all() : []; + $this->highlightTagsContainingTerms($tags, $terms); + } + + /** + * Highlight tags which match the given terms. + * @param Tag[] $tags + * @param string[] $terms + */ + protected function highlightTagsContainingTerms(array $tags, array $terms): void + { + foreach ($tags as $tag) { + $tagName = strtolower($tag->name); + $tagValue = strtolower($tag->value); + + foreach ($terms as $term) { + $termLower = strtolower($term); + + if (strpos($tagName, $termLower) !== false) { + $tag->setAttribute('highlight_name', true); + } + + if (strpos($tagValue, $termLower) !== false) { + $tag->setAttribute('highlight_value', true); + } + } + } } /** diff --git a/resources/sass/_blocks.scss b/resources/sass/_blocks.scss index ef03699f1..ae3e7a441 100644 --- a/resources/sass/_blocks.scss +++ b/resources/sass/_blocks.scss @@ -262,6 +262,10 @@ } } +.tag-name.highlight, .tag-value.highlight { + font-weight: bold; +} + .tag-list div:last-child .tag-item { margin-bottom: 0; } diff --git a/resources/views/entities/tag.blade.php b/resources/views/entities/tag.blade.php index 057c70921..de4750c13 100644 --- a/resources/views/entities/tag.blade.php +++ b/resources/views/entities/tag.blade.php @@ -1,9 +1,9 @@
@if($linked ?? true) - - @if($tag->value) @endif + + @if($tag->value) @endif @else -
@icon('tag'){{ $tag->name }}
- @if($tag->value)
{{$tag->value}}
@endif +
@icon('tag'){{ $tag->name }}
+ @if($tag->value)
{{$tag->value}}
@endif @endif
\ No newline at end of file From 63d8d72d7ecdba31903bee4c2295f2d0a2149e0d Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 13 Nov 2021 13:26:11 +0000 Subject: [PATCH 37/59] Added testing to cover search result highlighting --- tests/Entity/EntitySearchTest.php | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/tests/Entity/EntitySearchTest.php b/tests/Entity/EntitySearchTest.php index f69dba211..95d474629 100644 --- a/tests/Entity/EntitySearchTest.php +++ b/tests/Entity/EntitySearchTest.php @@ -383,4 +383,32 @@ class EntitySearchTest extends TestCase $this->assertEquals(3, $scoreByTerm->get('Animal')); $this->assertEquals(3, $scoreByTerm->get('SuperImportant')); } + + public function test_matching_terms_in_search_results_are_highlighted() + { + $this->newPage(['name' => 'My Meowie Cat', 'html' => '

A superimportant page about meowieable animals

', 'tags' => [ + ['name' => 'Animal', 'value' => 'MeowieCat'], + ['name' => 'SuperImportant'], + ]]); + + $search = $this->asEditor()->get('/search?term=SuperImportant+Meowie'); + // Title + $search->assertSee('My Meowie Cat', false); + // Content + $search->assertSee('A superimportant page about meowieable animals', false); + // Tag name + $search->assertElementContains('.tag-name.highlight', 'SuperImportant'); + // Tag value + $search->assertElementContains('.tag-value.highlight', 'MeowieCat'); + } + + public function test_html_entities_in_item_details_remains_escaped_in_search_results() + { + $this->newPage(['name' => 'My TestPageContent', 'html' => '

My supercool <great> TestPageContent page

']); + + $search = $this->asEditor()->get('/search?term=TestPageContent'); + $search->assertSee('My <cool> TestPageContent', false); + $search->assertSee('My supercool <great> TestPageContent page', false); + } + } From 2633b94deb760dc2f183a612b68e311f57795ce5 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 13 Nov 2021 13:28:17 +0000 Subject: [PATCH 38/59] Applied StyleCI changes --- app/Entities/Tools/SearchIndex.php | 9 ++++----- app/Entities/Tools/SearchOptions.php | 3 +-- app/Entities/Tools/SearchResultsFormatter.php | 15 ++++++++------- app/Entities/Tools/SearchRunner.php | 6 +++--- app/Http/Controllers/SearchController.php | 3 ++- tests/Entity/EntitySearchTest.php | 2 -- 6 files changed, 18 insertions(+), 20 deletions(-) diff --git a/app/Entities/Tools/SearchIndex.php b/app/Entities/Tools/SearchIndex.php index 3c4b5a247..702606be9 100644 --- a/app/Entities/Tools/SearchIndex.php +++ b/app/Entities/Tools/SearchIndex.php @@ -175,7 +175,7 @@ class SearchIndex $names = []; $values = []; - foreach($tags as $tag) { + foreach ($tags as $tag) { $names[] = $tag->name; $values[] = $tag->value; } @@ -233,17 +233,16 @@ class SearchIndex $entityType = $entity->getMorphClass(); foreach ($mergedScoreMap as $term => $score) { $dataArray[] = [ - 'term' => $term, - 'score' => $score, + 'term' => $term, + 'score' => $score, 'entity_type' => $entityType, - 'entity_id' => $entityId, + 'entity_id' => $entityId, ]; } return $dataArray; } - /** * For the given term data arrays, Merge their contents by term * while combining any scores. diff --git a/app/Entities/Tools/SearchOptions.php b/app/Entities/Tools/SearchOptions.php index 9f1b9742d..99271058e 100644 --- a/app/Entities/Tools/SearchOptions.php +++ b/app/Entities/Tools/SearchOptions.php @@ -124,7 +124,6 @@ class SearchOptions return $terms; } - /** * Parse a standard search term string into individual search terms and * extract any exact terms searches to be made. @@ -136,7 +135,7 @@ class SearchOptions $terms = explode(' ', $termString); $indexDelimiters = SearchIndex::$delimiters; $parsed = [ - 'terms' => [], + 'terms' => [], 'exacts' => [], ]; diff --git a/app/Entities/Tools/SearchResultsFormatter.php b/app/Entities/Tools/SearchResultsFormatter.php index 1ddee5830..2898520ab 100644 --- a/app/Entities/Tools/SearchResultsFormatter.php +++ b/app/Entities/Tools/SearchResultsFormatter.php @@ -8,10 +8,10 @@ use Illuminate\Support\HtmlString; class SearchResultsFormatter { - /** * For the given array of entities, Prepare the models to be shown in search result * output. This sets a series of additional attributes. + * * @param Entity[] $results */ public function format(array $results, SearchOptions $options): void @@ -32,7 +32,7 @@ class SearchResultsFormatter $terms = array_merge($options->exacts, $options->searches); $originalContentByNewAttribute = [ - 'preview_name' => $entity->name, + 'preview_name' => $entity->name, 'preview_content' => $textContent, ]; @@ -49,7 +49,8 @@ class SearchResultsFormatter /** * Highlight tags which match the given terms. - * @param Tag[] $tags + * + * @param Tag[] $tags * @param string[] $terms */ protected function highlightTagsContainingTerms(array $tags, array $terms): void @@ -104,6 +105,7 @@ class SearchResultsFormatter * adjacent or where they overlap. * * @param array $matchPositions + * * @return array */ protected function sortAndMergeMatchPositions(array $matchPositions): array @@ -118,7 +120,7 @@ class SearchResultsFormatter $mergedRefs[$start] = $end; $lastStart = $start; $lastEnd = $end; - } else if ($end > $lastEnd) { + } elseif ($end > $lastEnd) { $mergedRefs[$lastStart] = $end; $lastEnd = $end; } @@ -194,7 +196,7 @@ class SearchResultsFormatter $firstStart = $firstStart ?: 0; if ($remainder > 10 && $firstStart !== 0) { $padStart = max(0, $firstStart - $remainder); - $content = ($padStart === 0 ? '' : '...') . e(substr($originalText, $padStart, $firstStart - $padStart)) . substr($content, 4); + $content = ($padStart === 0 ? '' : '...') . e(substr($originalText, $padStart, $firstStart - $padStart)) . substr($content, 4); } // Add ellipsis if we're not at the end @@ -204,5 +206,4 @@ class SearchResultsFormatter return $content; } - -} \ No newline at end of file +} diff --git a/app/Entities/Tools/SearchRunner.php b/app/Entities/Tools/SearchRunner.php index afe5e9f19..f6da871f4 100644 --- a/app/Entities/Tools/SearchRunner.php +++ b/app/Entities/Tools/SearchRunner.php @@ -141,13 +141,13 @@ class SearchRunner $relations = ['tags']; if ($entityModelInstance instanceof BookChild) { - $relations['book'] = function(BelongsTo $query) { + $relations['book'] = function (BelongsTo $query) { $query->visible(); }; } if ($entityModelInstance instanceof Page) { - $relations['chapter'] = function(BelongsTo $query) { + $relations['chapter'] = function (BelongsTo $query) { $query->visible(); }; } @@ -310,7 +310,7 @@ class SearchRunner if (empty($termCounts)) { return []; } - + $multipliers = []; $max = max(array_values($termCounts)); diff --git a/app/Http/Controllers/SearchController.php b/app/Http/Controllers/SearchController.php index 040c04ece..6b2be5a2d 100644 --- a/app/Http/Controllers/SearchController.php +++ b/app/Http/Controllers/SearchController.php @@ -14,7 +14,8 @@ class SearchController extends Controller protected $searchRunner; protected $entityContextManager; - public function __construct(SearchRunner $searchRunner) { + public function __construct(SearchRunner $searchRunner) + { $this->searchRunner = $searchRunner; } diff --git a/tests/Entity/EntitySearchTest.php b/tests/Entity/EntitySearchTest.php index 95d474629..f935f1331 100644 --- a/tests/Entity/EntitySearchTest.php +++ b/tests/Entity/EntitySearchTest.php @@ -7,7 +7,6 @@ use BookStack\Entities\Models\Book; use BookStack\Entities\Models\Bookshelf; use BookStack\Entities\Models\Chapter; use BookStack\Entities\Models\Page; -use BookStack\Entities\Models\SearchTerm; use Tests\TestCase; class EntitySearchTest extends TestCase @@ -410,5 +409,4 @@ class EntitySearchTest extends TestCase $search->assertSee('My <cool> TestPageContent', false); $search->assertSee('My supercool <great> TestPageContent page', false); } - } From 221458ccfd70e1b2c6791018792732b247e55d65 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 13 Nov 2021 13:43:41 +0000 Subject: [PATCH 39/59] Fixed failing tests due to search highlighting changes --- app/Entities/Tools/SearchIndex.php | 2 +- tests/Entity/EntitySearchTest.php | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/app/Entities/Tools/SearchIndex.php b/app/Entities/Tools/SearchIndex.php index 702606be9..d748c1695 100644 --- a/app/Entities/Tools/SearchIndex.php +++ b/app/Entities/Tools/SearchIndex.php @@ -223,7 +223,7 @@ class SearchIndex if ($entity instanceof Page) { $bodyTermsMap = $this->generateTermScoreMapFromHtml($entity->html); } else { - $bodyTermsMap = $this->generateTermScoreMapFromText($entity->description, $entity->searchFactor); + $bodyTermsMap = $this->generateTermScoreMapFromText($entity->description ?? '', $entity->searchFactor); } $mergedScoreMap = $this->mergeTermScoreMaps($nameTermsMap, $bodyTermsMap, $tagTermsMap); diff --git a/tests/Entity/EntitySearchTest.php b/tests/Entity/EntitySearchTest.php index f935f1331..0ef46d3a7 100644 --- a/tests/Entity/EntitySearchTest.php +++ b/tests/Entity/EntitySearchTest.php @@ -18,15 +18,20 @@ class EntitySearchTest extends TestCase $search = $this->asEditor()->get('/search?term=' . urlencode($page->name)); $search->assertSee('Search Results'); - $search->assertSee($page->name); + + $title = strip_tags($search->getElementHtml('.entity-list-item-name')); + $this->assertEquals($page->name, $title); } public function test_bookshelf_search() { - $shelf = Bookshelf::first(); + /** @var Bookshelf $shelf */ + $shelf = Bookshelf::query()->first(); $search = $this->asEditor()->get('/search?term=' . urlencode(mb_substr($shelf->name, 0, 3)) . ' {type:bookshelf}'); $search->assertStatus(200); - $search->assertSee($shelf->name); + + $title = strip_tags($search->getElementHtml('.entity-list-item-name')); + $this->assertEquals($shelf->name, $title); } public function test_invalid_page_search() From 755dc99c724d63ed7feb9ccc1ff607c2579a9f75 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 13 Nov 2021 14:37:40 +0000 Subject: [PATCH 40/59] Made further tweaks to search results formatting - Updated page names to not be limited to a certain length. - Added better start/end fill logic. - Prevented tags from being counted towards the target content length desired from the formatter. --- app/Entities/Tools/SearchResultsFormatter.php | 46 +++++++++++++++---- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/app/Entities/Tools/SearchResultsFormatter.php b/app/Entities/Tools/SearchResultsFormatter.php index 2898520ab..a30c96003 100644 --- a/app/Entities/Tools/SearchResultsFormatter.php +++ b/app/Entities/Tools/SearchResultsFormatter.php @@ -37,9 +37,10 @@ class SearchResultsFormatter ]; foreach ($originalContentByNewAttribute as $attributeName => $content) { + $targetLength = ($attributeName === 'preview_name') ? 0 : 260; $matchRefs = $this->getMatchPositions($content, $terms); $mergedRefs = $this->sortAndMergeMatchPositions($matchRefs); - $formatted = $this->formatTextUsingMatchPositions($mergedRefs, $content); + $formatted = $this->formatTextUsingMatchPositions($mergedRefs, $content, $targetLength); $entity->setAttribute($attributeName, new HtmlString($formatted)); } @@ -132,15 +133,25 @@ class SearchResultsFormatter /** * Format the given original text, returning a version where terms are highlighted within. * Returned content is in HTML text format. + * A given $targetLength of 0 asserts no target length limit. + * + * This is a complex function but written to be relatively efficient, going through the term matches in order + * so that we're only doing a one-time loop through of the matches. There is no further searching + * done within here. */ - protected function formatTextUsingMatchPositions(array $matchPositions, string $originalText): string + protected function formatTextUsingMatchPositions(array $matchPositions, string $originalText, int $targetLength): string { $contextRange = 32; - $targetLength = 260; $maxEnd = strlen($originalText); $lastEnd = 0; $firstStart = null; + $fetchAll = ($targetLength === 0); $content = ''; + $contentTextLength = 0; + + if ($fetchAll) { + $targetLength = $maxEnd * 2; + } foreach ($matchPositions as $start => $end) { // Get our outer text ranges for the added context we want to show upon the result. @@ -151,18 +162,30 @@ class SearchResultsFormatter $startDiff = $start - $lastEnd; if ($startDiff < 0) { $contextStart = $start; + // Trims off '$startDiff' number of characters to bring it back to the start + // if this current match zone. $content = substr($content, 0, strlen($content) + $startDiff); + $contentTextLength += $startDiff; } // Add ellipsis between results - if ($contextStart !== 0 && $contextStart !== $start) { + if (!$fetchAll && $contextStart !== 0 && $contextStart !== $start) { $content .= ' ...'; + $contentTextLength += 4; + } else if ($fetchAll) { + // Or fill in gap since the previous match + $fillLength = $contextStart - $lastEnd; + $content .= e(substr($originalText, $lastEnd, $fillLength)); + $contentTextLength += $fillLength; } // Add our content including the bolded matching text $content .= e(substr($originalText, $contextStart, $start - $contextStart)); + $contentTextLength += $start - $contextStart; $content .= '' . e(substr($originalText, $start, $end - $start)) . ''; + $contentTextLength += $end - $start; $content .= e(substr($originalText, $end, $contextEnd - $end)); + $contentTextLength += $contextEnd - $end; // Update our last end position $lastEnd = $contextEnd; @@ -173,7 +196,7 @@ class SearchResultsFormatter } // Stop if we're near our target - if (strlen($content) >= $targetLength - 10) { + if ($contentTextLength >= $targetLength - 10) { break; } } @@ -181,20 +204,23 @@ class SearchResultsFormatter // Just copy out the content if we haven't moved along anywhere. if ($lastEnd === 0) { $content = e(substr($originalText, 0, $targetLength)); + $contentTextLength = $targetLength; $lastEnd = $targetLength; } // Pad out the end if we're low - $remainder = $targetLength - strlen($content); + $remainder = $targetLength - $contentTextLength; if ($remainder > 10) { - $content .= e(substr($originalText, $lastEnd, $remainder)); - $lastEnd += $remainder; + $padEndLength = min($maxEnd - $lastEnd, $remainder); + $content .= e(substr($originalText, $lastEnd, $padEndLength)); + $lastEnd += $padEndLength; + $contentTextLength += $padEndLength; } // Pad out the start if we're still low - $remainder = $targetLength - strlen($content); + $remainder = $targetLength - $contentTextLength; $firstStart = $firstStart ?: 0; - if ($remainder > 10 && $firstStart !== 0) { + if (!$fetchAll && $remainder > 10 && $firstStart !== 0) { $padStart = max(0, $firstStart - $remainder); $content = ($padStart === 0 ? '' : '...') . e(substr($originalText, $padStart, $firstStart - $padStart)) . substr($content, 4); } From 21d3620ef07e5a405c9aaeb118ced312aece6a85 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 13 Nov 2021 14:51:59 +0000 Subject: [PATCH 41/59] Attempted to make test a bit less flaky --- tests/Entity/EntitySearchTest.php | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/tests/Entity/EntitySearchTest.php b/tests/Entity/EntitySearchTest.php index 0ef46d3a7..6929adc74 100644 --- a/tests/Entity/EntitySearchTest.php +++ b/tests/Entity/EntitySearchTest.php @@ -18,20 +18,17 @@ class EntitySearchTest extends TestCase $search = $this->asEditor()->get('/search?term=' . urlencode($page->name)); $search->assertSee('Search Results'); - - $title = strip_tags($search->getElementHtml('.entity-list-item-name')); - $this->assertEquals($page->name, $title); + $search->assertSeeText($page->name, true); } public function test_bookshelf_search() { /** @var Bookshelf $shelf */ $shelf = Bookshelf::query()->first(); - $search = $this->asEditor()->get('/search?term=' . urlencode(mb_substr($shelf->name, 0, 3)) . ' {type:bookshelf}'); - $search->assertStatus(200); - $title = strip_tags($search->getElementHtml('.entity-list-item-name')); - $this->assertEquals($shelf->name, $title); + $search = $this->asEditor()->get('/search?term=' . urlencode($shelf->name) . ' {type:bookshelf}'); + $search->assertSee('Search Results'); + $search->assertSeeText($shelf->name, true); } public function test_invalid_page_search() From fc7bd57dc804921cc89f7add1ce07dd29c3736d1 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 13 Nov 2021 15:04:04 +0000 Subject: [PATCH 42/59] Fixed occurances of altered titles in search results --- app/Entities/Tools/SearchResultsFormatter.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/app/Entities/Tools/SearchResultsFormatter.php b/app/Entities/Tools/SearchResultsFormatter.php index a30c96003..31a8f81c9 100644 --- a/app/Entities/Tools/SearchResultsFormatter.php +++ b/app/Entities/Tools/SearchResultsFormatter.php @@ -141,11 +141,12 @@ class SearchResultsFormatter */ protected function formatTextUsingMatchPositions(array $matchPositions, string $originalText, int $targetLength): string { - $contextRange = 32; $maxEnd = strlen($originalText); - $lastEnd = 0; - $firstStart = null; $fetchAll = ($targetLength === 0); + $contextLength = ($fetchAll ? 0 : 32); + + $firstStart = null; + $lastEnd = 0; $content = ''; $contentTextLength = 0; @@ -155,8 +156,8 @@ class SearchResultsFormatter foreach ($matchPositions as $start => $end) { // Get our outer text ranges for the added context we want to show upon the result. - $contextStart = max($start - $contextRange, 0, $lastEnd); - $contextEnd = min($end + $contextRange, $maxEnd); + $contextStart = max($start - $contextLength, 0, $lastEnd); + $contextEnd = min($end + $contextLength, $maxEnd); // Adjust the start if we're going to be touching the previous match. $startDiff = $start - $lastEnd; From 89f7f8e2599d6155ebe7ee725fe5dc13e88467ea Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 14 Nov 2021 11:50:13 +0000 Subject: [PATCH 43/59] Hid skip-to-content for print media Fixes #3051 --- resources/views/common/skip-to-content.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/common/skip-to-content.blade.php b/resources/views/common/skip-to-content.blade.php index b63573d76..9b8db1142 100644 --- a/resources/views/common/skip-to-content.blade.php +++ b/resources/views/common/skip-to-content.blade.php @@ -1 +1 @@ -{{ trans('common.skip_to_main_content') }} \ No newline at end of file +{{ trans('common.skip_to_main_content') }} \ No newline at end of file From 8e71cd9bacfc12c50d1f9ed9ca379b85beece940 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 14 Nov 2021 12:17:22 +0000 Subject: [PATCH 44/59] Fixed issue where markdown drafts showed as HTML Markdown content was not being stored, only the sent HTML representation, causing the draft to show as HTML upon next edit. Added test to cover. Fixes #3054 --- app/Entities/Repos/PageRepo.php | 4 +--- tests/Entity/PageDraftTest.php | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/app/Entities/Repos/PageRepo.php b/app/Entities/Repos/PageRepo.php index 98fe4ef55..f66f2beb8 100644 --- a/app/Entities/Repos/PageRepo.php +++ b/app/Entities/Repos/PageRepo.php @@ -252,9 +252,7 @@ class PageRepo { // If the page itself is a draft simply update that if ($page->draft) { - if (isset($input['html'])) { - (new PageContent($page))->setNewHTML($input['html']); - } + $this->updateTemplateStatusAndContentFromInput($page, $input); $page->fill($input); $page->save(); diff --git a/tests/Entity/PageDraftTest.php b/tests/Entity/PageDraftTest.php index 9e2ceff51..ec6707bc5 100644 --- a/tests/Entity/PageDraftTest.php +++ b/tests/Entity/PageDraftTest.php @@ -178,4 +178,30 @@ class PageDraftTest extends TestCase 'html' => $page->html, ]); } + + public function test_updating_page_draft_with_markdown_retains_markdown_content() + { + /** @var Book $book */ + $book = Book::query()->first(); + $this->asEditor()->get($book->getUrl('/create-page')); + /** @var Page $draft */ + $draft = Page::query()->where('draft', '=', true)->where('book_id', '=', $book->id)->firstOrFail(); + + $resp = $this->put('/ajax/page/' . $draft->id . '/save-draft', [ + 'name' => 'My updated draft', + 'markdown' => "# My markdown page\n\n[A link](https://example.com)", + 'html' => '

checking markdown takes priority over this

' + ]); + $resp->assertOk(); + + $this->assertDatabaseHas('pages', [ + 'id' => $draft->id, + 'draft' => true, + 'name' => 'My updated draft', + 'markdown' => "# My markdown page\n\n[A link](https://example.com)", + ]); + + $draft->refresh(); + $this->assertStringContainsString('href="https://example.com"', $draft->html); + } } From 2e49b1617743ee844b5eb63d0e8fd6bca6343d12 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 14 Nov 2021 15:07:13 +0000 Subject: [PATCH 45/59] Prevented created/update_by filters be wiped in search Updating filters via sidebar would wipe the created_by/update_by filters since these were not part of the sidebar filter form. This adds them, if existing, as hidden inputs. Includes tests to cover. Closes #2736 --- resources/views/search/all.blade.php | 7 +++++++ tests/Entity/EntitySearchTest.php | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/resources/views/search/all.blade.php b/resources/views/search/all.blade.php index b9adccca7..85e6d1b7b 100644 --- a/resources/views/search/all.blade.php +++ b/resources/views/search/all.blade.php @@ -61,6 +61,13 @@ @include('search.parts.date-filter', ['name' => 'created_after', 'filters' => $options->filters]) @include('search.parts.date-filter', ['name' => 'created_before', 'filters' => $options->filters]) + @if(isset($options->filters['created_by'])) + + @endif + @if(isset($options->filters['updated_by'])) + + @endif + diff --git a/tests/Entity/EntitySearchTest.php b/tests/Entity/EntitySearchTest.php index 6929adc74..2b7bfd08d 100644 --- a/tests/Entity/EntitySearchTest.php +++ b/tests/Entity/EntitySearchTest.php @@ -411,4 +411,11 @@ class EntitySearchTest extends TestCase $search->assertSee('My <cool> TestPageContent', false); $search->assertSee('My supercool <great> TestPageContent page', false); } + + public function test_searches_with_user_filters_adds_them_into_advanced_search_form() + { + $resp = $this->asEditor()->get('/search?term=' . urlencode('test {updated_by:me} {created_by:dan}')); + $resp->assertElementExists('form input[type="hidden"][name="filters[updated_by]"][value="me"]'); + $resp->assertElementExists('form input[type="hidden"][name="filters[created_by]"][value="dan"]'); + } } From 7025cb38df62d0b9cd2c211dc2f0edc31386009f Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 14 Nov 2021 15:16:18 +0000 Subject: [PATCH 46/59] Removed prefix route groups, applyed styleci changes Removing prefix route groups out of visual preference. Those don't really save much and I prefer seeing the complete paths when going down the list to better guage where I am. --- app/Entities/Tools/SearchResultsFormatter.php | 2 +- routes/web.php | 248 +++++++++--------- tests/Entity/PageDraftTest.php | 10 +- 3 files changed, 127 insertions(+), 133 deletions(-) diff --git a/app/Entities/Tools/SearchResultsFormatter.php b/app/Entities/Tools/SearchResultsFormatter.php index 31a8f81c9..5dbcfb663 100644 --- a/app/Entities/Tools/SearchResultsFormatter.php +++ b/app/Entities/Tools/SearchResultsFormatter.php @@ -173,7 +173,7 @@ class SearchResultsFormatter if (!$fetchAll && $contextStart !== 0 && $contextStart !== $start) { $content .= ' ...'; $contentTextLength += 4; - } else if ($fetchAll) { + } elseif ($fetchAll) { // Or fill in gap since the previous match $fillLength = $contextStart - $lastEnd; $content .= e(substr($originalText, $lastEnd, $fillLength)); diff --git a/routes/web.php b/routes/web.php index 646201d55..854ec2337 100644 --- a/routes/web.php +++ b/routes/web.php @@ -48,93 +48,89 @@ Route::middleware('auth')->group(function () { // Shelves Route::get('/create-shelf', [BookshelfController::class, 'create']); - Route::prefix('shelves')->group(function () { - Route::get('/', [BookshelfController::class, 'index']); - Route::post('/', [BookshelfController::class, 'store']); - Route::get('/{slug}/edit', [BookshelfController::class, 'edit']); - Route::get('/{slug}/delete', [BookshelfController::class, 'showDelete']); - Route::get('/{slug}', [BookshelfController::class, 'show']); - Route::put('/{slug}', [BookshelfController::class, 'update']); - Route::delete('/{slug}', [BookshelfController::class, 'destroy']); - Route::get('/{slug}/permissions', [BookshelfController::class, 'showPermissions']); - Route::put('/{slug}/permissions', [BookshelfController::class, 'permissions']); - Route::post('/{slug}/copy-permissions', [BookshelfController::class, 'copyPermissions']); - - Route::get('/{shelfSlug}/create-book', [BookController::class, 'create']); - Route::post('/{shelfSlug}/create-book', [BookController::class, 'store']); - }); + Route::get('/shelves/', [BookshelfController::class, 'index']); + Route::post('/shelves/', [BookshelfController::class, 'store']); + Route::get('/shelves/{slug}/edit', [BookshelfController::class, 'edit']); + Route::get('/shelves/{slug}/delete', [BookshelfController::class, 'showDelete']); + Route::get('/shelves/{slug}', [BookshelfController::class, 'show']); + Route::put('/shelves/{slug}', [BookshelfController::class, 'update']); + Route::delete('/shelves/{slug}', [BookshelfController::class, 'destroy']); + Route::get('/shelves/{slug}/permissions', [BookshelfController::class, 'showPermissions']); + Route::put('/shelves/{slug}/permissions', [BookshelfController::class, 'permissions']); + Route::post('/shelves/{slug}/copy-permissions', [BookshelfController::class, 'copyPermissions']); + // Book Creation + Route::get('/shelves/{shelfSlug}/create-book', [BookController::class, 'create']); + Route::post('/shelves/{shelfSlug}/create-book', [BookController::class, 'store']); Route::get('/create-book', [BookController::class, 'create']); - Route::prefix('books')->group(function () { - // Books - Route::get('/', [BookController::class, 'index']); - Route::post('/', [BookController::class, 'store']); - Route::get('/{slug}/edit', [BookController::class, 'edit']); - Route::put('/{slug}', [BookController::class, 'update']); - Route::delete('/{id}', [BookController::class, 'destroy']); - Route::get('/{slug}/sort-item', [BookSortController::class, 'showItem']); - Route::get('/{slug}', [BookController::class, 'show']); - Route::get('/{bookSlug}/permissions', [BookController::class, 'showPermissions']); - Route::put('/{bookSlug}/permissions', [BookController::class, 'permissions']); - Route::get('/{slug}/delete', [BookController::class, 'showDelete']); - Route::get('/{bookSlug}/sort', [BookSortController::class, 'show']); - Route::put('/{bookSlug}/sort', [BookSortController::class, 'update']); - Route::get('/{bookSlug}/export/html', [BookExportController::class, 'html']); - Route::get('/{bookSlug}/export/pdf', [BookExportController::class, 'pdf']); - Route::get('/{bookSlug}/export/markdown', [BookExportController::class, 'markdown']); - Route::get('/{bookSlug}/export/zip', [BookExportController::class, 'zip']); - Route::get('/{bookSlug}/export/plaintext', [BookExportController::class, 'plainText']); + // Books + Route::get('/books/', [BookController::class, 'index']); + Route::post('/books/', [BookController::class, 'store']); + Route::get('/books/{slug}/edit', [BookController::class, 'edit']); + Route::put('/books/{slug}', [BookController::class, 'update']); + Route::delete('/books/{id}', [BookController::class, 'destroy']); + Route::get('/books/{slug}/sort-item', [BookSortController::class, 'showItem']); + Route::get('/books/{slug}', [BookController::class, 'show']); + Route::get('/books/{bookSlug}/permissions', [BookController::class, 'showPermissions']); + Route::put('/books/{bookSlug}/permissions', [BookController::class, 'permissions']); + Route::get('/books/{slug}/delete', [BookController::class, 'showDelete']); + Route::get('/books/{bookSlug}/sort', [BookSortController::class, 'show']); + Route::put('/books/{bookSlug}/sort', [BookSortController::class, 'update']); + Route::get('/books/{bookSlug}/export/html', [BookExportController::class, 'html']); + Route::get('/books/{bookSlug}/export/pdf', [BookExportController::class, 'pdf']); + Route::get('/books/{bookSlug}/export/markdown', [BookExportController::class, 'markdown']); + Route::get('/books/{bookSlug}/export/zip', [BookExportController::class, 'zip']); + Route::get('/books/{bookSlug}/export/plaintext', [BookExportController::class, 'plainText']); - // Pages - Route::get('/{bookSlug}/create-page', [PageController::class, 'create']); - Route::post('/{bookSlug}/create-guest-page', [PageController::class, 'createAsGuest']); - Route::get('/{bookSlug}/draft/{pageId}', [PageController::class, 'editDraft']); - Route::post('/{bookSlug}/draft/{pageId}', [PageController::class, 'store']); - Route::get('/{bookSlug}/page/{pageSlug}', [PageController::class, 'show']); - Route::get('/{bookSlug}/page/{pageSlug}/export/pdf', [PageExportController::class, 'pdf']); - Route::get('/{bookSlug}/page/{pageSlug}/export/html', [PageExportController::class, 'html']); - Route::get('/{bookSlug}/page/{pageSlug}/export/markdown', [PageExportController::class, 'markdown']); - Route::get('/{bookSlug}/page/{pageSlug}/export/plaintext', [PageExportController::class, 'plainText']); - Route::get('/{bookSlug}/page/{pageSlug}/edit', [PageController::class, 'edit']); - Route::get('/{bookSlug}/page/{pageSlug}/move', [PageController::class, 'showMove']); - Route::put('/{bookSlug}/page/{pageSlug}/move', [PageController::class, 'move']); - Route::get('/{bookSlug}/page/{pageSlug}/copy', [PageController::class, 'showCopy']); - Route::post('/{bookSlug}/page/{pageSlug}/copy', [PageController::class, 'copy']); - Route::get('/{bookSlug}/page/{pageSlug}/delete', [PageController::class, 'showDelete']); - Route::get('/{bookSlug}/draft/{pageId}/delete', [PageController::class, 'showDeleteDraft']); - Route::get('/{bookSlug}/page/{pageSlug}/permissions', [PageController::class, 'showPermissions']); - Route::put('/{bookSlug}/page/{pageSlug}/permissions', [PageController::class, 'permissions']); - Route::put('/{bookSlug}/page/{pageSlug}', [PageController::class, 'update']); - Route::delete('/{bookSlug}/page/{pageSlug}', [PageController::class, 'destroy']); - Route::delete('/{bookSlug}/draft/{pageId}', [PageController::class, 'destroyDraft']); + // Pages + Route::get('/books/{bookSlug}/create-page', [PageController::class, 'create']); + Route::post('/books/{bookSlug}/create-guest-page', [PageController::class, 'createAsGuest']); + Route::get('/books/{bookSlug}/draft/{pageId}', [PageController::class, 'editDraft']); + Route::post('/books/{bookSlug}/draft/{pageId}', [PageController::class, 'store']); + Route::get('/books/{bookSlug}/page/{pageSlug}', [PageController::class, 'show']); + Route::get('/books/{bookSlug}/page/{pageSlug}/export/pdf', [PageExportController::class, 'pdf']); + Route::get('/books/{bookSlug}/page/{pageSlug}/export/html', [PageExportController::class, 'html']); + Route::get('/books/{bookSlug}/page/{pageSlug}/export/markdown', [PageExportController::class, 'markdown']); + Route::get('/books/{bookSlug}/page/{pageSlug}/export/plaintext', [PageExportController::class, 'plainText']); + Route::get('/books/{bookSlug}/page/{pageSlug}/edit', [PageController::class, 'edit']); + Route::get('/books/{bookSlug}/page/{pageSlug}/move', [PageController::class, 'showMove']); + Route::put('/books/{bookSlug}/page/{pageSlug}/move', [PageController::class, 'move']); + Route::get('/books/{bookSlug}/page/{pageSlug}/copy', [PageController::class, 'showCopy']); + Route::post('/books/{bookSlug}/page/{pageSlug}/copy', [PageController::class, 'copy']); + Route::get('/books/{bookSlug}/page/{pageSlug}/delete', [PageController::class, 'showDelete']); + Route::get('/books/{bookSlug}/draft/{pageId}/delete', [PageController::class, 'showDeleteDraft']); + Route::get('/books/{bookSlug}/page/{pageSlug}/permissions', [PageController::class, 'showPermissions']); + Route::put('/books/{bookSlug}/page/{pageSlug}/permissions', [PageController::class, 'permissions']); + Route::put('/books/{bookSlug}/page/{pageSlug}', [PageController::class, 'update']); + Route::delete('/books/{bookSlug}/page/{pageSlug}', [PageController::class, 'destroy']); + Route::delete('/books/{bookSlug}/draft/{pageId}', [PageController::class, 'destroyDraft']); - // Revisions - Route::get('/{bookSlug}/page/{pageSlug}/revisions', [PageRevisionController::class, 'index']); - Route::get('/{bookSlug}/page/{pageSlug}/revisions/{revId}', [PageRevisionController::class, 'show']); - Route::get('/{bookSlug}/page/{pageSlug}/revisions/{revId}/changes', [PageRevisionController::class, 'changes']); - Route::put('/{bookSlug}/page/{pageSlug}/revisions/{revId}/restore', [PageRevisionController::class, 'restore']); - Route::delete('/{bookSlug}/page/{pageSlug}/revisions/{revId}/delete', [PageRevisionController::class, 'destroy']); + // Revisions + Route::get('/books/{bookSlug}/page/{pageSlug}/revisions', [PageRevisionController::class, 'index']); + Route::get('/books/{bookSlug}/page/{pageSlug}/revisions/{revId}', [PageRevisionController::class, 'show']); + Route::get('/books/{bookSlug}/page/{pageSlug}/revisions/{revId}/changes', [PageRevisionController::class, 'changes']); + Route::put('/books/{bookSlug}/page/{pageSlug}/revisions/{revId}/restore', [PageRevisionController::class, 'restore']); + Route::delete('/books/{bookSlug}/page/{pageSlug}/revisions/{revId}/delete', [PageRevisionController::class, 'destroy']); - // Chapters - Route::get('/{bookSlug}/chapter/{chapterSlug}/create-page', [PageController::class, 'create']); - Route::post('/{bookSlug}/chapter/{chapterSlug}/create-guest-page', [PageController::class, 'createAsGuest']); - Route::get('/{bookSlug}/create-chapter', [ChapterController::class, 'create']); - Route::post('/{bookSlug}/create-chapter', [ChapterController::class, 'store']); - Route::get('/{bookSlug}/chapter/{chapterSlug}', [ChapterController::class, 'show']); - Route::put('/{bookSlug}/chapter/{chapterSlug}', [ChapterController::class, 'update']); - Route::get('/{bookSlug}/chapter/{chapterSlug}/move', [ChapterController::class, 'showMove']); - Route::put('/{bookSlug}/chapter/{chapterSlug}/move', [ChapterController::class, 'move']); - Route::get('/{bookSlug}/chapter/{chapterSlug}/edit', [ChapterController::class, 'edit']); - Route::get('/{bookSlug}/chapter/{chapterSlug}/permissions', [ChapterController::class, 'showPermissions']); - Route::get('/{bookSlug}/chapter/{chapterSlug}/export/pdf', [ChapterExportController::class, 'pdf']); - Route::get('/{bookSlug}/chapter/{chapterSlug}/export/html', [ChapterExportController::class, 'html']); - Route::get('/{bookSlug}/chapter/{chapterSlug}/export/markdown', [ChapterExportController::class, 'markdown']); - Route::get('/{bookSlug}/chapter/{chapterSlug}/export/plaintext', [ChapterExportController::class, 'plainText']); - Route::put('/{bookSlug}/chapter/{chapterSlug}/permissions', [ChapterController::class, 'permissions']); - Route::get('/{bookSlug}/chapter/{chapterSlug}/delete', [ChapterController::class, 'showDelete']); - Route::delete('/{bookSlug}/chapter/{chapterSlug}', [ChapterController::class, 'destroy']); - }); + // Chapters + Route::get('/books/{bookSlug}/chapter/{chapterSlug}/create-page', [PageController::class, 'create']); + Route::post('/books/{bookSlug}/chapter/{chapterSlug}/create-guest-page', [PageController::class, 'createAsGuest']); + Route::get('/books/{bookSlug}/create-chapter', [ChapterController::class, 'create']); + Route::post('/books/{bookSlug}/create-chapter', [ChapterController::class, 'store']); + Route::get('/books/{bookSlug}/chapter/{chapterSlug}', [ChapterController::class, 'show']); + Route::put('/books/{bookSlug}/chapter/{chapterSlug}', [ChapterController::class, 'update']); + Route::get('/books/{bookSlug}/chapter/{chapterSlug}/move', [ChapterController::class, 'showMove']); + Route::put('/books/{bookSlug}/chapter/{chapterSlug}/move', [ChapterController::class, 'move']); + Route::get('/books/{bookSlug}/chapter/{chapterSlug}/edit', [ChapterController::class, 'edit']); + Route::get('/books/{bookSlug}/chapter/{chapterSlug}/permissions', [ChapterController::class, 'showPermissions']); + Route::get('/books/{bookSlug}/chapter/{chapterSlug}/export/pdf', [ChapterExportController::class, 'pdf']); + Route::get('/books/{bookSlug}/chapter/{chapterSlug}/export/html', [ChapterExportController::class, 'html']); + Route::get('/books/{bookSlug}/chapter/{chapterSlug}/export/markdown', [ChapterExportController::class, 'markdown']); + Route::get('/books/{bookSlug}/chapter/{chapterSlug}/export/plaintext', [ChapterExportController::class, 'plainText']); + Route::put('/books/{bookSlug}/chapter/{chapterSlug}/permissions', [ChapterController::class, 'permissions']); + Route::get('/books/{bookSlug}/chapter/{chapterSlug}/delete', [ChapterController::class, 'showDelete']); + Route::delete('/books/{bookSlug}/chapter/{chapterSlug}', [ChapterController::class, 'destroy']); // User Profile routes Route::get('/user/{slug}', [UserProfileController::class, 'show']); @@ -204,58 +200,56 @@ Route::middleware('auth')->group(function () { Route::get('/custom-head-content', [HomeController::class, 'customHeadContent']); // Settings - Route::prefix('settings')->group(function () { - Route::get('/', [SettingController::class, 'index'])->name('settings'); - Route::post('/', [SettingController::class, 'update']); + Route::get('/settings', [SettingController::class, 'index'])->name('settings'); + Route::post('/settings', [SettingController::class, 'update']); - // Maintenance - Route::get('/maintenance', [MaintenanceController::class, 'index']); - Route::delete('/maintenance/cleanup-images', [MaintenanceController::class, 'cleanupImages']); - Route::post('/maintenance/send-test-email', [MaintenanceController::class, 'sendTestEmail']); + // Maintenance + Route::get('/settings/maintenance', [MaintenanceController::class, 'index']); + Route::delete('/settings/maintenance/cleanup-images', [MaintenanceController::class, 'cleanupImages']); + Route::post('/settings/maintenance/send-test-email', [MaintenanceController::class, 'sendTestEmail']); - // Recycle Bin - Route::get('/recycle-bin', [RecycleBinController::class, 'index']); - Route::post('/recycle-bin/empty', [RecycleBinController::class, 'empty']); - Route::get('/recycle-bin/{id}/destroy', [RecycleBinController::class, 'showDestroy']); - Route::delete('/recycle-bin/{id}', [RecycleBinController::class, 'destroy']); - Route::get('/recycle-bin/{id}/restore', [RecycleBinController::class, 'showRestore']); - Route::post('/recycle-bin/{id}/restore', [RecycleBinController::class, 'restore']); + // Recycle Bin + Route::get('/settings/recycle-bin', [RecycleBinController::class, 'index']); + Route::post('/settings/recycle-bin/empty', [RecycleBinController::class, 'empty']); + Route::get('/settings/recycle-bin/{id}/destroy', [RecycleBinController::class, 'showDestroy']); + Route::delete('/settings/recycle-bin/{id}', [RecycleBinController::class, 'destroy']); + Route::get('/settings/recycle-bin/{id}/restore', [RecycleBinController::class, 'showRestore']); + Route::post('/settings/recycle-bin/{id}/restore', [RecycleBinController::class, 'restore']); - // Audit Log - Route::get('/audit', [AuditLogController::class, 'index']); + // Audit Log + Route::get('/settings/audit', [AuditLogController::class, 'index']); - // Users - Route::get('/users', [UserController::class, 'index']); - Route::get('/users/create', [UserController::class, 'create']); - Route::get('/users/{id}/delete', [UserController::class, 'delete']); - Route::patch('/users/{id}/switch-books-view', [UserController::class, 'switchBooksView']); - Route::patch('/users/{id}/switch-shelves-view', [UserController::class, 'switchShelvesView']); - Route::patch('/users/{id}/switch-shelf-view', [UserController::class, 'switchShelfView']); - Route::patch('/users/{id}/change-sort/{type}', [UserController::class, 'changeSort']); - Route::patch('/users/{id}/update-expansion-preference/{key}', [UserController::class, 'updateExpansionPreference']); - Route::patch('/users/toggle-dark-mode', [UserController::class, 'toggleDarkMode']); - Route::post('/users/create', [UserController::class, 'store']); - Route::get('/users/{id}', [UserController::class, 'edit']); - Route::put('/users/{id}', [UserController::class, 'update']); - Route::delete('/users/{id}', [UserController::class, 'destroy']); + // Users + Route::get('/settings/users', [UserController::class, 'index']); + Route::get('/settings/users/create', [UserController::class, 'create']); + Route::get('/settings/users/{id}/delete', [UserController::class, 'delete']); + Route::patch('/settings/users/{id}/switch-books-view', [UserController::class, 'switchBooksView']); + Route::patch('/settings/users/{id}/switch-shelves-view', [UserController::class, 'switchShelvesView']); + Route::patch('/settings/users/{id}/switch-shelf-view', [UserController::class, 'switchShelfView']); + Route::patch('/settings/users/{id}/change-sort/{type}', [UserController::class, 'changeSort']); + Route::patch('/settings/users/{id}/update-expansion-preference/{key}', [UserController::class, 'updateExpansionPreference']); + Route::patch('/settings/users/toggle-dark-mode', [UserController::class, 'toggleDarkMode']); + Route::post('/settings/users/create', [UserController::class, 'store']); + Route::get('/settings/users/{id}', [UserController::class, 'edit']); + Route::put('/settings/users/{id}', [UserController::class, 'update']); + Route::delete('/settings/users/{id}', [UserController::class, 'destroy']); - // User API Tokens - Route::get('/users/{userId}/create-api-token', [UserApiTokenController::class, 'create']); - Route::post('/users/{userId}/create-api-token', [UserApiTokenController::class, 'store']); - Route::get('/users/{userId}/api-tokens/{tokenId}', [UserApiTokenController::class, 'edit']); - Route::put('/users/{userId}/api-tokens/{tokenId}', [UserApiTokenController::class, 'update']); - Route::get('/users/{userId}/api-tokens/{tokenId}/delete', [UserApiTokenController::class, 'delete']); - Route::delete('/users/{userId}/api-tokens/{tokenId}', [UserApiTokenController::class, 'destroy']); + // User API Tokens + Route::get('/settings/users/{userId}/create-api-token', [UserApiTokenController::class, 'create']); + Route::post('/settings/users/{userId}/create-api-token', [UserApiTokenController::class, 'store']); + Route::get('/settings/users/{userId}/api-tokens/{tokenId}', [UserApiTokenController::class, 'edit']); + Route::put('/settings/users/{userId}/api-tokens/{tokenId}', [UserApiTokenController::class, 'update']); + Route::get('/settings/users/{userId}/api-tokens/{tokenId}/delete', [UserApiTokenController::class, 'delete']); + Route::delete('/settings/users/{userId}/api-tokens/{tokenId}', [UserApiTokenController::class, 'destroy']); - // Roles - Route::get('/roles', [RoleController::class, 'list']); - Route::get('/roles/new', [RoleController::class, 'create']); - Route::post('/roles/new', [RoleController::class, 'store']); - Route::get('/roles/delete/{id}', [RoleController::class, 'showDelete']); - Route::delete('/roles/delete/{id}', [RoleController::class, 'delete']); - Route::get('/roles/{id}', [RoleController::class, 'edit']); - Route::put('/roles/{id}', [RoleController::class, 'update']); - }); + // Roles + Route::get('/settings/roles', [RoleController::class, 'list']); + Route::get('/settings/roles/new', [RoleController::class, 'create']); + Route::post('/settings/roles/new', [RoleController::class, 'store']); + Route::get('/settings/roles/delete/{id}', [RoleController::class, 'showDelete']); + Route::delete('/settings/roles/delete/{id}', [RoleController::class, 'delete']); + Route::get('/settings/roles/{id}', [RoleController::class, 'edit']); + Route::put('/settings/roles/{id}', [RoleController::class, 'update']); }); // MFA routes diff --git a/tests/Entity/PageDraftTest.php b/tests/Entity/PageDraftTest.php index ec6707bc5..cac1babea 100644 --- a/tests/Entity/PageDraftTest.php +++ b/tests/Entity/PageDraftTest.php @@ -188,16 +188,16 @@ class PageDraftTest extends TestCase $draft = Page::query()->where('draft', '=', true)->where('book_id', '=', $book->id)->firstOrFail(); $resp = $this->put('/ajax/page/' . $draft->id . '/save-draft', [ - 'name' => 'My updated draft', + 'name' => 'My updated draft', 'markdown' => "# My markdown page\n\n[A link](https://example.com)", - 'html' => '

checking markdown takes priority over this

' + 'html' => '

checking markdown takes priority over this

', ]); $resp->assertOk(); $this->assertDatabaseHas('pages', [ - 'id' => $draft->id, - 'draft' => true, - 'name' => 'My updated draft', + 'id' => $draft->id, + 'draft' => true, + 'name' => 'My updated draft', 'markdown' => "# My markdown page\n\n[A link](https://example.com)", ]); From 20511899214f084732f90df7f0adb36be16c7714 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 14 Nov 2021 15:20:04 +0000 Subject: [PATCH 47/59] Added /api => /api/docs redirect for convenience. --- routes/web.php | 1 + tests/Api/ApiDocsTest.php | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/routes/web.php b/routes/web.php index 854ec2337..653b5c227 100644 --- a/routes/web.php +++ b/routes/web.php @@ -42,6 +42,7 @@ Route::middleware('auth')->group(function () { ->where('path', '.*$'); // API docs routes + Route::redirect('/api', '/api/docs'); Route::get('/api/docs', [Api\ApiDocsController::class, 'display']); Route::get('/pages/recently-updated', [PageController::class, 'showRecentlyUpdated']); diff --git a/tests/Api/ApiDocsTest.php b/tests/Api/ApiDocsTest.php index 062adce53..56b09cfb8 100644 --- a/tests/Api/ApiDocsTest.php +++ b/tests/Api/ApiDocsTest.php @@ -10,6 +10,12 @@ class ApiDocsTest extends TestCase protected $endpoint = '/api/docs'; + public function test_api_endpoint_redirects_to_docs() + { + $resp = $this->actingAsApiEditor()->get('/api'); + $resp->assertRedirect('api/docs'); + } + public function test_docs_page_returns_view_with_docs_content() { $resp = $this->actingAsApiEditor()->get($this->endpoint); From 6f1bdbf771b00be12db676e6289830d8cdc7ecda Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 14 Nov 2021 16:28:01 +0000 Subject: [PATCH 48/59] Added API search endpoint Is a little awkward, emulates a 'list' API endpoint but has unstable paging and does not support filters/sort. This is detailed on the endpoint though. Made some updates to the docs system to better support parameters and examples on GET requests. Includes tests to cover. For #909 --- app/Api/ApiDocsGenerator.php | 12 +++- app/Entities/Tools/SearchRunner.php | 2 + .../Controllers/Api/SearchApiController.php | 67 +++++++++++++++++++ dev/api/requests/search-all.http | 1 + dev/api/responses/search-all.json | 52 ++++++++++++++ .../views/api-docs/parts/endpoint.blade.php | 2 +- routes/api.php | 3 + tests/Api/SearchApiTest.php | 47 +++++++++++++ 8 files changed, 182 insertions(+), 4 deletions(-) create mode 100644 app/Http/Controllers/Api/SearchApiController.php create mode 100644 dev/api/requests/search-all.http create mode 100644 dev/api/responses/search-all.json create mode 100644 tests/Api/SearchApiTest.php diff --git a/app/Api/ApiDocsGenerator.php b/app/Api/ApiDocsGenerator.php index d130304de..4cba7900b 100644 --- a/app/Api/ApiDocsGenerator.php +++ b/app/Api/ApiDocsGenerator.php @@ -55,10 +55,16 @@ class ApiDocsGenerator { return $routes->map(function (array $route) { $exampleTypes = ['request', 'response']; + $fileTypes = ['json', 'http']; foreach ($exampleTypes as $exampleType) { - $exampleFile = base_path("dev/api/{$exampleType}s/{$route['name']}.json"); - $exampleContent = file_exists($exampleFile) ? file_get_contents($exampleFile) : null; - $route["example_{$exampleType}"] = $exampleContent; + foreach ($fileTypes as $fileType) { + $exampleFile = base_path("dev/api/{$exampleType}s/{$route['name']}." . $fileType); + if (file_exists($exampleFile)) { + $route["example_{$exampleType}"] = file_get_contents($exampleFile); + continue 2; + } + } + $route["example_{$exampleType}"] = null; } return $route; diff --git a/app/Entities/Tools/SearchRunner.php b/app/Entities/Tools/SearchRunner.php index f6da871f4..04f4c5768 100644 --- a/app/Entities/Tools/SearchRunner.php +++ b/app/Entities/Tools/SearchRunner.php @@ -56,6 +56,8 @@ class SearchRunner * Search all entities in the system. * The provided count is for each entity to search, * Total returned could be larger and not guaranteed. + * + * @return array{total: int, count: int, has_more: bool, results: Entity[]} */ public function searchEntities(SearchOptions $searchOpts, string $entityType = 'all', int $page = 1, int $count = 20, string $action = 'view'): array { diff --git a/app/Http/Controllers/Api/SearchApiController.php b/app/Http/Controllers/Api/SearchApiController.php new file mode 100644 index 000000000..8fb249665 --- /dev/null +++ b/app/Http/Controllers/Api/SearchApiController.php @@ -0,0 +1,67 @@ + [ + 'query' => ['required'], + 'page' => ['integer', 'min:1'], + 'count' => ['integer', 'min:1', 'max:100'], + ], + ]; + + public function __construct(SearchRunner $searchRunner) + { + $this->searchRunner = $searchRunner; + } + + /** + * Run a search query against all main content types (shelves, books, chapters & pages) + * in the system. Takes the same input as the main search bar within the BookStack + * interface as a 'query' parameter. See https://www.bookstackapp.com/docs/user/searching/ + * for a full list of search term options. Results contain a 'type' property to distinguish + * between: bookshelf, book, chapter & page. + * + * The paging parameters and response format emulates a standard listing endpoint + * but standard sorting and filtering cannot be done on this endpoint. If a count value + * is provided this will only be taken as a suggestion. The results in the response + * may currently be up to 4x this value. + */ + public function all(Request $request) + { + $this->validate($request, $this->rules['all']); + + $options = SearchOptions::fromString($request->get('query') ?? ''); + $page = intval($request->get('page', '0')) ?: 1; + $count = min(intval($request->get('count', '0')) ?: 20, 100); + + $results = $this->searchRunner->searchEntities($options, 'all', $page, $count); + + /** @var Entity $result */ + foreach ($results['results'] as $result) { + $result->setVisible([ + 'id', 'name', 'slug', 'book_id', + 'chapter_id', 'draft', 'template', + 'created_at', 'updated_at', + 'tags', 'type', + ]); + $result->setAttribute('type', $result->getType()); + } + + return response()->json([ + 'data' => $results['results'], + 'total' => $results['total'], + ]); + } + + +} diff --git a/dev/api/requests/search-all.http b/dev/api/requests/search-all.http new file mode 100644 index 000000000..ee5223816 --- /dev/null +++ b/dev/api/requests/search-all.http @@ -0,0 +1 @@ +GET /api/search?query=cats+{created_by:me}&page=1&count=2 \ No newline at end of file diff --git a/dev/api/responses/search-all.json b/dev/api/responses/search-all.json new file mode 100644 index 000000000..3096d6da1 --- /dev/null +++ b/dev/api/responses/search-all.json @@ -0,0 +1,52 @@ +{ + "data": [ + { + "id": 84, + "book_id": 1, + "slug": "a-chapter-for-cats", + "name": "A chapter for cats", + "created_at": "2021-11-14T15:57:35.000000Z", + "updated_at": "2021-11-14T15:57:35.000000Z", + "type": "chapter", + "tags": [] + }, + { + "name": "The hows and whys of cats", + "id": 396, + "slug": "the-hows-and-whys-of-cats", + "book_id": 1, + "chapter_id": 75, + "draft": false, + "template": false, + "created_at": "2021-05-15T16:28:10.000000Z", + "updated_at": "2021-11-14T15:56:49.000000Z", + "type": "page", + "tags": [ + { + "name": "Animal", + "value": "Cat", + "order": 0 + }, + { + "name": "Category", + "value": "Top Content", + "order": 0 + } + ] + }, + { + "name": "How advanced are cats?", + "id": 362, + "slug": "how-advanced-are-cats", + "book_id": 13, + "chapter_id": 73, + "draft": false, + "template": false, + "created_at": "2020-11-29T21:55:07.000000Z", + "updated_at": "2021-11-14T16:02:39.000000Z", + "type": "page", + "tags": [] + } + ], + "total": 3 +} \ No newline at end of file diff --git a/resources/views/api-docs/parts/endpoint.blade.php b/resources/views/api-docs/parts/endpoint.blade.php index c1bce805b..6e3d93659 100644 --- a/resources/views/api-docs/parts/endpoint.blade.php +++ b/resources/views/api-docs/parts/endpoint.blade.php @@ -13,7 +13,7 @@ @if($endpoint['body_params'] ?? false)
- Body Parameters + {{ $endpoint['method'] === 'GET' ? 'Query' : 'Body' }} Parameters diff --git a/routes/api.php b/routes/api.php index 4ba499462..7876ba6d4 100644 --- a/routes/api.php +++ b/routes/api.php @@ -9,6 +9,7 @@ use BookStack\Http\Controllers\Api\ChapterApiController; use BookStack\Http\Controllers\Api\ChapterExportApiController; use BookStack\Http\Controllers\Api\PageApiController; use BookStack\Http\Controllers\Api\PageExportApiController; +use BookStack\Http\Controllers\Api\SearchApiController; use Illuminate\Support\Facades\Route; /** @@ -57,6 +58,8 @@ Route::get('pages/{id}/export/pdf', [PageExportApiController::class, 'exportPdf' Route::get('pages/{id}/export/plaintext', [PageExportApiController::class, 'exportPlainText']); Route::get('pages/{id}/export/markdown', [PageExportApiController::class, 'exportMarkDown']); +Route::get('search', [SearchApiController::class, 'all']); + Route::get('shelves', [BookshelfApiController::class, 'list']); Route::post('shelves', [BookshelfApiController::class, 'create']); Route::get('shelves/{id}', [BookshelfApiController::class, 'read']); diff --git a/tests/Api/SearchApiTest.php b/tests/Api/SearchApiTest.php new file mode 100644 index 000000000..55ca0e009 --- /dev/null +++ b/tests/Api/SearchApiTest.php @@ -0,0 +1,47 @@ +actingAsApiEditor(); + $uniqueTerm = 'MySuperUniqueTermForSearching'; + + /** @var Entity $entityClass */ + foreach ([Page::class, Chapter::class, Book::class, Bookshelf::class] as $entityClass) { + /** @var Entity $first */ + $first = $entityClass::query()->first(); + $first->update(['name' => $uniqueTerm]); + $first->indexForSearch(); + } + + $resp = $this->getJson($this->baseEndpoint . '?query=' . $uniqueTerm . '&count=5&page=1'); + $resp->assertJsonCount(4, 'data'); + $resp->assertJsonFragment(['name' => $uniqueTerm, 'type' => 'book']); + $resp->assertJsonFragment(['name' => $uniqueTerm, 'type' => 'chapter']); + $resp->assertJsonFragment(['name' => $uniqueTerm, 'type' => 'page']); + $resp->assertJsonFragment(['name' => $uniqueTerm, 'type' => 'bookshelf']); + } + + public function test_all_endpoint_requires_query_parameter() + { + $resp = $this->actingAsApiEditor()->get($this->baseEndpoint); + $resp->assertStatus(422); + + $resp = $this->actingAsApiEditor()->get($this->baseEndpoint . '?query=myqueryvalue'); + $resp->assertOk(); + } +} From fceb4ecc07d177f9e6e88a8f95115687170b760b Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 14 Nov 2021 16:53:01 +0000 Subject: [PATCH 49/59] Fixed sponsor image logo paths Broke due to website branch name change --- readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index 2f88be96a..78c5c7e33 100644 --- a/readme.md +++ b/readme.md @@ -38,11 +38,11 @@ Note: Listed services are not tested, vetted nor supported by the official BookS
Param Name
- Diagrams.net logo + Diagrams.net - Stellar Hosted Logo + Stellar Hosted
From f910738a80f918e1fdcf9f1ae4e63bce4287bd83 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 14 Nov 2021 21:13:24 +0000 Subject: [PATCH 50/59] Changed logout routes to POST instead of GET As per #3047. Also made some SAML specific fixes: - IDP initiated login was broken due to forced default session value. Double checked against OneLogin lib docs that this reverted logic was fine. - Changed how the saml login flow works to use 'withoutMiddleware' on the route instead of hacking out the session driver. This was due to the array driver (previously used for the hack) no longer being considered non-persistent. --- app/Auth/Access/Saml2Service.php | 2 +- app/Http/Controllers/Auth/Saml2Controller.php | 10 ++-------- resources/views/common/header.blade.php | 12 +++++++----- routes/web.php | 10 +++++++--- tests/Auth/AuthTest.php | 4 ++-- tests/Auth/OidcTest.php | 2 +- tests/Auth/Saml2Test.php | 13 ++++++------- 7 files changed, 26 insertions(+), 27 deletions(-) diff --git a/app/Auth/Access/Saml2Service.php b/app/Auth/Access/Saml2Service.php index ad889faf7..f5d0cd7cc 100644 --- a/app/Auth/Access/Saml2Service.php +++ b/app/Auth/Access/Saml2Service.php @@ -99,7 +99,7 @@ class Saml2Service * @throws JsonDebugException * @throws UserRegistrationException */ - public function processAcsResponse(string $requestId, string $samlResponse): ?User + public function processAcsResponse(?string $requestId, string $samlResponse): ?User { // The SAML2 toolkit expects the response to be within the $_POST superglobal // so we need to manually put it back there at this point. diff --git a/app/Http/Controllers/Auth/Saml2Controller.php b/app/Http/Controllers/Auth/Saml2Controller.php index bd3b25da7..b84483961 100644 --- a/app/Http/Controllers/Auth/Saml2Controller.php +++ b/app/Http/Controllers/Auth/Saml2Controller.php @@ -5,8 +5,7 @@ namespace BookStack\Http\Controllers\Auth; use BookStack\Auth\Access\Saml2Service; use BookStack\Http\Controllers\Controller; use Illuminate\Http\Request; -use Illuminate\Support\Facades\Cache; -use Str; +use Illuminate\Support\Str; class Saml2Controller extends Controller { @@ -79,11 +78,6 @@ class Saml2Controller extends Controller */ public function startAcs(Request $request) { - // Note: This is a bit of a hack to prevent a session being stored - // on the response of this request. Within Laravel7+ this could instead - // be done via removing the StartSession middleware from the route. - config()->set('session.driver', 'array'); - $samlResponse = $request->get('SAMLResponse', null); if (empty($samlResponse)) { @@ -114,7 +108,7 @@ class Saml2Controller extends Controller $samlResponse = decrypt(cache()->pull($cacheKey)); } catch (\Exception $exception) { } - $requestId = session()->pull('saml2_request_id', 'unset'); + $requestId = session()->pull('saml2_request_id', null); if (empty($acsId) || empty($samlResponse)) { $this->showErrorNotification(trans('errors.saml_fail_authed', ['system' => config('saml2.name')])); diff --git a/resources/views/common/header.blade.php b/resources/views/common/header.blade.php index 2311ce3e0..d55f3ae2d 100644 --- a/resources/views/common/header.blade.php +++ b/resources/views/common/header.blade.php @@ -71,11 +71,13 @@ @icon('edit'){{ trans('common.edit_profile') }}
  • - @if(config('auth.method') === 'saml2') - @icon('logout'){{ trans('auth.logout') }} - @else - @icon('logout'){{ trans('auth.logout') }} - @endif +
    + {{ csrf_field() }} + +

  • diff --git a/routes/web.php b/routes/web.php index 653b5c227..c924ed68c 100644 --- a/routes/web.php +++ b/routes/web.php @@ -277,7 +277,7 @@ Route::get('/register/service/{socialDriver}', [Auth\SocialController::class, 'r // Login/Logout routes Route::get('/login', [Auth\LoginController::class, 'getLogin']); Route::post('/login', [Auth\LoginController::class, 'login']); -Route::get('/logout', [Auth\LoginController::class, 'logout']); +Route::post('/logout', [Auth\LoginController::class, 'logout']); Route::get('/register', [Auth\RegisterController::class, 'getRegister']); Route::get('/register/confirm', [Auth\ConfirmEmailController::class, 'show']); Route::get('/register/confirm/awaiting', [Auth\ConfirmEmailController::class, 'showAwaiting']); @@ -287,10 +287,14 @@ Route::post('/register', [Auth\RegisterController::class, 'postRegister']); // SAML routes Route::post('/saml2/login', [Auth\Saml2Controller::class, 'login']); -Route::get('/saml2/logout', [Auth\Saml2Controller::class, 'logout']); +Route::post('/saml2/logout', [Auth\Saml2Controller::class, 'logout']); Route::get('/saml2/metadata', [Auth\Saml2Controller::class, 'metadata']); Route::get('/saml2/sls', [Auth\Saml2Controller::class, 'sls']); -Route::post('/saml2/acs', [Auth\Saml2Controller::class, 'startAcs']); +Route::post('/saml2/acs', [Auth\Saml2Controller::class, 'startAcs'])->withoutMiddleware([ + \Illuminate\Session\Middleware\StartSession::class, + \Illuminate\View\Middleware\ShareErrorsFromSession::class, + \BookStack\Http\Middleware\VerifyCsrfToken::class, +]); Route::get('/saml2/acs', [Auth\Saml2Controller::class, 'processAcs']); // OIDC routes diff --git a/tests/Auth/AuthTest.php b/tests/Auth/AuthTest.php index 66ab09d3c..50f56bfb9 100644 --- a/tests/Auth/AuthTest.php +++ b/tests/Auth/AuthTest.php @@ -192,7 +192,7 @@ class AuthTest extends TestCase public function test_logout() { $this->asAdmin()->get('/')->assertOk(); - $this->get('/logout')->assertRedirect('/'); + $this->post('/logout')->assertRedirect('/'); $this->get('/')->assertRedirect('/login'); } @@ -204,7 +204,7 @@ class AuthTest extends TestCase $mfaSession->markVerifiedForUser($user); $this->assertTrue($mfaSession->isVerifiedForUser($user)); - $this->asAdmin()->get('/logout'); + $this->asAdmin()->post('/logout'); $this->assertFalse($mfaSession->isVerifiedForUser($user)); } diff --git a/tests/Auth/OidcTest.php b/tests/Auth/OidcTest.php index e7665a679..0b033ea81 100644 --- a/tests/Auth/OidcTest.php +++ b/tests/Auth/OidcTest.php @@ -90,7 +90,7 @@ class OidcTest extends TestCase public function test_logout_route_functions() { $this->actingAs($this->getEditor()); - $this->get('/logout'); + $this->post('/logout'); $this->assertFalse(auth()->check()); } diff --git a/tests/Auth/Saml2Test.php b/tests/Auth/Saml2Test.php index aac2710a8..cb217585c 100644 --- a/tests/Auth/Saml2Test.php +++ b/tests/Auth/Saml2Test.php @@ -157,8 +157,7 @@ class Saml2Test extends TestCase ]); $resp = $this->actingAs($this->getEditor())->get('/'); - $resp->assertElementExists('a[href$="/saml2/logout"]'); - $resp->assertElementContains('a[href$="/saml2/logout"]', 'Logout'); + $resp->assertElementContains('form[action$="/saml2/logout"] button', 'Logout'); } public function test_logout_sls_flow() @@ -177,7 +176,7 @@ class Saml2Test extends TestCase $this->followingRedirects()->post('/saml2/acs', ['SAMLResponse' => $this->acsPostData]); - $req = $this->get('/saml2/logout'); + $req = $this->post('/saml2/logout'); $redirect = $req->headers->get('location'); $this->assertStringStartsWith('http://saml.local/saml2/idp/SingleLogoutService.php', $redirect); $this->withGet(['SAMLResponse' => $this->sloResponseData], $handleLogoutResponse); @@ -193,7 +192,7 @@ class Saml2Test extends TestCase $this->followingRedirects()->post('/saml2/acs', ['SAMLResponse' => $this->acsPostData]); $this->assertTrue($this->isAuthenticated()); - $req = $this->get('/saml2/logout'); + $req = $this->post('/saml2/logout'); $req->assertRedirect('/'); $this->assertFalse($this->isAuthenticated()); } @@ -216,13 +215,13 @@ class Saml2Test extends TestCase public function test_saml_routes_are_only_active_if_saml_enabled() { config()->set(['auth.method' => 'standard']); - $getRoutes = ['/logout', '/metadata', '/sls']; + $getRoutes = ['/metadata', '/sls']; foreach ($getRoutes as $route) { $req = $this->get('/saml2' . $route); $this->assertPermissionError($req); } - $postRoutes = ['/login', '/acs']; + $postRoutes = ['/login', '/acs', '/logout']; foreach ($postRoutes as $route) { $req = $this->post('/saml2' . $route); $this->assertPermissionError($req); @@ -249,7 +248,7 @@ class Saml2Test extends TestCase $resp = $this->post('/login'); $this->assertPermissionError($resp); - $resp = $this->get('/logout'); + $resp = $this->post('/logout'); $this->assertPermissionError($resp); } From 85154fff693c80374bc048ca9497df663bd5e32d Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 14 Nov 2021 22:03:22 +0000 Subject: [PATCH 51/59] Added an env configurable file upload size limit Replaces the old suggestion of setting JS head 'window.uploadLimit' variable. This new env option will be used by back-end validation and front-end libs/logic too. Limits already likely exist within prod environments at a PHP and webserver level but this allows an app-level limit and centralises the option on the BookStack side into the .env Closes #3033 --- .env.example.complete | 4 ++ app/Config/app.php | 3 ++ app/Entities/Tools/PageContent.php | 6 +++ app/Http/Controllers/Api/ApiController.php | 5 +++ .../Api/AttachmentApiController.php | 37 ++++++++++--------- app/Http/Controllers/AttachmentController.php | 5 ++- app/Http/Controllers/Controller.php | 4 +- app/Uploads/AttachmentService.php | 8 ++++ resources/js/components/dropzone.js | 3 +- resources/views/form/dropzone.blade.php | 1 + 10 files changed, 54 insertions(+), 22 deletions(-) diff --git a/.env.example.complete b/.env.example.complete index 683db703c..9a46b23a5 100644 --- a/.env.example.complete +++ b/.env.example.complete @@ -293,6 +293,10 @@ REVISION_LIMIT=50 # Set to -1 for unlimited recycle bin lifetime. RECYCLE_BIN_LIFETIME=30 +# File Upload Limit +# Maximum file size, in megabytes, that can be uploaded to the system. +FILE_UPLOAD_SIZE_LIMIT=50 + # Allow