From 691027a522d43c5a52085b89abe3123596bf08cc Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 27 Sep 2020 23:24:33 +0100 Subject: [PATCH 01/72] Started implementation of recycle bin functionality --- app/Actions/ViewService.php | 25 ++-- app/Auth/Permissions/PermissionService.php | 13 +- app/Entities/DeleteRecord.php | 41 ++++++ app/Entities/Entity.php | 13 +- app/Entities/Managers/TrashCan.php | 130 +++++++++++++----- app/Entities/Repos/BookRepo.php | 5 +- app/Entities/Repos/BookshelfRepo.php | 2 +- app/Entities/Repos/ChapterRepo.php | 6 +- app/Entities/Repos/PageRepo.php | 5 +- app/Entities/SearchService.php | 9 +- app/Http/Controllers/HomeController.php | 2 +- ...0_09_27_210059_add_entity_soft_deletes.php | 50 +++++++ ..._27_210528_create_delete_records_table.php | 38 +++++ 13 files changed, 266 insertions(+), 73 deletions(-) create mode 100644 app/Entities/DeleteRecord.php create mode 100644 database/migrations/2020_09_27_210059_add_entity_soft_deletes.php create mode 100644 database/migrations/2020_09_27_210528_create_delete_records_table.php diff --git a/app/Actions/ViewService.php b/app/Actions/ViewService.php index 324bfaa4e..aa75abb72 100644 --- a/app/Actions/ViewService.php +++ b/app/Actions/ViewService.php @@ -79,29 +79,26 @@ class ViewService /** * Get all recently viewed entities for the current user. - * @param int $count - * @param int $page - * @param Entity|bool $filterModel - * @return mixed */ - public function getUserRecentlyViewed($count = 10, $page = 0, $filterModel = false) + public function getUserRecentlyViewed(int $count = 10, int $page = 1) { $user = user(); if ($user === null || $user->isDefault()) { return collect(); } - $query = $this->permissionService - ->filterRestrictedEntityRelations($this->view, 'views', 'viewable_id', 'viewable_type'); - - if ($filterModel) { - $query = $query->where('viewable_type', '=', $filterModel->getMorphClass()); + $all = collect(); + /** @var Entity $instance */ + foreach ($this->entityProvider->all() as $name => $instance) { + $items = $instance::visible()->withLastView() + ->orderBy('last_viewed_at', 'desc') + ->skip($count * ($page - 1)) + ->take($count) + ->get(); + $all = $all->concat($items); } - $query = $query->where('user_id', '=', $user->id); - $viewables = $query->with('viewable')->orderBy('updated_at', 'desc') - ->skip($count * $page)->take($count)->get()->pluck('viewable'); - return $viewables; + return $all->sortByDesc('last_viewed_at')->slice(0, $count); } /** diff --git a/app/Auth/Permissions/PermissionService.php b/app/Auth/Permissions/PermissionService.php index 97cc1ca24..2609779bf 100644 --- a/app/Auth/Permissions/PermissionService.php +++ b/app/Auth/Permissions/PermissionService.php @@ -51,11 +51,6 @@ class PermissionService /** * PermissionService constructor. - * @param JointPermission $jointPermission - * @param EntityPermission $entityPermission - * @param Role $role - * @param Connection $db - * @param EntityProvider $entityProvider */ public function __construct( JointPermission $jointPermission, @@ -176,7 +171,7 @@ class PermissionService }); // Chunk through all bookshelves - $this->entityProvider->bookshelf->newQuery()->select(['id', 'restricted', 'created_by']) + $this->entityProvider->bookshelf->newQuery()->withTrashed()->select(['id', 'restricted', 'created_by']) ->chunk(50, function ($shelves) use ($roles) { $this->buildJointPermissionsForShelves($shelves, $roles); }); @@ -188,11 +183,11 @@ class PermissionService */ protected function bookFetchQuery() { - return $this->entityProvider->book->newQuery() + return $this->entityProvider->book->withTrashed()->newQuery() ->select(['id', 'restricted', 'created_by'])->with(['chapters' => function ($query) { - $query->select(['id', 'restricted', 'created_by', 'book_id']); + $query->withTrashed()->select(['id', 'restricted', 'created_by', 'book_id']); }, 'pages' => function ($query) { - $query->select(['id', 'restricted', 'created_by', 'book_id', 'chapter_id']); + $query->withTrashed()->select(['id', 'restricted', 'created_by', 'book_id', 'chapter_id']); }]); } diff --git a/app/Entities/DeleteRecord.php b/app/Entities/DeleteRecord.php new file mode 100644 index 000000000..84b37f5a3 --- /dev/null +++ b/app/Entities/DeleteRecord.php @@ -0,0 +1,41 @@ +morphTo(); + } + + /** + * The the user that performed the deletion. + */ + public function deletedBy(): BelongsTo + { + return $this->belongsTo(User::class); + } + + /** + * Create a new deletion record for the provided entity. + */ + public static function createForEntity(Entity $entity): DeleteRecord + { + $record = (new self())->forceFill([ + 'deleted_by' => user()->id, + 'deletable_type' => $entity->getMorphClass(), + 'deletable_id' => $entity->id, + ]); + $record->save(); + return $record; + } + +} diff --git a/app/Entities/Entity.php b/app/Entities/Entity.php index cc7df46d4..d1a8664e4 100644 --- a/app/Entities/Entity.php +++ b/app/Entities/Entity.php @@ -12,6 +12,7 @@ use Carbon\Carbon; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Relations\MorphMany; +use Illuminate\Database\Eloquent\SoftDeletes; /** * Class Entity @@ -36,6 +37,7 @@ use Illuminate\Database\Eloquent\Relations\MorphMany; */ class Entity extends Ownable { + use SoftDeletes; /** * @var string - Name of property where the main text content is found @@ -193,13 +195,20 @@ class Entity extends Ownable /** * Get the entity jointPermissions this is connected to. - * @return MorphMany */ - public function jointPermissions() + public function jointPermissions(): MorphMany { return $this->morphMany(JointPermission::class, 'entity'); } + /** + * Get the related delete records for this entity. + */ + public function deleteRecords(): MorphMany + { + return $this->morphMany(DeleteRecord::class, 'deletable'); + } + /** * Check if this instance or class is a certain type of entity. * Examples of $type are 'page', 'book', 'chapter' diff --git a/app/Entities/Managers/TrashCan.php b/app/Entities/Managers/TrashCan.php index 1a32294fc..9a21f5e2c 100644 --- a/app/Entities/Managers/TrashCan.php +++ b/app/Entities/Managers/TrashCan.php @@ -3,6 +3,7 @@ use BookStack\Entities\Book; use BookStack\Entities\Bookshelf; use BookStack\Entities\Chapter; +use BookStack\Entities\DeleteRecord; use BookStack\Entities\Entity; use BookStack\Entities\HasCoverImage; use BookStack\Entities\Page; @@ -11,46 +12,67 @@ use BookStack\Facades\Activity; use BookStack\Uploads\AttachmentService; use BookStack\Uploads\ImageService; use Exception; -use Illuminate\Contracts\Container\BindingResolutionException; class TrashCan { /** - * Remove a bookshelf from the system. - * @throws Exception + * Send a shelf to the recycle bin. */ - public function destroyShelf(Bookshelf $shelf) + public function softDestroyShelf(Bookshelf $shelf) { - $this->destroyCommonRelations($shelf); + DeleteRecord::createForEntity($shelf); $shelf->delete(); } /** - * Remove a book from the system. - * @throws NotifyException - * @throws BindingResolutionException + * Send a book to the recycle bin. + * @throws Exception */ - public function destroyBook(Book $book) + public function softDestroyBook(Book $book) { + DeleteRecord::createForEntity($book); + foreach ($book->pages as $page) { - $this->destroyPage($page); + $this->softDestroyPage($page, false); } foreach ($book->chapters as $chapter) { - $this->destroyChapter($chapter); + $this->softDestroyChapter($chapter, false); } - $this->destroyCommonRelations($book); $book->delete(); } /** - * Remove a page from the system. - * @throws NotifyException + * Send a chapter to the recycle bin. + * @throws Exception */ - public function destroyPage(Page $page) + public function softDestroyChapter(Chapter $chapter, bool $recordDelete = true) { + if ($recordDelete) { + DeleteRecord::createForEntity($chapter); + } + + if (count($chapter->pages) > 0) { + foreach ($chapter->pages as $page) { + $this->softDestroyPage($page, false); + } + } + + $chapter->delete(); + } + + /** + * Send a page to the recycle bin. + * @throws Exception + */ + public function softDestroyPage(Page $page, bool $recordDelete = true) + { + if ($recordDelete) { + DeleteRecord::createForEntity($page); + } + // Check if set as custom homepage & remove setting if not used or throw error if active $customHome = setting('app-homepage', '0:'); if (intval($page->id) === intval(explode(':', $customHome)[0])) { @@ -60,6 +82,64 @@ class TrashCan setting()->remove('app-homepage'); } + $page->delete(); + } + + /** + * Remove a bookshelf from the system. + * @throws Exception + */ + public function destroyShelf(Bookshelf $shelf) + { + $this->destroyCommonRelations($shelf); + $shelf->forceDelete(); + } + + /** + * Remove a book from the system. + * Destroys any child chapters and pages. + * @throws Exception + */ + public function destroyBook(Book $book) + { + $pages = $book->pages()->withTrashed()->get(); + foreach ($pages as $page) { + $this->destroyPage($page); + } + + $chapters = $book->chapters()->withTrashed()->get(); + foreach ($chapters as $chapter) { + $this->destroyChapter($chapter); + } + + $this->destroyCommonRelations($book); + $book->forceDelete(); + } + + /** + * Remove a chapter from the system. + * Destroys all pages within. + * @throws Exception + */ + public function destroyChapter(Chapter $chapter) + { + $pages = $chapter->pages()->withTrashed()->get(); + if (count($pages)) { + foreach ($pages as $page) { + $this->destroyPage($page); + } + } + + $this->destroyCommonRelations($chapter); + $chapter->forceDelete(); + } + + /** + * Remove a page from the system. + * @throws Exception + */ + public function destroyPage(Page $page) + { $this->destroyCommonRelations($page); // Delete Attached Files @@ -68,24 +148,7 @@ class TrashCan $attachmentService->deleteFile($attachment); } - $page->delete(); - } - - /** - * Remove a chapter from the system. - * @throws Exception - */ - public function destroyChapter(Chapter $chapter) - { - if (count($chapter->pages) > 0) { - foreach ($chapter->pages as $page) { - $page->chapter_id = 0; - $page->save(); - } - } - - $this->destroyCommonRelations($chapter); - $chapter->delete(); + $page->forceDelete(); } /** @@ -100,6 +163,7 @@ class TrashCan $entity->comments()->delete(); $entity->jointPermissions()->delete(); $entity->searchTerms()->delete(); + $entity->deleteRecords()->delete(); if ($entity instanceof HasCoverImage && $entity->cover) { $imageService = app()->make(ImageService::class); diff --git a/app/Entities/Repos/BookRepo.php b/app/Entities/Repos/BookRepo.php index 70db0fa65..bb1895b36 100644 --- a/app/Entities/Repos/BookRepo.php +++ b/app/Entities/Repos/BookRepo.php @@ -123,12 +123,11 @@ class BookRepo /** * Remove a book from the system. - * @throws NotifyException - * @throws BindingResolutionException + * @throws Exception */ public function destroy(Book $book) { $trashCan = new TrashCan(); - $trashCan->destroyBook($book); + $trashCan->softDestroyBook($book); } } diff --git a/app/Entities/Repos/BookshelfRepo.php b/app/Entities/Repos/BookshelfRepo.php index ba687c6f6..eb1536da7 100644 --- a/app/Entities/Repos/BookshelfRepo.php +++ b/app/Entities/Repos/BookshelfRepo.php @@ -174,6 +174,6 @@ class BookshelfRepo public function destroy(Bookshelf $shelf) { $trashCan = new TrashCan(); - $trashCan->destroyShelf($shelf); + $trashCan->softDestroyShelf($shelf); } } diff --git a/app/Entities/Repos/ChapterRepo.php b/app/Entities/Repos/ChapterRepo.php index c6f3a2d2f..c1573f5db 100644 --- a/app/Entities/Repos/ChapterRepo.php +++ b/app/Entities/Repos/ChapterRepo.php @@ -6,10 +6,7 @@ use BookStack\Entities\Managers\BookContents; use BookStack\Entities\Managers\TrashCan; use BookStack\Exceptions\MoveOperationException; use BookStack\Exceptions\NotFoundException; -use BookStack\Exceptions\NotifyException; use Exception; -use Illuminate\Contracts\Container\BindingResolutionException; -use Illuminate\Database\Eloquent\Builder; use Illuminate\Support\Collection; class ChapterRepo @@ -19,7 +16,6 @@ class ChapterRepo /** * ChapterRepo constructor. - * @param $baseRepo */ public function __construct(BaseRepo $baseRepo) { @@ -77,7 +73,7 @@ class ChapterRepo public function destroy(Chapter $chapter) { $trashCan = new TrashCan(); - $trashCan->destroyChapter($chapter); + $trashCan->softDestroyChapter($chapter); } /** diff --git a/app/Entities/Repos/PageRepo.php b/app/Entities/Repos/PageRepo.php index e5f13463c..87839192b 100644 --- a/app/Entities/Repos/PageRepo.php +++ b/app/Entities/Repos/PageRepo.php @@ -12,6 +12,7 @@ use BookStack\Exceptions\MoveOperationException; use BookStack\Exceptions\NotFoundException; use BookStack\Exceptions\NotifyException; use BookStack\Exceptions\PermissionsException; +use Exception; use Illuminate\Database\Eloquent\Builder; use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\Support\Collection; @@ -259,12 +260,12 @@ class PageRepo /** * Destroy a page from the system. - * @throws NotifyException + * @throws Exception */ public function destroy(Page $page) { $trashCan = new TrashCan(); - $trashCan->destroyPage($page); + $trashCan->softDestroyPage($page); } /** diff --git a/app/Entities/SearchService.php b/app/Entities/SearchService.php index 11b731cd0..7da8192cc 100644 --- a/app/Entities/SearchService.php +++ b/app/Entities/SearchService.php @@ -287,9 +287,12 @@ class SearchService foreach ($this->entityProvider->all() as $entityModel) { $selectFields = ['id', 'name', $entityModel->textField]; - $entityModel->newQuery()->select($selectFields)->chunk(1000, function ($entities) { - $this->indexEntities($entities); - }); + $entityModel->newQuery() + ->withTrashed() + ->select($selectFields) + ->chunk(1000, function ($entities) { + $this->indexEntities($entities); + }); } } diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index 60d2664d0..3d68b8bcd 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -29,7 +29,7 @@ class HomeController extends Controller $recentFactor = count($draftPages) > 0 ? 0.5 : 1; $recents = $this->isSignedIn() ? - Views::getUserRecentlyViewed(12*$recentFactor, 0) + Views::getUserRecentlyViewed(12*$recentFactor, 1) : Book::visible()->orderBy('created_at', 'desc')->take(12 * $recentFactor)->get(); $recentlyUpdatedPages = Page::visible()->where('draft', false) ->orderBy('updated_at', 'desc')->take(12)->get(); diff --git a/database/migrations/2020_09_27_210059_add_entity_soft_deletes.php b/database/migrations/2020_09_27_210059_add_entity_soft_deletes.php new file mode 100644 index 000000000..d2b63e8d0 --- /dev/null +++ b/database/migrations/2020_09_27_210059_add_entity_soft_deletes.php @@ -0,0 +1,50 @@ +softDeletes(); + }); + Schema::table('books', function(Blueprint $table) { + $table->softDeletes(); + }); + Schema::table('chapters', function(Blueprint $table) { + $table->softDeletes(); + }); + Schema::table('pages', function(Blueprint $table) { + $table->softDeletes(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('bookshelves', function(Blueprint $table) { + $table->dropSoftDeletes(); + }); + Schema::table('books', function(Blueprint $table) { + $table->dropSoftDeletes(); + }); + Schema::table('chapters', function(Blueprint $table) { + $table->dropSoftDeletes(); + }); + Schema::table('pages', function(Blueprint $table) { + $table->dropSoftDeletes(); + }); + } +} diff --git a/database/migrations/2020_09_27_210528_create_delete_records_table.php b/database/migrations/2020_09_27_210528_create_delete_records_table.php new file mode 100644 index 000000000..cdb18ced6 --- /dev/null +++ b/database/migrations/2020_09_27_210528_create_delete_records_table.php @@ -0,0 +1,38 @@ +increments('id'); + $table->integer('deleted_by'); + $table->string('deletable_type', 100); + $table->integer('deletable_id'); + $table->timestamps(); + + $table->index('deleted_by'); + $table->index('deletable_type'); + $table->index('deletable_id'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('delete_records'); + } +} From a74d551bd6428ccc73098d53cc7ec8de79b0d6b2 Mon Sep 17 00:00:00 2001 From: Timo Schwarzer Date: Thu, 1 Oct 2020 11:34:56 +0200 Subject: [PATCH 02/72] Install composer dependencies in Docker entrypoint --- dev/docker/entrypoint.app.sh | 3 ++- readme.md | 13 ++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/dev/docker/entrypoint.app.sh b/dev/docker/entrypoint.app.sh index ff44f0c8d..e91d34a71 100755 --- a/dev/docker/entrypoint.app.sh +++ b/dev/docker/entrypoint.app.sh @@ -7,8 +7,9 @@ env if [[ -n "$1" ]]; then exec "$@" else + composer install wait-for-it db:3306 -t 45 php artisan migrate --database=mysql chown -R www-data:www-data storage exec apache2-foreground -fi \ No newline at end of file +fi diff --git a/readme.md b/readme.md index 7c2872a0a..bf6dfac2d 100644 --- a/readme.md +++ b/readme.md @@ -93,12 +93,11 @@ To get started, make sure you meet the following requirements: If all the conditions are met, you can proceed with the following steps: -1. Install PHP/Composer dependencies with **`docker-compose run app composer install`** (first time can take a while because the image has to be built). -2. **Copy `.env.example` to `.env`** and change `APP_KEY` to a random 32 char string. -3. Make sure **port 8080 is unused** *or else* change `DEV_PORT` to a free port on your host. -4. **Run `chgrp -R docker storage`**. The development container will chown the `storage` directory to the `www-data` user inside the container so BookStack can write to it. You need to change the group to your host's `docker` group here to not lose access to the `storage` directory. -5. **Run `docker-compose up`** and wait until all database migrations have been done. -6. You can now login with `admin@admin.com` and `password` as password on `localhost:8080` (or another port if specified). +1. **Copy `.env.example` to `.env`**, change `APP_KEY` to a random 32 char string and set `APP_ENV` to `local`. +2. Make sure **port 8080 is unused** *or else* change `DEV_PORT` to a free port on your host. +3. **Run `chgrp -R docker storage`**. The development container will chown the `storage` directory to the `www-data` user inside the container so BookStack can write to it. You need to change the group to your host's `docker` group here to not lose access to the `storage` directory. +4. **Run `docker-compose up`** and wait until the image is built and all database migrations have been done. +5. You can now login with `admin@admin.com` and `password` as password on `localhost:8080` (or another port if specified). If needed, You'll be able to run any artisan commands via docker-compose like so: @@ -170,4 +169,4 @@ These are the great open-source projects used to help build BookStack: * [WKHTMLtoPDF](http://wkhtmltopdf.org/index.html) * [diagrams.net](https://github.com/jgraph/drawio) * [Laravel Stats](https://github.com/stefanzweifel/laravel-stats) -* [OneLogin's SAML PHP Toolkit](https://github.com/onelogin/php-saml) \ No newline at end of file +* [OneLogin's SAML PHP Toolkit](https://github.com/onelogin/php-saml) From 04197e393ac69934df85df76e5ba2c4361f5e1d4 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 3 Oct 2020 18:44:12 +0100 Subject: [PATCH 03/72] Started work on the recycle bin interface --- .../{DeleteRecord.php => Deletion.php} | 10 +-- app/Entities/Entity.php | 4 +- app/Entities/EntityProvider.php | 1 + app/Entities/Managers/TrashCan.php | 66 ++++++++++++-- app/Http/Controllers/HomeController.php | 8 +- .../Controllers/MaintenanceController.php | 9 +- app/Http/Controllers/RecycleBinController.php | 35 ++++++++ ...0_09_27_210528_create_deletions_table.php} | 6 +- resources/lang/en/settings.php | 12 +++ resources/sass/styles.scss | 4 +- resources/views/partials/table-user.blade.php | 12 +++ resources/views/settings/audit.blade.php | 11 +-- .../views/settings/maintenance.blade.php | 18 ++++ .../views/settings/recycle-bin.blade.php | 90 +++++++++++++++++++ routes/web.php | 4 + 15 files changed, 259 insertions(+), 31 deletions(-) rename app/Entities/{DeleteRecord.php => Deletion.php} (80%) create mode 100644 app/Http/Controllers/RecycleBinController.php rename database/migrations/{2020_09_27_210528_create_delete_records_table.php => 2020_09_27_210528_create_deletions_table.php} (80%) create mode 100644 resources/views/partials/table-user.blade.php create mode 100644 resources/views/settings/recycle-bin.blade.php diff --git a/app/Entities/DeleteRecord.php b/app/Entities/Deletion.php similarity index 80% rename from app/Entities/DeleteRecord.php rename to app/Entities/Deletion.php index 84b37f5a3..576862caa 100644 --- a/app/Entities/DeleteRecord.php +++ b/app/Entities/Deletion.php @@ -5,7 +5,7 @@ use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\MorphTo; -class DeleteRecord extends Model +class Deletion extends Model { /** @@ -13,21 +13,21 @@ class DeleteRecord extends Model */ public function deletable(): MorphTo { - return $this->morphTo(); + return $this->morphTo('deletable')->withTrashed(); } /** * The the user that performed the deletion. */ - public function deletedBy(): BelongsTo + public function deleter(): BelongsTo { - return $this->belongsTo(User::class); + return $this->belongsTo(User::class, 'deleted_by'); } /** * Create a new deletion record for the provided entity. */ - public static function createForEntity(Entity $entity): DeleteRecord + public static function createForEntity(Entity $entity): Deletion { $record = (new self())->forceFill([ 'deleted_by' => user()->id, diff --git a/app/Entities/Entity.php b/app/Entities/Entity.php index d1a8664e4..14328386c 100644 --- a/app/Entities/Entity.php +++ b/app/Entities/Entity.php @@ -204,9 +204,9 @@ class Entity extends Ownable /** * Get the related delete records for this entity. */ - public function deleteRecords(): MorphMany + public function deletions(): MorphMany { - return $this->morphMany(DeleteRecord::class, 'deletable'); + return $this->morphMany(Deletion::class, 'deletable'); } /** diff --git a/app/Entities/EntityProvider.php b/app/Entities/EntityProvider.php index 6bf923b31..d28afe6f2 100644 --- a/app/Entities/EntityProvider.php +++ b/app/Entities/EntityProvider.php @@ -57,6 +57,7 @@ class EntityProvider /** * Fetch all core entity types as an associated array * with their basic names as the keys. + * @return [string => Entity] */ public function all(): array { diff --git a/app/Entities/Managers/TrashCan.php b/app/Entities/Managers/TrashCan.php index 9a21f5e2c..280694906 100644 --- a/app/Entities/Managers/TrashCan.php +++ b/app/Entities/Managers/TrashCan.php @@ -3,8 +3,9 @@ use BookStack\Entities\Book; use BookStack\Entities\Bookshelf; use BookStack\Entities\Chapter; -use BookStack\Entities\DeleteRecord; +use BookStack\Entities\Deletion; use BookStack\Entities\Entity; +use BookStack\Entities\EntityProvider; use BookStack\Entities\HasCoverImage; use BookStack\Entities\Page; use BookStack\Exceptions\NotifyException; @@ -21,7 +22,7 @@ class TrashCan */ public function softDestroyShelf(Bookshelf $shelf) { - DeleteRecord::createForEntity($shelf); + Deletion::createForEntity($shelf); $shelf->delete(); } @@ -31,7 +32,7 @@ class TrashCan */ public function softDestroyBook(Book $book) { - DeleteRecord::createForEntity($book); + Deletion::createForEntity($book); foreach ($book->pages as $page) { $this->softDestroyPage($page, false); @@ -51,7 +52,7 @@ class TrashCan public function softDestroyChapter(Chapter $chapter, bool $recordDelete = true) { if ($recordDelete) { - DeleteRecord::createForEntity($chapter); + Deletion::createForEntity($chapter); } if (count($chapter->pages) > 0) { @@ -70,7 +71,7 @@ class TrashCan public function softDestroyPage(Page $page, bool $recordDelete = true) { if ($recordDelete) { - DeleteRecord::createForEntity($page); + Deletion::createForEntity($page); } // Check if set as custom homepage & remove setting if not used or throw error if active @@ -151,6 +152,59 @@ class TrashCan $page->forceDelete(); } + /** + * Get the total counts of those that have been trashed + * but not yet fully deleted (In recycle bin). + */ + public function getTrashedCounts(): array + { + $provider = app(EntityProvider::class); + $counts = []; + + /** @var Entity $instance */ + foreach ($provider->all() as $key => $instance) { + $counts[$key] = $instance->newQuery()->onlyTrashed()->count(); + } + + return $counts; + } + + /** + * Destroy all items that have pending deletions. + */ + public function destroyFromAllDeletions() + { + $deletions = Deletion::all(); + foreach ($deletions as $deletion) { + // For each one we load in the relation since it may have already + // been deleted as part of another deletion in this loop. + $entity = $deletion->deletable()->first(); + if ($entity) { + $this->destroyEntity($deletion->deletable); + } + $deletion->delete(); + } + } + + /** + * Destroy the given entity. + */ + protected function destroyEntity(Entity $entity) + { + if ($entity->isA('page')) { + return $this->destroyPage($entity); + } + if ($entity->isA('chapter')) { + return $this->destroyChapter($entity); + } + if ($entity->isA('book')) { + return $this->destroyBook($entity); + } + if ($entity->isA('shelf')) { + return $this->destroyShelf($entity); + } + } + /** * Update entity relations to remove or update outstanding connections. */ @@ -163,7 +217,7 @@ class TrashCan $entity->comments()->delete(); $entity->jointPermissions()->delete(); $entity->searchTerms()->delete(); - $entity->deleteRecords()->delete(); + $entity->deletions()->delete(); if ($entity instanceof HasCoverImage && $entity->cover) { $imageService = app()->make(ImageService::class); diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index 3d68b8bcd..3b8b7c6e2 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -14,7 +14,6 @@ class HomeController extends Controller /** * Display the homepage. - * @return Response */ public function index() { @@ -22,9 +21,12 @@ class HomeController extends Controller $draftPages = []; if ($this->isSignedIn()) { - $draftPages = Page::visible()->where('draft', '=', true) + $draftPages = Page::visible() + ->where('draft', '=', true) ->where('created_by', '=', user()->id) - ->orderBy('updated_at', 'desc')->take(6)->get(); + ->orderBy('updated_at', 'desc') + ->take(6) + ->get(); } $recentFactor = count($draftPages) > 0 ? 0.5 : 1; diff --git a/app/Http/Controllers/MaintenanceController.php b/app/Http/Controllers/MaintenanceController.php index 664a896b2..0d6265f90 100644 --- a/app/Http/Controllers/MaintenanceController.php +++ b/app/Http/Controllers/MaintenanceController.php @@ -2,6 +2,7 @@ namespace BookStack\Http\Controllers; +use BookStack\Entities\Managers\TrashCan; use BookStack\Notifications\TestEmail; use BookStack\Uploads\ImageService; use Illuminate\Http\Request; @@ -19,7 +20,13 @@ class MaintenanceController extends Controller // Get application version $version = trim(file_get_contents(base_path('version'))); - return view('settings.maintenance', ['version' => $version]); + // Recycle bin details + $recycleStats = (new TrashCan())->getTrashedCounts(); + + return view('settings.maintenance', [ + 'version' => $version, + 'recycleStats' => $recycleStats, + ]); } /** diff --git a/app/Http/Controllers/RecycleBinController.php b/app/Http/Controllers/RecycleBinController.php new file mode 100644 index 000000000..b30eddf0c --- /dev/null +++ b/app/Http/Controllers/RecycleBinController.php @@ -0,0 +1,35 @@ +checkPermission('settings-manage'); + $this->checkPermission('restrictions-manage-all'); + + $deletions = Deletion::query()->with(['deletable', 'deleter'])->paginate(10); + + return view('settings.recycle-bin', [ + 'deletions' => $deletions, + ]); + } + + /** + * Empty out the recycle bin. + */ + public function empty() + { + $this->checkPermission('settings-manage'); + $this->checkPermission('restrictions-manage-all'); + + (new TrashCan())->destroyFromAllDeletions(); + return redirect('/settings/recycle-bin'); + } +} diff --git a/database/migrations/2020_09_27_210528_create_delete_records_table.php b/database/migrations/2020_09_27_210528_create_deletions_table.php similarity index 80% rename from database/migrations/2020_09_27_210528_create_delete_records_table.php rename to database/migrations/2020_09_27_210528_create_deletions_table.php index cdb18ced6..c38a9357f 100644 --- a/database/migrations/2020_09_27_210528_create_delete_records_table.php +++ b/database/migrations/2020_09_27_210528_create_deletions_table.php @@ -4,7 +4,7 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -class CreateDeleteRecordsTable extends Migration +class CreateDeletionsTable extends Migration { /** * Run the migrations. @@ -13,7 +13,7 @@ class CreateDeleteRecordsTable extends Migration */ public function up() { - Schema::create('delete_records', function (Blueprint $table) { + Schema::create('deletions', function (Blueprint $table) { $table->increments('id'); $table->integer('deleted_by'); $table->string('deletable_type', 100); @@ -33,6 +33,6 @@ class CreateDeleteRecordsTable extends Migration */ public function down() { - Schema::dropIfExists('delete_records'); + Schema::dropIfExists('deletions'); } } diff --git a/resources/lang/en/settings.php b/resources/lang/en/settings.php index e280396a2..66a1fe30c 100755 --- a/resources/lang/en/settings.php +++ b/resources/lang/en/settings.php @@ -80,6 +80,18 @@ return [ 'maint_send_test_email_mail_subject' => 'Test Email', 'maint_send_test_email_mail_greeting' => 'Email delivery seems to work!', 'maint_send_test_email_mail_text' => 'Congratulations! As you received this email notification, your email settings seem to be configured properly.', + 'maint_recycle_bin_desc' => 'Items deleted remain in the recycle bin until it is emptied. Open the recycle bin to restore or permanently remove items.', + 'maint_recycle_bin_open' => 'Open Recycle Bin', + + // Recycle Bin + 'recycle_bin' => 'Recycle Bin', + 'recycle_bin_desc' => 'Here you can restore items that have been deleted or choose to permanently remove them from the system. This list is unfiltered unlike similar activity lists in the system where permission filters are applied.', + 'recycle_bin_deleted_item' => 'Deleted Item', + 'recycle_bin_deleted_by' => 'Deleted By', + 'recycle_bin_deleted_at' => 'Deletion Time', + 'recycle_bin_contents_empty' => 'The recycle bin is currently empty', + 'recycle_bin_empty' => 'Empty Recycle Bin', + 'recycle_bin_empty_confirm' => 'This will permanently destroy all items in the recycle bin including content contained within each item. Are you sure you want to empty the recycle bin?', // Audit Log 'audit' => 'Audit Log', diff --git a/resources/sass/styles.scss b/resources/sass/styles.scss index 376541b5d..78d94f977 100644 --- a/resources/sass/styles.scss +++ b/resources/sass/styles.scss @@ -290,12 +290,12 @@ $btt-size: 40px; } } -table a.audit-log-user { +table.table .table-user-item { display: grid; grid-template-columns: 42px 1fr; align-items: center; } -table a.icon-list-item { +table.table .table-entity-item { display: grid; grid-template-columns: 36px 1fr; align-items: center; diff --git a/resources/views/partials/table-user.blade.php b/resources/views/partials/table-user.blade.php new file mode 100644 index 000000000..a8f2777f0 --- /dev/null +++ b/resources/views/partials/table-user.blade.php @@ -0,0 +1,12 @@ +{{-- +$user - User mode to display, Can be null. +$user_id - Id of user to show. Must be provided. +--}} +@if($user) + +
{{ $user->name }}
+
{{ $user->name }}
+
+@else + [ID: {{ $user_id }}] {{ trans('common.deleted_user') }} +@endif \ No newline at end of file diff --git a/resources/views/settings/audit.blade.php b/resources/views/settings/audit.blade.php index 9b97f060d..47a2355d1 100644 --- a/resources/views/settings/audit.blade.php +++ b/resources/views/settings/audit.blade.php @@ -60,19 +60,12 @@ @foreach($activities as $activity) - @if($activity->user) - -
{{ $activity->user->name }}
-
{{ $activity->user->name }}
-
- @else - [ID: {{ $activity->user_id }}] {{ trans('common.deleted_user') }} - @endif + @include('partials.table-user', ['user' => $activity->user, 'user_id' => $activity->user_id]) {{ $activity->key }} @if($activity->entity) - + @icon($activity->entity->getType())
{{ $activity->entity->name }} diff --git a/resources/views/settings/maintenance.blade.php b/resources/views/settings/maintenance.blade.php index 35686ca33..804112c91 100644 --- a/resources/views/settings/maintenance.blade.php +++ b/resources/views/settings/maintenance.blade.php @@ -50,5 +50,23 @@
+
+ @stop diff --git a/resources/views/settings/recycle-bin.blade.php b/resources/views/settings/recycle-bin.blade.php new file mode 100644 index 000000000..145eb5d3c --- /dev/null +++ b/resources/views/settings/recycle-bin.blade.php @@ -0,0 +1,90 @@ +@extends('simple-layout') + +@section('body') +
+ +
+
+ @include('settings.navbar', ['selected' => 'maintenance']) +
+
+ +
+

{{ trans('settings.recycle_bin') }}

+ +
+
+

{{ trans('settings.recycle_bin_desc') }}

+
+
+ + +
+
+ + +
+ + {!! $deletions->links() !!} + + + + + + + + @if(count($deletions) === 0) + + + + @endif + @foreach($deletions as $deletion) + + + + + + @endforeach +
{{ trans('settings.recycle_bin_deleted_item') }}{{ trans('settings.recycle_bin_deleted_by') }}{{ trans('settings.recycle_bin_deleted_at') }}
+

{{ trans('settings.recycle_bin_contents_empty') }}

+
+
+ @icon($deletion->deletable->getType()) +
+ {{ $deletion->deletable->name }} +
+
+ @if($deletion->deletable instanceof \BookStack\Entities\Book) +
+
+ @icon('chapter') {{ trans_choice('entities.x_chapters', $deletion->deletable->chapters()->withTrashed()->count()) }} +
+
+ @endif + @if($deletion->deletable instanceof \BookStack\Entities\Book || $deletion->deletable instanceof \BookStack\Entities\Chapter) +
+
+ @icon('page') {{ trans_choice('entities.x_pages', $deletion->deletable->pages()->withTrashed()->count()) }} +
+
+ @endif +
@include('partials.table-user', ['user' => $deletion->deleter, 'user_id' => $deletion->deleted_by]){{ $deletion->created_at }}
+ + {!! $deletions->links() !!} + +
+ +
+@stop diff --git a/routes/web.php b/routes/web.php index acbcb4e8f..20f6639a5 100644 --- a/routes/web.php +++ b/routes/web.php @@ -166,6 +166,10 @@ Route::group(['middleware' => 'auth'], function () { Route::delete('/maintenance/cleanup-images', 'MaintenanceController@cleanupImages'); Route::post('/maintenance/send-test-email', 'MaintenanceController@sendTestEmail'); + // Recycle Bin + Route::get('/recycle-bin', 'RecycleBinController@index'); + Route::post('/recycle-bin/empty', 'RecycleBinController@empty'); + // Audit Log Route::get('/audit', 'AuditLogController@index'); From ff7cbd14fcdad963a7f53f788dabbb43ccd73b8b Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 3 Oct 2020 18:53:09 +0100 Subject: [PATCH 04/72] Added recycle bin empty notification response with count --- app/Entities/Managers/TrashCan.php | 26 ++++++++++++++----- app/Http/Controllers/RecycleBinController.php | 4 ++- resources/lang/en/settings.php | 1 + 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/app/Entities/Managers/TrashCan.php b/app/Entities/Managers/TrashCan.php index 280694906..aedf4d7af 100644 --- a/app/Entities/Managers/TrashCan.php +++ b/app/Entities/Managers/TrashCan.php @@ -90,10 +90,11 @@ class TrashCan * Remove a bookshelf from the system. * @throws Exception */ - public function destroyShelf(Bookshelf $shelf) + public function destroyShelf(Bookshelf $shelf): int { $this->destroyCommonRelations($shelf); $shelf->forceDelete(); + return 1; } /** @@ -101,20 +102,24 @@ class TrashCan * Destroys any child chapters and pages. * @throws Exception */ - public function destroyBook(Book $book) + public function destroyBook(Book $book): int { + $count = 0; $pages = $book->pages()->withTrashed()->get(); foreach ($pages as $page) { $this->destroyPage($page); + $count++; } $chapters = $book->chapters()->withTrashed()->get(); foreach ($chapters as $chapter) { $this->destroyChapter($chapter); + $count++; } $this->destroyCommonRelations($book); $book->forceDelete(); + return $count + 1; } /** @@ -122,24 +127,27 @@ class TrashCan * Destroys all pages within. * @throws Exception */ - public function destroyChapter(Chapter $chapter) + public function destroyChapter(Chapter $chapter): int { + $count = 0; $pages = $chapter->pages()->withTrashed()->get(); if (count($pages)) { foreach ($pages as $page) { $this->destroyPage($page); + $count++; } } $this->destroyCommonRelations($chapter); $chapter->forceDelete(); + return $count + 1; } /** * Remove a page from the system. * @throws Exception */ - public function destroyPage(Page $page) + public function destroyPage(Page $page): int { $this->destroyCommonRelations($page); @@ -150,6 +158,7 @@ class TrashCan } $page->forceDelete(); + return 1; } /** @@ -172,24 +181,27 @@ class TrashCan /** * Destroy all items that have pending deletions. */ - public function destroyFromAllDeletions() + public function destroyFromAllDeletions(): int { $deletions = Deletion::all(); + $deleteCount = 0; foreach ($deletions as $deletion) { // For each one we load in the relation since it may have already // been deleted as part of another deletion in this loop. $entity = $deletion->deletable()->first(); if ($entity) { - $this->destroyEntity($deletion->deletable); + $count = $this->destroyEntity($deletion->deletable); + $deleteCount += $count; } $deletion->delete(); } + return $deleteCount; } /** * Destroy the given entity. */ - protected function destroyEntity(Entity $entity) + protected function destroyEntity(Entity $entity): int { if ($entity->isA('page')) { return $this->destroyPage($entity); diff --git a/app/Http/Controllers/RecycleBinController.php b/app/Http/Controllers/RecycleBinController.php index b30eddf0c..3cbc99df3 100644 --- a/app/Http/Controllers/RecycleBinController.php +++ b/app/Http/Controllers/RecycleBinController.php @@ -29,7 +29,9 @@ class RecycleBinController extends Controller $this->checkPermission('settings-manage'); $this->checkPermission('restrictions-manage-all'); - (new TrashCan())->destroyFromAllDeletions(); + $deleteCount = (new TrashCan())->destroyFromAllDeletions(); + + $this->showSuccessNotification(trans('settings.recycle_bin_empty_notification', ['count' => $deleteCount])); return redirect('/settings/recycle-bin'); } } diff --git a/resources/lang/en/settings.php b/resources/lang/en/settings.php index 66a1fe30c..6de6c2f1a 100755 --- a/resources/lang/en/settings.php +++ b/resources/lang/en/settings.php @@ -92,6 +92,7 @@ return [ 'recycle_bin_contents_empty' => 'The recycle bin is currently empty', 'recycle_bin_empty' => 'Empty Recycle Bin', 'recycle_bin_empty_confirm' => 'This will permanently destroy all items in the recycle bin including content contained within each item. Are you sure you want to empty the recycle bin?', + 'recycle_bin_empty_notification' => 'Deleted :count total items from the recycle bin.', // Audit Log 'audit' => 'Audit Log', From 704b808e9e6d7e90167e9b1e9f98ba6d90245762 Mon Sep 17 00:00:00 2001 From: imanghafoori Date: Fri, 16 Oct 2020 02:57:36 +0330 Subject: [PATCH 05/72] fixes from laravel-microscope --- app/Auth/Permissions/PermissionService.php | 3 --- app/Http/Controllers/Images/ImageController.php | 2 +- tests/Permissions/RestrictionsTest.php | 2 +- tests/User/UserApiTokenTest.php | 2 +- tests/User/UserPreferencesTest.php | 2 +- tests/User/UserProfileTest.php | 2 +- 6 files changed, 5 insertions(+), 8 deletions(-) diff --git a/app/Auth/Permissions/PermissionService.php b/app/Auth/Permissions/PermissionService.php index 97cc1ca24..043227aab 100644 --- a/app/Auth/Permissions/PermissionService.php +++ b/app/Auth/Permissions/PermissionService.php @@ -3,11 +3,8 @@ use BookStack\Auth\Permissions; use BookStack\Auth\Role; use BookStack\Entities\Book; -use BookStack\Entities\Bookshelf; -use BookStack\Entities\Chapter; use BookStack\Entities\Entity; use BookStack\Entities\EntityProvider; -use BookStack\Entities\Page; use BookStack\Ownable; use Illuminate\Database\Connection; use Illuminate\Database\Eloquent\Builder; diff --git a/app/Http/Controllers/Images/ImageController.php b/app/Http/Controllers/Images/ImageController.php index 7d06facff..52cc463c8 100644 --- a/app/Http/Controllers/Images/ImageController.php +++ b/app/Http/Controllers/Images/ImageController.php @@ -3,7 +3,7 @@ use BookStack\Entities\Page; use BookStack\Exceptions\ImageUploadException; use BookStack\Http\Controllers\Controller; -use BookStack\Repos\PageRepo; +use BookStack\Entities\Repos\PageRepo; use BookStack\Uploads\Image; use BookStack\Uploads\ImageRepo; use Exception; diff --git a/tests/Permissions/RestrictionsTest.php b/tests/Permissions/RestrictionsTest.php index 7d6c1831a..a43a65e58 100644 --- a/tests/Permissions/RestrictionsTest.php +++ b/tests/Permissions/RestrictionsTest.php @@ -58,7 +58,7 @@ class RestrictionsTest extends BrowserKitTest public function test_bookshelf_update_restriction() { - $shelf = BookShelf::first(); + $shelf = Bookshelf::first(); $this->actingAs($this->user) ->visit($shelf->getUrl('/edit')) diff --git a/tests/User/UserApiTokenTest.php b/tests/User/UserApiTokenTest.php index f738eb579..c89a590f0 100644 --- a/tests/User/UserApiTokenTest.php +++ b/tests/User/UserApiTokenTest.php @@ -1,4 +1,4 @@ - Date: Fri, 16 Oct 2020 18:40:44 +0330 Subject: [PATCH 06/72] Adds laravel-microscope package --- composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/composer.json b/composer.json index 59fc909d6..c6e45462e 100644 --- a/composer.json +++ b/composer.json @@ -35,6 +35,7 @@ "socialiteproviders/twitch": "^5.0" }, "require-dev": { + "imanghafoori/laravel-microscope": "^1.0", "barryvdh/laravel-debugbar": "^3.2.8", "barryvdh/laravel-ide-helper": "^2.6.4", "fzaninotto/faker": "^1.4", From 837cccd4d44677a2c3e0529648b0dc1b64b2b7ec Mon Sep 17 00:00:00 2001 From: Ole Aldric Date: Mon, 19 Oct 2020 11:43:43 +0200 Subject: [PATCH 07/72] =?UTF-8?q?Added=20translation=20for=20Norwegian=20(?= =?UTF-8?q?Bokm=C3=A5l)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This will add translations for Norwegian to BookStack. It is identified by the langID no_NB --- resources/lang/en/settings.php | 1 + resources/lang/no_NB/activities.php | 49 +++++ resources/lang/no_NB/auth.php | 77 +++++++ resources/lang/no_NB/common.php | 80 +++++++ resources/lang/no_NB/components.php | 34 +++ resources/lang/no_NB/entities.php | 316 ++++++++++++++++++++++++++++ resources/lang/no_NB/errors.php | 102 +++++++++ resources/lang/no_NB/pagination.php | 12 ++ resources/lang/no_NB/passwords.php | 15 ++ resources/lang/no_NB/settings.php | 230 ++++++++++++++++++++ resources/lang/no_NB/validation.php | 114 ++++++++++ 11 files changed, 1030 insertions(+) create mode 100644 resources/lang/no_NB/activities.php create mode 100644 resources/lang/no_NB/auth.php create mode 100644 resources/lang/no_NB/common.php create mode 100644 resources/lang/no_NB/components.php create mode 100644 resources/lang/no_NB/entities.php create mode 100644 resources/lang/no_NB/errors.php create mode 100644 resources/lang/no_NB/pagination.php create mode 100644 resources/lang/no_NB/passwords.php create mode 100644 resources/lang/no_NB/settings.php create mode 100644 resources/lang/no_NB/validation.php diff --git a/resources/lang/en/settings.php b/resources/lang/en/settings.php index e280396a2..1537855b8 100755 --- a/resources/lang/en/settings.php +++ b/resources/lang/en/settings.php @@ -214,6 +214,7 @@ return [ 'ja' => '日本語', 'ko' => '한국어', 'nl' => 'Nederlands', + 'no_NB' => 'Norsk (Bokmål)' 'pl' => 'Polski', 'pt_BR' => 'Português do Brasil', 'ru' => 'Русский', diff --git a/resources/lang/no_NB/activities.php b/resources/lang/no_NB/activities.php new file mode 100644 index 000000000..3c254a61a --- /dev/null +++ b/resources/lang/no_NB/activities.php @@ -0,0 +1,49 @@ + 'opprettet side', + 'page_create_notification' => 'Siden ble opprettet', + 'page_update' => 'oppdaterte side', + 'page_update_notification' => 'Siden ble oppdatert', + 'page_delete' => 'slettet side', + 'page_delete_notification' => 'Siden ble slettet', + 'page_restore' => 'gjenopprettet side', + 'page_restore_notification' => 'Siden ble gjenopprettet', + 'page_move' => 'flyttet side', + + // Chapters + 'chapter_create' => 'opprettet kapittel', + 'chapter_create_notification' => 'Kapittelet ble opprettet', + 'chapter_update' => 'oppdaterte kapittel', + 'chapter_update_notification' => 'Kapittelet ble oppdatert', + 'chapter_delete' => 'slettet kapittel', + 'chapter_delete_notification' => 'Kapittelet ble slettet', + 'chapter_move' => 'flyttet kapittel + ', + + // Books + 'book_create' => 'opprettet bok', + 'book_create_notification' => 'Boken ble opprettet', + 'book_update' => 'oppdaterte bok', + 'book_update_notification' => 'Boken ble oppdatert', + 'book_delete' => 'slettet bok', + 'book_delete_notification' => 'Boken ble slettet', + 'book_sort' => 'sorterte bok', + 'book_sort_notification' => 'Boken ble omsortert', + + // Bookshelves + 'bookshelf_create' => 'opprettet bokhylle', + 'bookshelf_create_notification' => 'Bokhyllen ble opprettet', + 'bookshelf_update' => 'oppdaterte bokhylle', + 'bookshelf_update_notification' => 'Bokhyllen ble oppdatert', + 'bookshelf_delete' => 'slettet bokhylle', + 'bookshelf_delete_notification' => 'Bokhyllen ble slettet', + + // Other + 'commented_on' => 'kommenterte på', +]; diff --git a/resources/lang/no_NB/auth.php b/resources/lang/no_NB/auth.php new file mode 100644 index 000000000..ae145d28b --- /dev/null +++ b/resources/lang/no_NB/auth.php @@ -0,0 +1,77 @@ + 'Disse detaljene samsvarer ikke med det vi har på bok.', + 'throttle' => 'For mange forsøk, prøv igjen om :seconds sekunder.', + + // Login & Register + 'sign_up' => 'Registrer deg', + 'log_in' => 'Logg inn', + 'log_in_with' => 'Logg inn med :socialDriver', + 'sign_up_with' => 'Registrer med :socialDriver', + 'logout' => 'Logg ut', + + 'name' => 'Navn', + 'username' => 'Brukernavn', + 'email' => 'E-post', + 'password' => 'Passord', + 'password_confirm' => 'Bekreft passord', + 'password_hint' => 'Må inneholde 7 tegn', + 'forgot_password' => 'Glemt passord?', + 'remember_me' => 'Husk meg', + 'ldap_email_hint' => 'Oppgi en e-post for denne kontoen.', + 'create_account' => 'Opprett konto', + 'already_have_account' => 'Har du allerede en konto?', + 'dont_have_account' => 'Mangler du en konto?', + 'social_login' => 'Sosiale kontoer', + 'social_registration' => 'Registrer via sosiale kontoer', + 'social_registration_text' => 'Bruk en annen tjeneste for å registrere deg.', + + 'register_thanks' => 'Takk for at du registrerte deg!', + 'register_confirm' => 'Sjekk e-posten din for informasjon som gir deg tilgang til :appName.', + 'registrations_disabled' => 'Registrering er deaktivert.', + '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.', + 'reset_password_send_button' => 'Send nullstillingslenke', + 'reset_password_sent' => 'En nullstillingslenke ble sendt til :email om den eksisterer i systemet.', + 'reset_password_success' => 'Passordet ble nullstilt.', + 'email_reset_subject' => 'Nullstill ditt :appName passord', + '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!', + 'email_confirm_text' => 'Bekreft e-posten din ved å trykke på knappen nedenfor:', + 'email_confirm_action' => 'Bekreft e-post', + 'email_confirm_send_error' => 'Bekreftelse er krevd av systemet, men systemet kan ikke sende disse. Kontakt admin for å løse problemet.', + 'email_confirm_success' => 'E-posten din er bekreftet!', + 'email_confirm_resent' => 'Bekreftelsespost ble sendt, sjekk innboksen din.', + + 'email_not_confirmed' => 'E-posten er ikke bekreftet.', + 'email_not_confirmed_text' => 'Epost-adressen er ennå ikke bekreftet.', + 'email_not_confirmed_click_link' => 'Trykk på lenken i e-posten du fikk vedrørende din registrering.', + 'email_not_confirmed_resend' => 'Om du ikke finner den i innboksen eller søppelboksen, kan du få tilsendt ny ved å trykke på knappen under.', + 'email_not_confirmed_resend_button' => 'Send bekreftelsespost på nytt', + + // User Invite + 'user_invite_email_subject' => 'Du har blitt invitert til :appName!', + 'user_invite_email_greeting' => 'En konto har blitt opprettet for deg på :appName.', + 'user_invite_email_text' => 'Trykk på knappen under for å opprette et sikkert passord:', + 'user_invite_email_action' => 'Angi passord', + 'user_invite_page_welcome' => 'Velkommen til :appName!', + 'user_invite_page_text' => 'For å fullføre prosessen må du oppgi et passord som sikrer din konto på :appName for fremtidige besøk.', + 'user_invite_page_confirm_button' => 'Bekreft passord', + 'user_invite_success' => 'Passordet er angitt, du kan nå bruke :appName!' +]; \ No newline at end of file diff --git a/resources/lang/no_NB/common.php b/resources/lang/no_NB/common.php new file mode 100644 index 000000000..8bda991f4 --- /dev/null +++ b/resources/lang/no_NB/common.php @@ -0,0 +1,80 @@ + 'Avbryt', + 'confirm' => 'Bekreft', + 'back' => 'Tilbake', + 'save' => 'Lagre', + 'continue' => 'Fortsett', + 'select' => 'Velg', + 'toggle_all' => 'Bytt alle', + 'more' => 'Mer', + + // Form Labels + 'name' => 'Navn', + 'description' => 'Beskrivelse', + 'role' => 'Rolle', + 'cover_image' => 'Bokomslag', + 'cover_image_description' => 'Bildet bør være ca. 440x250px.', + + // Actions + 'actions' => 'Handlinger', + 'view' => 'Vis', + 'view_all' => 'Vis alle', + 'create' => 'Opprett', + 'update' => 'Oppdater', + 'edit' => 'Rediger', + 'sort' => 'Sorter', + 'move' => 'Flytt', + 'copy' => 'Kopier', + 'reply' => 'Svar', + 'delete' => 'Slett', + 'delete_confirm' => 'Bekreft sletting', + 'search' => 'Søk', + 'search_clear' => 'Nullstill søk', + 'reset' => 'Nullstill', + 'remove' => 'Fjern', + 'add' => 'Legg til', + 'fullscreen' => 'Fullskjerm', + + // Sort Options + 'sort_options' => 'Sorteringsalternativer', + 'sort_direction_toggle' => 'Sorteringsretning', + 'sort_ascending' => 'Stigende sortering', + 'sort_descending' => 'Synkende sortering', + 'sort_name' => 'Navn', + 'sort_created_at' => 'Dato opprettet', + 'sort_updated_at' => 'Dato oppdatert', + + // Misc + 'deleted_user' => 'Slett bruker', + 'no_activity' => 'Ingen aktivitet å vise', + 'no_items' => 'Ingen ting å vise', + 'back_to_top' => 'Hopp til toppen', + 'toggle_details' => 'Vis/skjul detaljer', + 'toggle_thumbnails' => 'Vis/skjul miniatyrbilder', + 'details' => 'Detaljer', + 'grid_view' => 'Rutenettvisning', + 'list_view' => 'Listevisning', + 'default' => 'Standard', + 'breadcrumb' => 'Brødsmuler', + + // Header + 'profile_menu' => 'Profilmeny', + 'view_profile' => 'Vis profil', + 'edit_profile' => 'Endre Profile', + 'dark_mode' => 'Kveldsmodus', + 'light_mode' => 'Dagmodus', + + // Layout tabs + 'tab_info' => 'Informasjon', + 'tab_content' => 'Innhold', + + // Email Content + 'email_action_help' => 'Om du har problemer med å trykke på «:actionText»-knappen, bruk nettadressen under for å gå direkte dit:', + 'email_rights' => 'Kopibeskyttet', +]; diff --git a/resources/lang/no_NB/components.php b/resources/lang/no_NB/components.php new file mode 100644 index 000000000..cfc28c409 --- /dev/null +++ b/resources/lang/no_NB/components.php @@ -0,0 +1,34 @@ + 'Velg bilde', + 'image_all' => 'Alle', + 'image_all_title' => 'Vis alle bilder', + 'image_book_title' => 'Vis bilder som er lastet opp i denne boken', + 'image_page_title' => 'Vis bilder lastet opp til denne siden', + 'image_search_hint' => 'Søk på bilder etter navn', + 'image_uploaded' => 'Opplastet :uploadedDate', + 'image_load_more' => 'Last in flere', + 'image_image_name' => 'Bildenavn', + 'image_delete_used' => 'Dette bildet er brukt på sidene nedenfor.', + 'image_delete_confirm_text' => 'Vil du slette dette bildet?', + 'image_select_image' => 'Velg bilde', + 'image_dropzone' => 'Dra og slipp eller trykk her for å laste opp bilder', + 'images_deleted' => 'Bilder slettet', + 'image_preview' => 'Hurtigvisning av bilder', + 'image_upload_success' => 'Bilde ble lastet opp', + 'image_update_success' => 'Bildedetaljer ble oppdatert', + 'image_delete_success' => 'Bilde ble slettet', + 'image_upload_remove' => 'Fjern', + + // Code Editor + 'code_editor' => 'Endre kode', + 'code_language' => 'Kodespråk', + 'code_content' => 'Kodeinnhold', + 'code_session_history' => 'Sesjonshistorikk', + 'code_save' => 'Lagre kode', +]; diff --git a/resources/lang/no_NB/entities.php b/resources/lang/no_NB/entities.php new file mode 100644 index 000000000..56ded1601 --- /dev/null +++ b/resources/lang/no_NB/entities.php @@ -0,0 +1,316 @@ + 'Nylig opprettet', + 'recently_created_pages' => 'Nylig opprettede sider', + 'recently_updated_pages' => 'Nylig oppdaterte sider', + 'recently_created_chapters' => 'Nylig opprettede kapitler', + 'recently_created_books' => 'Nylig opprettede bøker', + 'recently_created_shelves' => 'Nylig opprettede bokhyller', + 'recently_update' => 'Nylig oppdatert', + 'recently_viewed' => 'Nylig vist', + 'recent_activity' => 'Nylig aktivitet', + 'create_now' => 'Opprett en nå', + 'revisions' => 'Revisjoner', + 'meta_revision' => 'Revisjon #:revisionCount', + 'meta_created' => 'Opprettet :timeLength', + 'meta_created_name' => 'Opprettet :timeLength av :user', + 'meta_updated' => 'Oppdatert :timeLength', + 'meta_updated_name' => 'Oppdatert :timeLength av :user', + 'entity_select' => 'Velg entitet', + 'images' => 'Bilder', + 'my_recent_drafts' => 'Mine nylige utkast', + 'my_recently_viewed' => 'Mine nylige visninger', + 'no_pages_viewed' => 'Du har ikke sett på noen sider', + 'no_pages_recently_created' => 'Ingen sider har nylig blitt opprettet', + 'no_pages_recently_updated' => 'Ingen sider har nylig blitt oppdatert', + 'export' => 'Eksporter', + 'export_html' => 'Nettside med alt', + 'export_pdf' => 'PDF Fil', + 'export_text' => 'Tekstfil', + + // Permissions and restrictions + 'permissions' => 'Tilganger', + 'permissions_intro' => 'Når disse er tillatt, vil disse tillatelsene ha prioritet over alle angitte rolletillatelser.', + 'permissions_enable' => 'Aktiver egendefinerte tillatelser', + 'permissions_save' => 'Lagre tillatelser', + + // Search + 'search_results' => 'Søkeresultater', + 'search_total_results_found' => ':count resultater funnet|:count totalt', + 'search_clear' => 'Nullstill søk', + 'search_no_pages' => 'Ingen sider passer med søket', + 'search_for_term' => 'Søk etter :term', + 'search_more' => 'Flere resultater', + 'search_advanced' => 'Avansert søk', + 'search_terms' => 'Søkeord', + 'search_content_type' => 'Innholdstype', + 'search_exact_matches' => 'Eksakte ord', + 'search_tags' => 'Søk på merker', + 'search_options' => 'ALternativer', + 'search_viewed_by_me' => 'Sett av meg', + 'search_not_viewed_by_me' => 'Ikke sett av meg', + 'search_permissions_set' => 'Tilganger er angitt', + 'search_created_by_me' => 'Opprettet av meg', + 'search_updated_by_me' => 'Oppdatert av meg', + 'search_date_options' => 'Datoalternativer', + 'search_updated_before' => 'Oppdatert før', + 'search_updated_after' => 'Oppdatert etter', + 'search_created_before' => 'Opprettet før', + 'search_created_after' => 'Opprettet etter', + 'search_set_date' => 'Angi dato', + 'search_update' => 'Oppdater søk', + + // Shelves + 'shelf' => 'Hylle', + 'shelves' => 'Hyller', + 'x_shelves' => ':count hylle|:count hyller', + 'shelves_long' => 'Bokhyller', + 'shelves_empty' => 'Ingen bokhyller er opprettet', + 'shelves_create' => 'Opprett ny bokhylle', + 'shelves_popular' => 'Populære bokhyller', + 'shelves_new' => 'Nye bokhyller', + 'shelves_new_action' => 'Ny bokhylle', + 'shelves_popular_empty' => 'De mest populære bokhyllene blir vist her.', + 'shelves_new_empty' => 'Nylig opprettede bokhyller vises her.', + 'shelves_save' => 'Lagre hylle', + 'shelves_books' => 'Bøker på denne hyllen', + 'shelves_add_books' => 'Legg til bøker på denne hyllen', + 'shelves_drag_books' => 'Dra bøker hit for å stable dem i denne hylla', + 'shelves_empty_contents' => 'INgen bøker er stablet i denne hylla', + 'shelves_edit_and_assign' => 'Endre hylla for å legge til bøker', + 'shelves_edit_named' => 'Endre hyllen :name', + 'shelves_edit' => 'Endre bokhylle', + 'shelves_delete' => 'Fjern bokhylle', + 'shelves_delete_named' => 'Fjern bokhyllen :name', + 'shelves_delete_explain' => "Dette vil fjerne bokhyllen ':name'. Bøkene vil ikke fjernes fra systemet.", + 'shelves_delete_confirmation' => 'Er du helt sikker på at du vil skru ned hylla?', + 'shelves_permissions' => 'Tilganger til hylla', + 'shelves_permissions_updated' => 'Hyllas tilganger er oppdatert', + 'shelves_permissions_active' => 'Hyllas tilganger er aktive', + 'shelves_copy_permissions_to_books' => 'Kopier tilganger til bøkene på hylla', + 'shelves_copy_permissions' => 'Kopier tilganger', + 'shelves_copy_permissions_explain' => 'Dette vil angi gjeldende tillatelsesinnstillinger for denne bokhyllen på alle bøkene som finnes på den. Før du aktiverer, må du forsikre deg om at endringer i tillatelsene til denne bokhyllen er lagret.', + 'shelves_copy_permission_success' => 'Tilgangene ble overført til :count bøker', + + // Books + 'book' => 'Bok', + 'books' => 'Bøker', + 'x_books' => ':count bok|:count bøker', + 'books_empty' => 'Ingen bøker er skrevet', + 'books_popular' => 'Populære bøker', + 'books_recent' => 'Nylige bøker', + 'books_new' => 'Nye bøker', + 'books_new_action' => 'Ny bok', + 'books_popular_empty' => 'De mest populære bøkene', + 'books_new_empty' => 'Siste utgivelser vises her.', + 'books_create' => 'Skriv ny bok', + 'books_delete' => 'Brenn bok', + 'books_delete_named' => 'Brenn boken :bookName', + 'books_delete_explain' => 'Dette vil brenne boken «:bookName». Alle sider i boken vil fordufte for godt.', + 'books_delete_confirmation' => 'Er du sikker på at du vil brenne boken?', + 'books_edit' => 'Endre bok', + 'books_edit_named' => 'Endre boken :bookName', + 'books_form_book_name' => 'Boktittel', + 'books_save' => 'Lagre bok', + 'books_permissions' => 'Boktilganger', + 'books_permissions_updated' => 'Boktilganger oppdatert', + 'books_empty_contents' => 'Ingen sider eller kapitler finnes i denne boken.', + 'books_empty_create_page' => 'Skriv en ny side', + 'books_empty_sort_current_book' => 'Sorter innholdet i boken', + 'books_empty_add_chapter' => 'Start på nytt kapittel', + 'books_permissions_active' => 'Boktilganger er aktive', + 'books_search_this' => 'Søk i boken', + 'books_navigation' => 'Boknavigasjon', + 'books_sort' => 'Sorter bokinnhold', + 'books_sort_named' => 'Sorter boken :bookName', + 'books_sort_name' => 'Sorter på navn', + 'books_sort_created' => 'Sorter på opprettet dato', + 'books_sort_updated' => 'Sorter på oppdatert dato', + 'books_sort_chapters_first' => 'Kapitler først', + 'books_sort_chapters_last' => 'Kapitler sist', + 'books_sort_show_other' => 'Vis andre bøker', + 'books_sort_save' => 'Lagre sortering', + + // Chapters + 'chapter' => 'Kapittel', + 'chapters' => 'Kapitler', + 'x_chapters' => ':count Kapittel|:count Kapitler', + 'chapters_popular' => 'Populære kapittler', + 'chapters_new' => 'Nytt kapittel', + 'chapters_create' => 'Skriv nytt kapittel', + 'chapters_delete' => 'Riv ut kapittel', + 'chapters_delete_named' => 'Riv ut kapittelet :chapterName', + 'chapters_delete_explain' => 'Du ønsker å rive ut kapittelet «:chapterName». Alle sidene vil bli flyttet ut av kapittelet og vil ligge direkte i boka.', + 'chapters_delete_confirm' => 'Er du sikker på at du vil rive ut dette kapittelet?', + 'chapters_edit' => 'Endre kapittel', + 'chapters_edit_named' => 'Endre kapittelet :chapterName', + 'chapters_save' => 'Lagre kapittel', + 'chapters_move' => 'Flytt kapittel', + 'chapters_move_named' => 'Flytt kapittelet :chapterName', + 'chapter_move_success' => 'Kapittelet ble flyttet til :bookName', + 'chapters_permissions' => 'Kapitteltilganger', + 'chapters_empty' => 'Det finnes ingen sider i dette kapittelet.', + 'chapters_permissions_active' => 'Kapitteltilganger er aktivert', + 'chapters_permissions_success' => 'Kapitteltilgager er oppdatert', + 'chapters_search_this' => 'Søk i dette kapittelet', + + // Pages + 'page' => 'Side', + 'pages' => 'Sider', + 'x_pages' => ':count side|:count sider', + 'pages_popular' => 'Populære sider', + 'pages_new' => 'Ny side', + 'pages_attachments' => 'Vedlegg', + 'pages_navigation' => 'Sidenavigasjon', + 'pages_delete' => 'Riv ut side', + 'pages_delete_named' => 'Riv ut siden :pageName', + 'pages_delete_draft_named' => 'Kast sideutkast :pageName', + 'pages_delete_draft' => 'Kast sideutkast', + 'pages_delete_success' => 'Siden er revet ut', + 'pages_delete_draft_success' => 'Sideutkast er kastet', + 'pages_delete_confirm' => 'Er du sikker på at du vil rive ut siden?', + 'pages_delete_draft_confirm' => 'Er du sikker på at du vil forkaste utkastet?', + 'pages_editing_named' => 'Endrer :pageName', + 'pages_edit_draft_options' => 'Utkastsalternativer', + 'pages_edit_save_draft' => 'Lagre utkast', + 'pages_edit_draft' => 'Endre utkast', + 'pages_editing_draft' => 'Redigerer utkast', + 'pages_editing_page' => 'Redigerer side', + 'pages_edit_draft_save_at' => 'Ukast lagret under ', + 'pages_edit_delete_draft' => 'Forkast utkast', + 'pages_edit_discard_draft' => 'Gi opp utkast', + 'pages_edit_set_changelog' => 'Angi endringslogg', + 'pages_edit_enter_changelog_desc' => 'Gi en kort beskrivelse av endringene dine', + 'pages_edit_enter_changelog' => 'Se endringslogg', + 'pages_save' => 'Lagre side', + 'pages_title' => 'Sidetittel', + 'pages_name' => 'Sidenavn', + 'pages_md_editor' => 'Tekstbehandler', + 'pages_md_preview' => 'Forhåndsvisning', + 'pages_md_insert_image' => 'Lim inn bilde', + 'pages_md_insert_link' => 'Lim in lenke', + 'pages_md_insert_drawing' => 'Lim inn tegning', + 'pages_not_in_chapter' => 'Siden tilhører ingen kapittel', + 'pages_move' => 'Flytt side', + 'pages_move_success' => 'Siden ble flyttet til ":parentName"', + 'pages_copy' => 'Kopier side', + 'pages_copy_desination' => 'Destinasjon', + 'pages_copy_success' => 'Siden ble flyttet', + 'pages_permissions' => 'Sidetilganger', + 'pages_permissions_success' => 'Sidens tilganger ble endret', + 'pages_revision' => 'Revisjon', + 'pages_revisions' => 'Sidens revisjoner', + 'pages_revisions_named' => 'Revisjoner for :pageName', + 'pages_revision_named' => 'Revisjoner for :pageName', + 'pages_revisions_created_by' => 'Skrevet av', + 'pages_revisions_date' => 'Revideringsdato', + 'pages_revisions_number' => '#', + 'pages_revisions_numbered' => 'Revisjon #:id', + 'pages_revisions_numbered_changes' => 'Endringer på revisjon #:id', + 'pages_revisions_changelog' => 'Endringslogg', + 'pages_revisions_changes' => 'Endringer', + 'pages_revisions_current' => 'Siste versjon', + 'pages_revisions_preview' => 'Forhåndsvisning', + 'pages_revisions_restore' => 'Gjenopprett', + 'pages_revisions_none' => 'Denne siden har ingen revisjoner', + 'pages_copy_link' => 'Kopier lenke', + 'pages_edit_content_link' => 'Endre innhold', + 'pages_permissions_active' => 'Sidetilganger er aktive', + 'pages_initial_revision' => 'Første publisering', + 'pages_initial_name' => 'Ny side', + 'pages_editing_draft_notification' => 'Du skriver på et utkast som sist ble lagret :timeDiff.', + 'pages_draft_edited_notification' => 'Siden har blitt endret siden du startet. Det anbefales at du forkaster dine endringer.', + 'pages_draft_edit_active' => [ + 'start_a' => ':count forfattere har begynt å endre denne siden.', + 'start_b' => ':userName skriver på siden for øyeblikket', + 'time_a' => 'siden sist siden ble oppdatert', + 'time_b' => 'i løpet av de siste :minCount minuttene', + 'message' => ':start :time. Prøv å ikke overskriv hverandres endringer!', + ], + 'pages_draft_discarded' => 'Forkastet, viser nå siste endringer fra siden slik den er lagret.', + 'pages_specific' => 'Bestemt side', + 'pages_is_template' => 'Sidemal', + + // Editor Sidebar + 'page_tags' => 'Sidemerker', + 'chapter_tags' => 'Kapittelmerker', + 'book_tags' => 'Bokmerker', + 'shelf_tags' => 'Hyllemerker', + 'tag' => 'Merke', + 'tags' => 'Merker', + 'tag_name' => 'Merketittel', + 'tag_value' => 'Merkeverdi (Valgfritt)', + 'tags_explain' => "Legg til merker for å kategorisere innholdet ditt. \n Du kan legge til merkeverdier for å beskrive dem ytterligere.", + 'tags_add' => 'Legg til flere merker', + 'tags_remove' => 'Fjern merke', + 'attachments' => 'Vedlegg', + 'attachments_explain' => 'Last opp vedlegg eller legg til lenker for å berike innholdet. Disse vil vises i sidestolpen på siden.', + 'attachments_explain_instant_save' => 'Endringer her blir lagret med en gang.', + 'attachments_items' => 'Vedlegg', + 'attachments_upload' => 'Last opp vedlegg', + 'attachments_link' => 'Fest lenke', + 'attachments_set_link' => 'Angi lenke', + 'attachments_delete' => 'Er du sikker på at du vil fjerne vedlegget?', + 'attachments_dropzone' => 'Dra og slipp eller trykk her for å feste vedlegg', + 'attachments_no_files' => 'Ingen vedlegg er lastet opp', + 'attachments_explain_link' => 'Du kan feste lenker til denne. Det kan være henvisning til andre sider, bøker etc. eller lenker fra nettet.', + 'attachments_link_name' => 'Lenkenavn', + 'attachment_link' => 'Vedleggslenke', + 'attachments_link_url' => 'Lenke til vedlegg', + 'attachments_link_url_hint' => 'Adresse til lenke eller vedlegg', + 'attach' => 'Fest', + 'attachments_insert_link' => 'Fest vedleggslenke', + 'attachments_edit_file' => 'Endre vedlegg', + 'attachments_edit_file_name' => 'Vedleggsnavn', + 'attachments_edit_drop_upload' => 'Dra og slipp eller trykk her for å oppdatere eller overskrive', + 'attachments_order_updated' => 'Vedleggssortering endret', + 'attachments_updated_success' => 'Vedleggsdetaljer endret', + 'attachments_deleted' => 'Vedlegg fjernet', + 'attachments_file_uploaded' => 'Vedlegg ble lastet opp', + 'attachments_file_updated' => 'Vedlegget ble oppdatert', + 'attachments_link_attached' => 'Lenken ble festet til siden', + 'templates' => 'Maler', + 'templates_set_as_template' => 'Siden er en mal', + 'templates_explain_set_as_template' => 'Du kan angi denne siden som en mal slik at innholdet kan brukes når du oppretter andre sider. Andre brukere vil kunne bruke denne malen hvis de har visningstillatelser for denne siden.', + 'templates_replace_content' => 'Bytt sideinnhold', + 'templates_append_content' => 'Legg til neders på siden', + 'templates_prepend_content' => 'Legg til øverst på siden', + + // Profile View + 'profile_user_for_x' => 'Medlem i :time', + 'profile_created_content' => 'Har skrevet', + 'profile_not_created_pages' => ':userName har ikke forfattet noen sider', + 'profile_not_created_chapters' => ':userName har ikke opprettet noen kapitler', + 'profile_not_created_books' => ':userName har ikke laget noen bøker', + 'profile_not_created_shelves' => ':userName har ikke hengt opp noen hyller', + + // Comments + 'comment' => 'Kommentar', + 'comments' => 'Kommentarer', + 'comment_add' => 'Skriv kommentar', + 'comment_placeholder' => 'Skriv en kommentar her', + 'comment_count' => '{0} Ingen kommentarer|{1} 1 kommentar|[2,*] :count kommentarer', + 'comment_save' => 'Publiser kommentar', + 'comment_saving' => 'Publiserer ...', + 'comment_deleting' => 'Fjerner...', + 'comment_new' => 'Ny kommentar', + 'comment_created' => 'kommenterte :createDiff', + 'comment_updated' => 'Oppdatert :updateDiff av :username', + 'comment_deleted_success' => 'Kommentar fjernet', + 'comment_created_success' => 'Kommentar skrevet', + 'comment_updated_success' => 'Kommentar endret', + 'comment_delete_confirm' => 'Er du sikker på at du vil fjerne kommentaren?', + 'comment_in_reply_to' => 'Som svar til :commentId', + + // Revision + '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.' +]; \ No newline at end of file diff --git a/resources/lang/no_NB/errors.php b/resources/lang/no_NB/errors.php new file mode 100644 index 000000000..4e5c07f65 --- /dev/null +++ b/resources/lang/no_NB/errors.php @@ -0,0 +1,102 @@ + 'Du har ikke tilgang til å se denne siden.', + 'permissionJson' => 'Du har ikke tilgang til å utføre denne handlingen.', + + // Auth + 'error_user_exists_different_creds' => 'En konto med :email finnes allerede, men har andre detaljer.', + 'email_already_confirmed' => 'E-posten er allerede bekreftet, du kan forsøke å logge inn.', + 'email_confirmation_invalid' => 'Denne bekreftelseskoden er allerede benyttet eller utgått. Prøv å registrere på nytt.', + 'email_confirmation_expired' => 'Bekreftelseskoden er allerede utgått, en ny e-post er sendt.', + 'email_confirmation_awaiting' => 'Du må bekrefte e-posten for denne kontoen.', + 'ldap_fail_anonymous' => 'LDAP kan ikke benyttes med anonym tilgang for denne tjeneren.', + 'ldap_fail_authed' => 'LDAP tilgang feilet med angitt DN', + 'ldap_extension_not_installed' => 'LDAP PHP modulen er ikke installert.', + 'ldap_cannot_connect' => 'Klarer ikke koble til LDAP på denne adressen', + 'saml_already_logged_in' => 'Allerede logget inn', + 'saml_user_not_registered' => 'Kontoen med navn :name er ikke registert, registrering er også deaktivert.', + 'saml_no_email_address' => 'Denne kontoinformasjonen finnes ikke i det eksterne autentiseringssystemet.', + 'saml_invalid_response_id' => 'Forespørselen fra det eksterne autentiseringssystemet gjenkjennes ikke av en prosess som startes av dette programmet. Å navigere tilbake etter pålogging kan forårsake dette problemet.', + 'saml_fail_authed' => 'Innlogging gjennom :system feilet. Fikk ikke kontakt med autentiseringstjeneren.', + 'social_no_action_defined' => 'Ingen handlinger er definert', + 'social_login_bad_response' => "Feilmelding mottat fra :socialAccount innloggingstjeneste: \n:error", + 'social_account_in_use' => 'Denne :socialAccount kontoen er allerede registrert, Prøv å logge inn med :socialAccount alternativet.', + 'social_account_email_in_use' => 'E-posten :email er allerede i bruk. Har du allerede en konto hos :socialAccount kan dette angis fra profilsiden din.', + 'social_account_existing' => 'Denne :socialAccount er allerede koblet til din konto.', + 'social_account_already_used_existing' => 'This :socialAccount account is already used by another user.', + 'social_account_not_used' => 'Denne :socialAccount konten er ikke koblet til noen konto, angi denne i profilinnstillingene dine. ', + 'social_account_register_instructions' => 'Har du ikke en konto her ennå, kan du benytte :socialAccount alternativet for å registrere deg.', + 'social_driver_not_found' => 'Autentiseringstjeneste fra sosiale medier er ikke installert', + 'social_driver_not_configured' => 'Dine :socialAccount innstilliner er ikke angitt.', + 'invite_token_expired' => 'Invitasjonslenken har utgått, du kan forsøke å be om nytt passord istede.', + + // System + 'path_not_writable' => 'Filstien :filePath aksepterer ikke filer, du må sjekke filstitilganger i systemet.', + 'cannot_get_image_from_url' => 'Kan ikke hente bilde fra :url', + 'cannot_create_thumbs' => 'Kan ikke opprette miniatyrbilder. GD PHP er ikke installert.', + 'server_upload_limit' => 'Vedlegget er for stort, forsøk med et mindre vedlegg.', + 'uploaded' => 'Tjenesten aksepterer ikke vedlegg som er så stor.', + 'image_upload_error' => 'Bildet kunne ikke lastes opp, forsøk igjen.', + 'image_upload_type_error' => 'Bildeformatet støttes ikke, forsøk med et annet format.', + 'file_upload_timeout' => 'Opplastingen gikk ut på tid.', + + // Attachments + 'attachment_not_found' => 'Vedlegget ble ikke funnet', + + // Pages + 'page_draft_autosave_fail' => 'Kunne ikke lagre utkastet, forsikre deg om at du er tilkoblet tjeneren (Har du nettilgang?)', + 'page_custom_home_deletion' => 'Kan ikke slette en side som er satt som forside.', + + // Entities + 'entity_not_found' => 'Entitet ble ikke funnet', + 'bookshelf_not_found' => 'Bokhyllen ble ikke funnet', + 'book_not_found' => 'Boken ble ikke funnet', + 'page_not_found' => 'Siden ble ikke funnet', + 'chapter_not_found' => 'Kapittel ble ikke funnet', + 'selected_book_not_found' => 'Den valgte boken eksisterer ikke', + 'selected_book_chapter_not_found' => 'Den valgte boken eller kapittelet eksisterer ikke', + 'guests_cannot_save_drafts' => 'Gjester kan ikke lagre utkast', + + // Users + 'users_cannot_delete_only_admin' => 'Du kan ikke kaste ut den eneste administratoren', + 'users_cannot_delete_guest' => 'Du kan ikke slette gjestebrukeren (Du kan deaktivere offentlig visning istede)', + + // Roles + 'role_cannot_be_edited' => 'Denne rollen kan ikke endres', + 'role_system_cannot_be_deleted' => 'Denne systemrollen kan ikke slettes', + 'role_registration_default_cannot_delete' => 'Du kan ikke slette en rolle som er satt som registreringsrolle (rollen nye kontoer får når de registrerer seg)', + 'role_cannot_remove_only_admin' => 'Denne brukeren er den eneste brukeren som er tildelt administratorrollen. Tilordne administratorrollen til en annen bruker før du prøver å fjerne den her.', + + // Comments + 'comment_list' => 'Det oppstod en feil under henting av kommentarene.', + 'cannot_add_comment_to_draft' => 'Du kan ikke legge til kommentarer i et utkast.', + 'comment_add' => 'Det oppsto en feil da kommentaren skulle legges til / oppdateres.', + 'comment_delete' => 'Det oppstod en feil under sletting av kommentaren.', + 'empty_comment' => 'Kan ikke legge til en tom kommentar.', + + // Error pages + '404_page_not_found' => 'Siden finnes ikke', + 'sorry_page_not_found' => 'Beklager, siden du leter etter ble ikke funnet.', + 'sorry_page_not_found_permission_warning' => 'Hvis du forventet at denne siden skulle eksistere, har du kanskje ikke tillatelse til å se den.', + 'return_home' => 'Gå til hovedside', + 'error_occurred' => 'En feil oppsto', + 'app_down' => ':appName er nede for øyeblikket', + 'back_soon' => 'Den vil snart komme tilbake.', + + // API errors + 'api_no_authorization_found' => 'Ingen autorisasjonstoken ble funnet på forespørselen', + 'api_bad_authorization_format' => 'Det ble funnet et autorisasjonstoken på forespørselen, men formatet virket feil', + 'api_user_token_not_found' => 'Ingen samsvarende API-token ble funnet for det angitte autorisasjonstokenet', + 'api_incorrect_token_secret' => 'Hemmeligheten som er gitt for det gitte brukte API-tokenet er feil', + 'api_user_no_api_permission' => 'Eieren av det brukte API-tokenet har ikke tillatelse til å ringe API-samtaler', + 'api_user_token_expired' => 'Autorisasjonstokenet som er brukt, har utløpt', + + // Settings & Maintenance + 'maintenance_test_email_failure' => 'Feil kastet når du sendte en test-e-post:', + +]; diff --git a/resources/lang/no_NB/pagination.php b/resources/lang/no_NB/pagination.php new file mode 100644 index 000000000..d910da124 --- /dev/null +++ b/resources/lang/no_NB/pagination.php @@ -0,0 +1,12 @@ + '« Forrige', + 'next' => 'Neste »', + +]; diff --git a/resources/lang/no_NB/passwords.php b/resources/lang/no_NB/passwords.php new file mode 100644 index 000000000..8c3215b42 --- /dev/null +++ b/resources/lang/no_NB/passwords.php @@ -0,0 +1,15 @@ + 'Passord må inneholde minst åtte tegn og samsvarer med bekreftelsen.', + '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/no_NB/settings.php b/resources/lang/no_NB/settings.php new file mode 100644 index 000000000..873de5c47 --- /dev/null +++ b/resources/lang/no_NB/settings.php @@ -0,0 +1,230 @@ + 'Innstillinger', + 'settings_save' => 'Lagre innstillinger', + 'settings_save_success' => 'Innstillinger lagret', + + // App Settings + 'app_customization' => 'Tilpassing', + 'app_features_security' => 'Funksjoner og sikkerhet', + 'app_name' => 'Applikasjonsnavn', + 'app_name_desc' => 'Dette navnet vises i overskriften og i alle e-postmeldinger som sendes av systemet.', + 'app_name_header' => 'Vis navn i topptekst', + 'app_public_access' => 'Offentlig tilgang', + 'app_public_access_desc' => 'Hvis du aktiverer dette alternativet, kan besøkende, som ikke er logget på, få tilgang til innhold i din BookStack-forekomst.', + 'app_public_access_desc_guest' => 'Tilgang for offentlige besøkende kan kontrolleres gjennom "Gjest" -brukeren.', + 'app_public_access_toggle' => 'Tillat offentlig tilgang', + 'app_public_viewing' => 'Tillat offentlig visning?', + 'app_secure_images' => 'Høyere sikkerhet på bildeopplastinger', + 'app_secure_images_toggle' => 'Enable høyere sikkerhet på bildeopplastinger', + 'app_secure_images_desc' => 'Av ytelsesgrunner er alle bilder offentlige. Dette alternativet legger til en tilfeldig streng som er vanskelig å gjette foran bildets nettadresser. Forsikre deg om at katalogindekser ikke er aktivert for å forhindre enkel tilgang.', + 'app_editor' => 'Tekstbehandler', + 'app_editor_desc' => 'Velg hvilken tekstbehandler som skal brukes av alle brukere til å redigere sider.', + 'app_custom_html' => 'Tilpasset HTML-hodeinnhold', + 'app_custom_html_desc' => 'Alt innhold som legges til her, blir satt inn i bunnen av -delen på hver side. Dette er praktisk for å overstyre stiler eller legge til analysekode.', + 'app_custom_html_disabled_notice' => 'Tilpasset HTML-hodeinnhold er deaktivert på denne innstillingssiden for å sikre at eventuelle endringer ødelegger noe, kan tilbakestilles.', + 'app_logo' => 'Applikasjonslogo', + 'app_logo_desc' => 'Dette bildet skal være 43 px høyt.
Store bilder blir nedskalert.', + 'app_primary_color' => 'Applikasjonens primærfarge', + 'app_primary_color_desc' => 'Angir primærfargen for applikasjonen inkludert banner, knapper og lenker.', + 'app_homepage' => 'Applikasjonens hjemmeside', + 'app_homepage_desc' => 'Velg en visning som skal vises på hjemmesiden i stedet for standardvisningen. Sidetillatelser ignoreres for utvalgte sider.', + 'app_homepage_select' => 'Velg en side', + 'app_disable_comments' => 'Deaktiver kommentarer', + 'app_disable_comments_toggle' => 'Deaktiver kommentarer', + 'app_disable_comments_desc' => 'Deaktiver kommentarer på tvers av alle sidene i applikasjonen.
Eksisterende kommentarer vises ikke.', + + // Color settings + 'content_colors' => 'Innholdsfarger', + 'content_colors_desc' => 'Angir farger for alle elementene i sideorganisasjonshierarkiet. Det anbefales å lese farger med en lignende lysstyrke som standardfargene for lesbarhet.', + 'bookshelf_color' => 'Hyllefarge', + 'book_color' => 'Bokfarge', + 'chapter_color' => 'Kapittelfarge', + 'page_color' => 'Sidefarge', + 'page_draft_color' => 'Sideutkastsfarge', + + // Registration Settings + 'reg_settings' => 'Registrering', + 'reg_enable' => 'Tillat registrering', + 'reg_enable_toggle' => 'Tillat registrering', + 'reg_enable_desc' => 'Når registrering er aktivert vil brukeren kunne registrere seg som applikasjonsbruker. Ved registrering får de en standard brukerrolle.', + 'reg_default_role' => 'Standard brukerrolle etter registrering', + 'reg_enable_external_warning' => 'Alternativet ovenfor ignoreres mens ekstern LDAP- eller SAML-autentisering er aktiv. Brukerkontoer for ikke-eksisterende medlemmer blir automatisk opprettet hvis autentisering mot det eksterne systemet i bruk lykkes.', + 'reg_email_confirmation' => 'E-postbekreftelse', + 'reg_email_confirmation_toggle' => 'Krev e-postbekreftelse', + 'reg_confirm_email_desc' => 'Hvis domenebegrensning brukes, vil e-postbekreftelse være nødvendig, og dette alternativet vil bli ignorert.', + 'reg_confirm_restrict_domain' => 'Domenebegrensning', + 'reg_confirm_restrict_domain_desc' => 'Skriv inn en kommaseparert liste over e-postdomener du vil begrense registreringen til. Brukerne vil bli sendt en e-post for å bekrefte adressen deres før de får lov til å kommunisere med applikasjonen.
Vær oppmerksom på at brukere vil kunne endre e-postadressene sine etter vellykket registrering.', + 'reg_confirm_restrict_domain_placeholder' => 'Ingen begrensninger er satt', + + // Maintenance settings + 'maint' => 'Maintenance', + '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_ignore_revisions' => 'Ignorer bilder i revisjoner', + '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?', + 'maint_image_cleanup_success' => ':count potensielt ubrukte bilder funnet og slettet!', + 'maint_image_cleanup_nothing_found' => 'Ingen ubrukte bilder funnet, ingenting slettet!', + 'maint_send_test_email' => 'Send en test-e-post', + 'maint_send_test_email_desc' => 'Dette sender en test-e-post til din e-postadresse som er angitt i profilen din.', + 'maint_send_test_email_run' => 'Send en test-e-post', + 'maint_send_test_email_success' => 'Send en test-e-post til :address', + 'maint_send_test_email_mail_subject' => 'Test-e-post', + 'maint_send_test_email_mail_greeting' => 'E-postsending ser ut til å fungere!', + 'maint_send_test_email_mail_text' => 'Gratulerer! Da du mottok dette e-postvarselet, ser det ut til at e-postinnstillingene dine er konfigurert riktig.', + + // Audit Log + 'audit' => 'Revisjonslogg', + 'audit_desc' => 'Denne revisjonsloggen viser en liste over aktiviteter som spores i systemet. Denne listen er ufiltrert i motsetning til lignende aktivitetslister i systemet der tillatelsesfiltre brukes.', + 'audit_event_filter' => 'Hendelsesfilter', + 'audit_event_filter_no_filter' => 'Ingen filter', + 'audit_deleted_item' => 'Slettet ting', + 'audit_deleted_item_name' => 'Navn: :name', + 'audit_table_user' => 'Kontoholder', + 'audit_table_event' => 'Hendelse', + 'audit_table_item' => 'Relatert ting', + 'audit_table_date' => 'Aktivitetsdato', + 'audit_date_from' => 'Datoperiode fra', + 'audit_date_to' => 'Datoperiode til', + + // Role Settings + 'roles' => 'Roller', + 'role_user_roles' => 'Kontoroller', + 'role_create' => 'Opprett ny rolle', + 'role_create_success' => 'Rolle opprettet', + '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_sure' => 'Er du sikker på at du vil slette rollen?', + 'role_delete_success' => 'Rollen ble slettet', + 'role_edit' => 'Endre rolle', + 'role_details' => 'Rolledetaljer', + 'role_name' => 'Rollenavn', + 'role_desc' => 'Kort beskrivelse av rolle', + 'role_external_auth_id' => 'Ekstern godkjennings-ID', + 'role_system' => 'Systemtilganger', + 'role_manage_users' => 'Behandle kontoer', + 'role_manage_roles' => 'Behandle roller og rolletilganger', + 'role_manage_entity_permissions' => 'Behandle bok-, kapittel- og sidetilganger', + 'role_manage_own_entity_permissions' => 'Behandle tilganger på egne verk', + 'role_manage_page_templates' => 'Behandle sidemaler', + 'role_access_api' => 'Systemtilgang API', + 'role_manage_settings' => 'Behandle applikasjonsinnstillinger', + 'role_asset' => 'Eiendomstillatelser', + 'roles_system_warning' => 'Vær oppmerksom på at tilgang til noen av de ovennevnte tre tillatelsene kan tillate en bruker å endre sine egne rettigheter eller rettighetene til andre i systemet. Bare tildel roller med disse tillatelsene til pålitelige brukere.', + 'role_asset_desc' => 'Disse tillatelsene kontrollerer standard tilgang til eiendelene i systemet. Tillatelser til bøker, kapitler og sider overstyrer disse tillatelsene.', + 'role_asset_admins' => 'Administratorer får automatisk tilgang til alt innhold, men disse alternativene kan vise eller skjule UI-alternativer.', + 'role_all' => 'Alle', + 'role_own' => 'Egne', + 'role_controlled_by_asset' => 'Kontrollert av eiendelen de er lastet opp til', + 'role_save' => 'Lagre rolle', + 'role_update_success' => 'Rollen ble oppdatert', + 'role_users' => 'Kontoholdere med denne rollen', + 'role_users_none' => 'Ingen kontoholdere er gitt denne rollen', + + // Users + 'users' => 'Users', + 'user_profile' => 'Profil', + 'users_add_new' => 'Register ny konto', + 'users_search' => 'Søk i kontoer', + 'users_details' => 'Kontodetaljer', + 'users_details_desc' => 'Angi et visningsnavn og en e-postadresse for denne kontoholderen. E-postadressen vil bli brukt til å logge på applikasjonen.', + 'users_details_desc_no_email' => 'Angi et visningsnavn for denne kontoholderen slik at andre kan gjenkjenne dem.', + 'users_role' => 'Roller', + 'users_role_desc' => 'Velg hvilke roller denne kontoholderen vil bli tildelt. Hvis en kontoholderen er tildelt flere roller, vil tillatelsene fra disse rollene stable seg, og de vil motta alle evnene til de tildelte rollene.', + 'users_password' => 'Passord', + 'users_password_desc' => 'Angi et passord som brukes til å logge på applikasjonen. Dette må bestå av minst 6 tegn.', + 'users_send_invite_text' => 'Du kan velge å sende denne kontoholderen en invitasjons-e-post som lar dem angi sitt eget passord, ellers kan du selv angi passordet.', + 'users_send_invite_option' => 'Send invitasjonsmelding', + 'users_external_auth_id' => 'Ekstern godkjennings-ID', + 'users_external_auth_id_desc' => 'Dette er ID-en som brukes til å matche denne kontoholderen når de kommuniserer med det eksterne autentiseringssystemet.', + 'users_password_warning' => 'Fyll bare ut nedenfor hvis du vil endre passordet ditt.', + 'users_system_public' => 'Denne brukeren representerer alle gjester som besøker appliaksjonen din. Den kan ikke brukes til å logge på, men tildeles automatisk.', + 'users_delete' => 'Slett konto', + 'users_delete_named' => 'Slett kontoen :userName', + 'users_delete_warning' => 'Dette vil fullstendig slette denne brukeren med navnet «:userName» fra systemet.', + 'users_delete_confirm' => 'Er du sikker på at du vil slette denne kontoen?', + 'users_delete_success' => 'Konto slettet', + 'users_edit' => 'Rediger konto', + 'users_edit_profile' => 'Rediger profil', + 'users_edit_success' => 'Kontoen ble oppdatert', + 'users_avatar' => 'Kontobilde', + 'users_avatar_desc' => 'Velg et bilde for å representere denne kontoholderen. Dette skal være omtrent 256px kvadrat.', + 'users_preferred_language' => 'Foretrukket språk', + 'users_preferred_language_desc' => 'Dette alternativet vil endre språket som brukes til brukergrensesnittet til applikasjonen. Dette påvirker ikke noe brukeropprettet innhold.', + 'users_social_accounts' => 'Sosiale kontoer', + 'users_social_accounts_info' => 'Her kan du koble andre kontoer for raskere og enklere pålogging. Hvis du frakobler en konto her, tilbakekaller ikke dette tidligere autorisert tilgang. Tilbakekall tilgang fra profilinnstillingene dine på den tilkoblede sosiale kontoen.', + 'users_social_connect' => 'Koble til konto', + 'users_social_disconnect' => 'Koble fra konto', + 'users_social_connected' => ':socialAccount ble lagt til din konto.', + 'users_social_disconnected' => ':socialAccount ble koblet fra din konto.', + 'users_api_tokens' => 'API-nøkler', + 'users_api_tokens_none' => 'Ingen API-nøkler finnes for denne kontoen', + 'users_api_tokens_create' => 'Opprett nøkkel', + 'users_api_tokens_expires' => 'Utløper', + 'users_api_tokens_docs' => 'API-dokumentasjon', + + // API Tokens + 'user_api_token_create' => 'Opprett API-nøkkel', + 'user_api_token_name' => 'Navn', + 'user_api_token_name_desc' => 'Gi nøkkelen et lesbart navn som en fremtidig påminnelse om det tiltenkte formålet.', + 'user_api_token_expiry' => 'Utløpsdato', + 'user_api_token_expiry_desc' => 'Angi en dato da denne nøkkelen utløper. Etter denne datoen vil forespørsler som er gjort med denne nøkkelen ikke lenger fungere. Å la dette feltet stå tomt vil sette utløpsdato 100 år inn i fremtiden.', + 'user_api_token_create_secret_message' => 'Umiddelbart etter å ha opprettet denne nøkkelen vil en identifikator og hemmelighet bli generert og vist. Hemmeligheten vil bare vises en gang, så husk å kopiere verdien til et trygt sted før du fortsetter.', + 'user_api_token_create_success' => 'API-nøkkel ble opprettet', + 'user_api_token_update_success' => 'API-nøkkel ble oppdatert', + 'user_api_token' => 'API-nøkkel', + 'user_api_token_id' => 'Identifikator', + 'user_api_token_id_desc' => 'Dette er en ikke-redigerbar systemgenerert identifikator for denne nøkkelen som må oppgis i API-forespørsler.', + 'user_api_token_secret' => 'Hemmelighet', + 'user_api_token_secret_desc' => 'Dette er en systemgenerert hemmelighet for denne nøkkelen som må leveres i API-forespørsler. Dette vises bare denne gangen, så kopier denne verdien til et trygt sted.', + 'user_api_token_created' => 'Nøkkel opprettet :timeAgo', + 'user_api_token_updated' => 'Nøkkel oppdatert :timeAgo', + 'user_api_token_delete' => 'Slett nøkkel', + 'user_api_token_delete_warning' => 'Dette vil slette API-nøkkelen \':tokenName\' fra systemet.', + 'user_api_token_delete_confirm' => 'Sikker på at du vil slette nøkkelen?', + 'user_api_token_delete_success' => 'API-nøkkelen ble slettet', + + //! If editing translations files directly please ignore this in all + //! languages apart from en. Content will be auto-copied from en. + //!//////////////////////////////// + 'language_select' => [ + 'en' => 'English', + 'ar' => 'العربية', + 'bg' => 'Bǎlgarski', + 'cs' => 'Česky', + 'da' => 'Dansk', + 'de' => 'Deutsch (Sie)', + 'de_informal' => 'Deutsch (Du)', + 'es' => 'Español', + 'es_AR' => 'Español Argentina', + 'fr' => 'Français', + 'he' => 'עברית', + 'hu' => 'Magyar', + 'it' => 'Italian', + 'ja' => '日本語', + 'ko' => '한국어', + 'nl' => 'Nederlands', + 'pl' => 'Polski', + 'pt_BR' => 'Português do Brasil', + 'ru' => 'Русский', + 'sk' => 'Slovensky', + 'sl' => 'Slovenščina', + 'sv' => 'Svenska', + 'tr' => 'Türkçe', + 'uk' => 'Українська', + 'vi' => 'Tiếng Việt', + 'zh_CN' => '简体中文', + 'zh_TW' => '繁體中文', + ] + //!//////////////////////////////// +]; diff --git a/resources/lang/no_NB/validation.php b/resources/lang/no_NB/validation.php new file mode 100644 index 000000000..8060931fa --- /dev/null +++ b/resources/lang/no_NB/validation.php @@ -0,0 +1,114 @@ + ':attribute må aksepteres.', + 'active_url' => ':attribute er ikke en godkjent URL.', + 'after' => ':attribute må være en dato etter :date.', + 'alpha' => ':attribute kan kun inneholde bokstaver.', + 'alpha_dash' => ':attribute kan kunne inneholde bokstaver, tall, bindestreker eller understreker.', + 'alpha_num' => ':attribute kan kun inneholde bokstaver og tall.', + 'array' => ':attribute må være en liste.', + 'before' => ':attribute må være en dato før :date.', + 'between' => [ + 'numeric' => ':attribute må være mellom :min og :max.', + 'file' => ':attribute må være mellom :min og :max kilobytes.', + 'string' => ':attribute må være mellom :min og :max tegn.', + 'array' => ':attribute må være mellom :min og :max ting.', + ], + 'boolean' => ':attribute feltet kan bare være sann eller falsk.', + 'confirmed' => ':attribute bekreftelsen samsvarer ikke.', + 'date' => ':attribute er ikke en gyldig dato.', + 'date_format' => ':attribute samsvarer ikke med :format.', + 'different' => ':attribute og :other må være forskjellige.', + 'digits' => ':attribute må være :digits tall.', + 'digits_between' => ':attribute må være mellomg :min og :max tall.', + 'email' => ':attribute må være en gyldig e-post.', + 'ends_with' => ':attribute må slutte med en av verdiene: :values', + 'filled' => ':attribute feltet er påkrevd.', + 'gt' => [ + 'numeric' => ':attribute må være større enn :value.', + 'file' => ':attribute må være større enn :value kilobytes.', + 'string' => ':attribute må være større enn :value tegn.', + 'array' => ':attribute må ha mer en :value ting.', + ], + 'gte' => [ + 'numeric' => ':attribute må være større enn eller lik :value.', + 'file' => ':attribute må være større enn eller lik :value kilobytes.', + 'string' => ':attribute må være større enn eller lik :value tegn.', + 'array' => ':attribute må ha :value eller flere ting.', + ], + 'exists' => 'Den valgte :attribute er ugyldig.', + 'image' => ':attribute må være et bilde.', + 'image_extension' => ':attribute må ha støttet formattype.', + 'in' => 'Den valgte :attribute er ugyldig.', + 'integer' => ':attribute må være et heltall', + 'ip' => ':attribute må være en gyldig IP adresse.', + 'ipv4' => ':attribute må være en gyldig IPv4 adresse.', + 'ipv6' => ':attribute må være en gyldig IPv6 adresse.', + 'json' => ':attribute må være en gyldig JSON tekststreng.', + 'lt' => [ + 'numeric' => ':attribute må være mindre enn :value.', + 'file' => ':attribute må være mindre enn :value kilobytes.', + 'string' => ':attribute må være mindre enn :value tegn.', + 'array' => ':attribute må ha mindre enn :value ting.', + ], + 'lte' => [ + 'numeric' => ':attribute må være mindre enn eller lik :value.', + 'file' => ':attribute må være mindre enn eller lik :value kilobytes.', + 'string' => ':attribute må være mindre enn eller lik :value characters.', + 'array' => ':attribute må ha mindre enn eller lik :value ting.', + ], + 'max' => [ + 'numeric' => ':attribute kan ikke være større enn :max.', + 'file' => ':attribute kan ikke være større enn :max kilobytes.', + 'string' => ':attribute kan ikke være større enn :max tegn.', + 'array' => ':attribute kan ikke inneholde mer enn :max ting.', + ], + 'mimes' => ':attribute må være en fil av typen: :values.', + 'min' => [ + 'numeric' => ':attribute må være på minst :min.', + 'file' => ':attribute må være på minst :min kilobytes.', + 'string' => ':attribute må være på minst :min tegn.', + 'array' => ':attribute må minst ha :min ting.', + ], + 'no_double_extension' => ':attribute kan bare ha en formattype spesifisert.', + 'not_in' => 'Den valgte :attribute er ugyldig.', + 'not_regex' => ':attribute format er ugyldig.', + 'numeric' => ':attribute må være et nummer.', + 'regex' => ':attribute format er ugyldig.', + 'required' => ':attribute feltet er påkrevt.', + 'required_if' => ':attribute feltet er påkrevt når :other er :value.', + 'required_with' => ':attribute feltet er påkrevt når :values er tilgjengelig.', + 'required_with_all' => ':attribute feltet er påkrevt når :values er tilgjengelig', + 'required_without' => ':attribute feltet er påkrevt når :values ikke er tilgjengelig.', + 'required_without_all' => ':attribute feltet er påkrevt når ingen av :values er tilgjengelig.', + 'same' => ':attribute og :other må samsvare.', + 'size' => [ + 'numeric' => ':attribute må være :size.', + 'file' => ':attribute må være :size kilobytes.', + 'string' => ':attribute må være :size tegn.', + 'array' => ':attribute må inneholde :size ting.', + ], + 'string' => ':attribute må være en tekststreng.', + 'timezone' => ':attribute må være en tidssone.', + 'unique' => ':attribute har allerede blitt tatt.', + 'url' => ':attribute format er ugyldig.', + 'uploaded' => 'kunne ikke lastes opp, tjeneren støtter ikke filer av denne størrelsen.', + + // Custom validation lines + 'custom' => [ + 'password-confirm' => [ + 'required_with' => 'passordbekreftelse er påkrevd', + ], + ], + + // Custom validation attributes + 'attributes' => [], +]; From 461977cf9a9f40f91955f35b9fefac40015a939b Mon Sep 17 00:00:00 2001 From: Ole Aldric Date: Mon, 19 Oct 2020 12:26:18 +0200 Subject: [PATCH 08/72] added missing comma that caused the testprocess to fail. --- resources/lang/en/settings.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/lang/en/settings.php b/resources/lang/en/settings.php index 1537855b8..38be68e47 100755 --- a/resources/lang/en/settings.php +++ b/resources/lang/en/settings.php @@ -214,7 +214,7 @@ return [ 'ja' => '日本語', 'ko' => '한국어', 'nl' => 'Nederlands', - 'no_NB' => 'Norsk (Bokmål)' + 'no_NB' => 'Norsk (Bokmål)', 'pl' => 'Polski', 'pt_BR' => 'Português do Brasil', 'ru' => 'Русский', From 4c5566755f8147c71b5e77e3154c792001ff163c Mon Sep 17 00:00:00 2001 From: Ole Aldric Date: Mon, 19 Oct 2020 12:35:05 +0200 Subject: [PATCH 09/72] updated config to also include Norwegian --- app/Config/app.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Config/app.php b/app/Config/app.php index 8a1d17528..23c4bb0c7 100755 --- a/app/Config/app.php +++ b/app/Config/app.php @@ -52,7 +52,7 @@ return [ 'locale' => env('APP_LANG', 'en'), // Locales available - 'locales' => ['en', 'ar', 'bg', 'cs', 'da', 'de', 'de_informal', 'es', 'es_AR', 'fa', 'fr', 'he', 'hu', 'it', 'ja', 'ko', 'nl', 'pt', 'pt_BR', 'sk', 'sl', 'sv', 'pl', 'ru', 'th', 'tr', 'uk', 'vi', 'zh_CN', 'zh_TW',], + 'locales' => ['en', 'ar', 'bg', 'cs', 'da', 'de', 'de_informal', 'es', 'es_AR', 'fa', 'fr', 'he', 'hu', 'it', 'ja', 'ko', 'nl', 'no_NB', 'pt', 'pt_BR', 'sk', 'sl', 'sv', 'pl', 'ru', 'th', 'tr', 'uk', 'vi', 'zh_CN', 'zh_TW',], // Application Fallback Locale 'fallback_locale' => 'en', From 36daa094417fa35d47ef8c841c4df5bb531c11f0 Mon Sep 17 00:00:00 2001 From: Ole Aldric Date: Mon, 19 Oct 2020 12:43:41 +0200 Subject: [PATCH 10/72] Update Localization.php in Middleware with "no" tag for estimate. --- app/Http/Middleware/Localization.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/Http/Middleware/Localization.php b/app/Http/Middleware/Localization.php index c0ac7a7c4..8b44e4a2a 100644 --- a/app/Http/Middleware/Localization.php +++ b/app/Http/Middleware/Localization.php @@ -32,6 +32,7 @@ class Localization 'ja' => 'ja', 'ko' => 'ko_KR', 'nl' => 'nl_NL', + 'no' => 'no_NB', 'pl' => 'pl_PL', 'pt' => 'pl_PT', 'pt_BR' => 'pt_BR', From 82e671a06d2d18757a9ff0be83f11e0a7053b3d5 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 31 Oct 2020 23:05:48 +0000 Subject: [PATCH 11/72] Re-aligned init files with Laravel default Removed the custom init elements that we added in 2017 to custom load the helpers file and instead load via composer. Also removed laravel-microscope package due to not running due to helpers file. --- app/helpers.php | 23 ++++++----------------- artisan | 10 ++++++---- bootstrap/init.php | 25 ------------------------- composer.json | 6 ++++-- phpunit.xml | 2 +- public/index.php | 10 ++++++---- 6 files changed, 23 insertions(+), 53 deletions(-) delete mode 100644 bootstrap/init.php diff --git a/app/helpers.php b/app/helpers.php index 83017c37d..935d4d8da 100644 --- a/app/helpers.php +++ b/app/helpers.php @@ -7,9 +7,6 @@ use BookStack\Settings\SettingService; /** * Get the path to a versioned file. - * - * @param string $file - * @return string * @throws Exception */ function versioned_asset(string $file = ''): string @@ -33,7 +30,6 @@ function versioned_asset(string $file = ''): string /** * Helper method to get the current User. * Defaults to public 'Guest' user if not logged in. - * @return User */ function user(): User { @@ -57,9 +53,8 @@ function hasAppAccess(): bool } /** - * Check if the current user has a permission. - * If an ownable element is passed in the jointPermissions are checked against - * that particular item. + * Check if the current user has a permission. If an ownable element + * is passed in the jointPermissions are checked against that particular item. */ function userCan(string $permission, Ownable $ownable = null): bool { @@ -75,9 +70,6 @@ function userCan(string $permission, Ownable $ownable = null): bool /** * Check if the current user has the given permission * on any item in the system. - * @param string $permission - * @param string|null $entityClass - * @return bool */ function userCanOnAny(string $permission, string $entityClass = null): bool { @@ -87,27 +79,26 @@ function userCanOnAny(string $permission, string $entityClass = null): bool /** * Helper to access system settings. - * @param string $key - * @param $default * @return bool|string|SettingService */ function setting(string $key = null, $default = false) { $settingService = resolve(SettingService::class); + if (is_null($key)) { return $settingService; } + return $settingService->get($key, $default); } /** * Get a path to a theme resource. - * @param string $path - * @return string */ function theme_path(string $path = ''): string { $theme = config('view.theme'); + if (!$theme) { return ''; } @@ -121,9 +112,6 @@ function theme_path(string $path = ''): string * to the 'resources/assets/icons' folder. * * Returns an empty string if icon file not found. - * @param $name - * @param array $attrs - * @return mixed */ function icon(string $name, array $attrs = []): string { @@ -139,6 +127,7 @@ function icon(string $name, array $attrs = []): string $iconPath = resource_path('icons/' . $name . '.svg'); $themeIconPath = theme_path('icons/' . $name . '.svg'); + if ($themeIconPath && file_exists($themeIconPath)) { $iconPath = $themeIconPath; } else if (!file_exists($iconPath)) { diff --git a/artisan b/artisan index dad16dcde..d5c6aaf98 100755 --- a/artisan +++ b/artisan @@ -5,15 +5,17 @@ define('LARAVEL_START', microtime(true)); /* |-------------------------------------------------------------------------- -| Initialize The App +| Register The Auto Loader |-------------------------------------------------------------------------- | -| We need to get things going before we start up the app. -| The init file loads everything in, in the correct order. +| Composer provides a convenient, automatically generated class loader +| for our application. We just need to utilize it! We'll require it +| into the script here so that we do not have to worry about the +| loading of any our classes "manually". Feels great to relax. | */ -require __DIR__.'/bootstrap/init.php'; +require __DIR__.'/vendor/autoload.php'; $app = require_once __DIR__.'/bootstrap/app.php'; diff --git a/bootstrap/init.php b/bootstrap/init.php deleted file mode 100644 index 7d9e43f07..000000000 --- a/bootstrap/init.php +++ /dev/null @@ -1,25 +0,0 @@ - Date: Mon, 2 Nov 2020 22:47:48 +0000 Subject: [PATCH 12/72] Added per-item recycle-bin delete and restore --- app/Entities/Entity.php | 16 ++++ app/Entities/Managers/TrashCan.php | 83 ++++++++++++++++-- app/Entities/Page.php | 8 -- app/Entities/Repos/PageRepo.php | 7 +- app/Http/Controllers/PageController.php | 4 +- app/Http/Controllers/RecycleBinController.php | 87 ++++++++++++++++--- resources/lang/en/settings.php | 10 ++- resources/sass/_layout.scss | 9 +- .../partials/entity-display-item.blade.php | 7 ++ .../deletable-entity-list.blade.php | 11 +++ .../settings/recycle-bin/destroy.blade.php | 31 +++++++ .../index.blade.php} | 19 +++- .../settings/recycle-bin/restore.blade.php | 33 +++++++ routes/web.php | 4 + 14 files changed, 291 insertions(+), 38 deletions(-) create mode 100644 resources/views/partials/entity-display-item.blade.php create mode 100644 resources/views/settings/recycle-bin/deletable-entity-list.blade.php create mode 100644 resources/views/settings/recycle-bin/destroy.blade.php rename resources/views/settings/{recycle-bin.blade.php => recycle-bin/index.blade.php} (76%) create mode 100644 resources/views/settings/recycle-bin/restore.blade.php diff --git a/app/Entities/Entity.php b/app/Entities/Entity.php index 14328386c..ed3040929 100644 --- a/app/Entities/Entity.php +++ b/app/Entities/Entity.php @@ -287,6 +287,22 @@ class Entity extends Ownable return $path; } + /** + * Get the parent entity if existing. + * This is the "static" parent and does not include dynamic + * relations such as shelves to books. + */ + public function getParent(): ?Entity + { + if ($this->isA('page')) { + return $this->chapter_id ? $this->chapter()->withTrashed()->first() : $this->book->withTrashed()->first(); + } + if ($this->isA('chapter')) { + return $this->book->withTrashed()->first(); + } + return null; + } + /** * Rebuild the permissions for this entity. */ diff --git a/app/Entities/Managers/TrashCan.php b/app/Entities/Managers/TrashCan.php index aedf4d7af..f99c62801 100644 --- a/app/Entities/Managers/TrashCan.php +++ b/app/Entities/Managers/TrashCan.php @@ -180,24 +180,91 @@ class TrashCan /** * Destroy all items that have pending deletions. + * @throws Exception */ public function destroyFromAllDeletions(): int { $deletions = Deletion::all(); $deleteCount = 0; foreach ($deletions as $deletion) { - // For each one we load in the relation since it may have already - // been deleted as part of another deletion in this loop. - $entity = $deletion->deletable()->first(); - if ($entity) { - $count = $this->destroyEntity($deletion->deletable); - $deleteCount += $count; - } - $deletion->delete(); + $deleteCount += $this->destroyFromDeletion($deletion); } return $deleteCount; } + /** + * Destroy an element from the given deletion model. + * @throws Exception + */ + public function destroyFromDeletion(Deletion $deletion): int + { + // We directly load the deletable element here just to ensure it still + // exists in the event it has already been destroyed during this request. + $entity = $deletion->deletable()->first(); + $count = 0; + if ($entity) { + $count = $this->destroyEntity($deletion->deletable); + } + $deletion->delete(); + return $count; + } + + /** + * Restore the content within the given deletion. + * @throws Exception + */ + public function restoreFromDeletion(Deletion $deletion): int + { + $shouldRestore = true; + $restoreCount = 0; + $parent = $deletion->deletable->getParent(); + + if ($parent && $parent->trashed()) { + $shouldRestore = false; + } + + if ($shouldRestore) { + $restoreCount = $this->restoreEntity($deletion->deletable); + } + + $deletion->delete(); + return $restoreCount; + } + + /** + * Restore an entity so it is essentially un-deleted. + * Deletions on restored child elements will be removed during this restoration. + */ + protected function restoreEntity(Entity $entity): int + { + $count = 1; + $entity->restore(); + + if ($entity->isA('chapter') || $entity->isA('book')) { + foreach ($entity->pages()->withTrashed()->withCount('deletions')->get() as $page) { + if ($page->deletions_count > 0) { + $page->deletions()->delete(); + } + + $page->restore(); + $count++; + } + } + + if ($entity->isA('book')) { + foreach ($entity->chapters()->withTrashed()->withCount('deletions')->get() as $chapter) { + if ($chapter->deletions_count === 0) { + $chapter->deletions()->delete(); + } + + $chapter->restore(); + $count++; + } + } + + return $count; + } + /** * Destroy the given entity. */ diff --git a/app/Entities/Page.php b/app/Entities/Page.php index 32ba2981d..8ad05e7aa 100644 --- a/app/Entities/Page.php +++ b/app/Entities/Page.php @@ -49,14 +49,6 @@ class Page extends BookChild return $array; } - /** - * Get the parent item - */ - public function parent(): Entity - { - return $this->chapter_id ? $this->chapter : $this->book; - } - /** * Get the chapter that this page is in, If applicable. * @return BelongsTo diff --git a/app/Entities/Repos/PageRepo.php b/app/Entities/Repos/PageRepo.php index 87839192b..3b9b1f34c 100644 --- a/app/Entities/Repos/PageRepo.php +++ b/app/Entities/Repos/PageRepo.php @@ -321,7 +321,7 @@ class PageRepo */ public function copy(Page $page, string $parentIdentifier = null, string $newName = null): Page { - $parent = $parentIdentifier ? $this->findParentByIdentifier($parentIdentifier) : $page->parent(); + $parent = $parentIdentifier ? $this->findParentByIdentifier($parentIdentifier) : $page->getParent(); if ($parent === null) { throw new MoveOperationException('Book or chapter to move page into not found'); } @@ -440,8 +440,9 @@ class PageRepo */ protected function getNewPriority(Page $page): int { - if ($page->parent() instanceof Chapter) { - $lastPage = $page->parent()->pages('desc')->first(); + $parent = $page->getParent(); + if ($parent instanceof Chapter) { + $lastPage = $parent->pages('desc')->first(); return $lastPage ? $lastPage->priority + 1 : 0; } diff --git a/app/Http/Controllers/PageController.php b/app/Http/Controllers/PageController.php index 57d70fb32..ee998996f 100644 --- a/app/Http/Controllers/PageController.php +++ b/app/Http/Controllers/PageController.php @@ -78,7 +78,7 @@ class PageController extends Controller public function editDraft(string $bookSlug, int $pageId) { $draft = $this->pageRepo->getById($pageId); - $this->checkOwnablePermission('page-create', $draft->parent()); + $this->checkOwnablePermission('page-create', $draft->getParent()); $this->setPageTitle(trans('entities.pages_edit_draft')); $draftsEnabled = $this->isSignedIn(); @@ -104,7 +104,7 @@ class PageController extends Controller 'name' => 'required|string|max:255' ]); $draftPage = $this->pageRepo->getById($pageId); - $this->checkOwnablePermission('page-create', $draftPage->parent()); + $this->checkOwnablePermission('page-create', $draftPage->getParent()); $page = $this->pageRepo->publishDraft($draftPage, $request->all()); Activity::add($page, 'page_create', $draftPage->book->id); diff --git a/app/Http/Controllers/RecycleBinController.php b/app/Http/Controllers/RecycleBinController.php index 3cbc99df3..64459da23 100644 --- a/app/Http/Controllers/RecycleBinController.php +++ b/app/Http/Controllers/RecycleBinController.php @@ -2,36 +2,103 @@ use BookStack\Entities\Deletion; use BookStack\Entities\Managers\TrashCan; -use Illuminate\Http\Request; class RecycleBinController extends Controller { + + protected $recycleBinBaseUrl = '/settings/recycle-bin'; + + /** + * On each request to a method of this controller check permissions + * using a middleware closure. + */ + public function __construct() + { + // TODO - Check this is enforced. + $this->middleware(function ($request, $next) { + $this->checkPermission('settings-manage'); + $this->checkPermission('restrictions-manage-all'); + return $next($request); + }); + parent::__construct(); + } + + /** * Show the top-level listing for the recycle bin. */ public function index() { - $this->checkPermission('settings-manage'); - $this->checkPermission('restrictions-manage-all'); - $deletions = Deletion::query()->with(['deletable', 'deleter'])->paginate(10); - return view('settings.recycle-bin', [ + return view('settings.recycle-bin.index', [ 'deletions' => $deletions, ]); } + /** + * Show the page to confirm a restore of the deletion of the given id. + */ + public function showRestore(string $id) + { + /** @var Deletion $deletion */ + $deletion = Deletion::query()->findOrFail($id); + + return view('settings.recycle-bin.restore', [ + 'deletion' => $deletion, + ]); + } + + /** + * Restore the element attached to the given deletion. + * @throws \Exception + */ + public function restore(string $id) + { + /** @var Deletion $deletion */ + $deletion = Deletion::query()->findOrFail($id); + $restoreCount = (new TrashCan())->restoreFromDeletion($deletion); + + $this->showSuccessNotification(trans('settings.recycle_bin_restore_notification', ['count' => $restoreCount])); + return redirect($this->recycleBinBaseUrl); + } + + /** + * Show the page to confirm a Permanent deletion of the element attached to the deletion of the given id. + */ + public function showDestroy(string $id) + { + /** @var Deletion $deletion */ + $deletion = Deletion::query()->findOrFail($id); + + return view('settings.recycle-bin.destroy', [ + 'deletion' => $deletion, + ]); + } + + /** + * Permanently delete the content associated with the given deletion. + * @throws \Exception + */ + public function destroy(string $id) + { + /** @var Deletion $deletion */ + $deletion = Deletion::query()->findOrFail($id); + $deleteCount = (new TrashCan())->destroyFromDeletion($deletion); + + $this->showSuccessNotification(trans('settings.recycle_bin_destroy_notification', ['count' => $deleteCount])); + return redirect($this->recycleBinBaseUrl); + } + /** * Empty out the recycle bin. + * @throws \Exception */ public function empty() { - $this->checkPermission('settings-manage'); - $this->checkPermission('restrictions-manage-all'); - $deleteCount = (new TrashCan())->destroyFromAllDeletions(); - $this->showSuccessNotification(trans('settings.recycle_bin_empty_notification', ['count' => $deleteCount])); - return redirect('/settings/recycle-bin'); + $this->showSuccessNotification(trans('settings.recycle_bin_destroy_notification', ['count' => $deleteCount])); + return redirect($this->recycleBinBaseUrl); } } diff --git a/resources/lang/en/settings.php b/resources/lang/en/settings.php index 6de6c2f1a..b9d91e18c 100755 --- a/resources/lang/en/settings.php +++ b/resources/lang/en/settings.php @@ -89,10 +89,18 @@ return [ 'recycle_bin_deleted_item' => 'Deleted Item', 'recycle_bin_deleted_by' => 'Deleted By', 'recycle_bin_deleted_at' => 'Deletion Time', + 'recycle_bin_permanently_delete' => 'Permanently Delete', + 'recycle_bin_restore' => 'Restore', 'recycle_bin_contents_empty' => 'The recycle bin is currently empty', 'recycle_bin_empty' => 'Empty Recycle Bin', 'recycle_bin_empty_confirm' => 'This will permanently destroy all items in the recycle bin including content contained within each item. Are you sure you want to empty the recycle bin?', - 'recycle_bin_empty_notification' => 'Deleted :count total items from the recycle bin.', + 'recycle_bin_destroy_confirm' => 'This action will permanently delete this item, along with any child elements listed below, from the system and you will not be able to restore this content. Are you sure you want to permanently delete this item?', + 'recycle_bin_destroy_list' => 'Items to be Destroyed', + 'recycle_bin_restore_list' => 'Items to be Restored', + 'recycle_bin_restore_confirm' => 'This action will restore the deleted item, including any child elements, to their original location. If the original location has since been deleted, and is now in the recycle bin, the parent item will also need to be restored.', + 'recycle_bin_restore_deleted_parent' => 'The parent of this item has also been deleted. These will remain deleted until that parent is also restored.', + 'recycle_bin_destroy_notification' => 'Deleted :count total items from the recycle bin.', + 'recycle_bin_restore_notification' => 'Restored :count total items from the recycle bin.', // Audit Log 'audit' => 'Audit Log', diff --git a/resources/sass/_layout.scss b/resources/sass/_layout.scss index 519cb27ad..c4e412f0e 100644 --- a/resources/sass/_layout.scss +++ b/resources/sass/_layout.scss @@ -150,22 +150,25 @@ body.flexbox { .justify-flex-end { justify-content: flex-end; } +.justify-center { + justify-content: center; +} /** * Display and float utilities */ .block { - display: block; + display: block !important; position: relative; } .inline { - display: inline; + display: inline !important; } .block.inline { - display: inline-block; + display: inline-block !important; } .hidden { diff --git a/resources/views/partials/entity-display-item.blade.php b/resources/views/partials/entity-display-item.blade.php new file mode 100644 index 000000000..d6633edbe --- /dev/null +++ b/resources/views/partials/entity-display-item.blade.php @@ -0,0 +1,7 @@ +getType(); ?> +
+ @icon($type) +
+
{{ $entity->name }}
+
+
\ No newline at end of file diff --git a/resources/views/settings/recycle-bin/deletable-entity-list.blade.php b/resources/views/settings/recycle-bin/deletable-entity-list.blade.php new file mode 100644 index 000000000..07ad94f8e --- /dev/null +++ b/resources/views/settings/recycle-bin/deletable-entity-list.blade.php @@ -0,0 +1,11 @@ +@include('partials.entity-display-item', ['entity' => $entity]) +@if($entity->isA('book')) + @foreach($entity->chapters()->withTrashed()->get() as $chapter) + @include('partials.entity-display-item', ['entity' => $chapter]) + @endforeach +@endif +@if($entity->isA('book') || $entity->isA('chapter')) + @foreach($entity->pages()->withTrashed()->get() as $page) + @include('partials.entity-display-item', ['entity' => $page]) + @endforeach +@endif \ No newline at end of file diff --git a/resources/views/settings/recycle-bin/destroy.blade.php b/resources/views/settings/recycle-bin/destroy.blade.php new file mode 100644 index 000000000..2cc11dabf --- /dev/null +++ b/resources/views/settings/recycle-bin/destroy.blade.php @@ -0,0 +1,31 @@ +@extends('simple-layout') + +@section('body') +
+ +
+
+ @include('settings.navbar', ['selected' => 'maintenance']) +
+
+ +
+

{{ trans('settings.recycle_bin_permanently_delete') }}

+

{{ trans('settings.recycle_bin_destroy_confirm') }}

+
+ {!! method_field('DELETE') !!} + {!! csrf_field() !!} + {{ trans('common.cancel') }} + +
+ + @if($deletion->deletable instanceof \BookStack\Entities\Entity) +
+
{{ trans('settings.recycle_bin_destroy_list') }}
+ @include('settings.recycle-bin.deletable-entity-list', ['entity' => $deletion->deletable]) + @endif + +
+ +
+@stop diff --git a/resources/views/settings/recycle-bin.blade.php b/resources/views/settings/recycle-bin/index.blade.php similarity index 76% rename from resources/views/settings/recycle-bin.blade.php rename to resources/views/settings/recycle-bin/index.blade.php index 145eb5d3c..6a61ff9fa 100644 --- a/resources/views/settings/recycle-bin.blade.php +++ b/resources/views/settings/recycle-bin/index.blade.php @@ -44,10 +44,11 @@ {{ trans('settings.recycle_bin_deleted_item') }} {{ trans('settings.recycle_bin_deleted_by') }} {{ trans('settings.recycle_bin_deleted_at') }} + @if(count($deletions) === 0) - +

{{ trans('settings.recycle_bin_contents_empty') }}

@@ -55,12 +56,15 @@ @foreach($deletions as $deletion) -
+
@icon($deletion->deletable->getType())
{{ $deletion->deletable->name }}
+ @if($deletion->deletable instanceof \BookStack\Entities\Book || $deletion->deletable instanceof \BookStack\Entities\Chapter) +
+ @endif @if($deletion->deletable instanceof \BookStack\Entities\Book)
@@ -77,7 +81,16 @@ @endif @include('partials.table-user', ['user' => $deletion->deleter, 'user_id' => $deletion->deleted_by]) - {{ $deletion->created_at }} + {{ $deletion->created_at }} + + + @endforeach diff --git a/resources/views/settings/recycle-bin/restore.blade.php b/resources/views/settings/recycle-bin/restore.blade.php new file mode 100644 index 000000000..79ccf1b7d --- /dev/null +++ b/resources/views/settings/recycle-bin/restore.blade.php @@ -0,0 +1,33 @@ +@extends('simple-layout') + +@section('body') +
+ +
+
+ @include('settings.navbar', ['selected' => 'maintenance']) +
+
+ +
+

{{ trans('settings.recycle_bin_restore') }}

+

{{ trans('settings.recycle_bin_restore_confirm') }}

+
+ {!! csrf_field() !!} + {{ trans('common.cancel') }} + +
+ + @if($deletion->deletable instanceof \BookStack\Entities\Entity) +
+
{{ trans('settings.recycle_bin_restore_list') }}
+ @if($deletion->deletable->getParent() && $deletion->deletable->getParent()->trashed()) +

{{ trans('settings.recycle_bin_restore_deleted_parent') }}

+ @endif + @include('settings.recycle-bin.deletable-entity-list', ['entity' => $deletion->deletable]) + @endif + +
+ +
+@stop diff --git a/routes/web.php b/routes/web.php index 20f6639a5..b87355105 100644 --- a/routes/web.php +++ b/routes/web.php @@ -169,6 +169,10 @@ Route::group(['middleware' => 'auth'], function () { // 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'); // Audit Log Route::get('/audit', 'AuditLogController@index'); From 3e70c661a183a510d1e999e38723489650a6b96f Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Mon, 2 Nov 2020 22:54:00 +0000 Subject: [PATCH 13/72] Cleaned up duplicate code in recycle-bin restore --- app/Entities/Managers/TrashCan.php | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/app/Entities/Managers/TrashCan.php b/app/Entities/Managers/TrashCan.php index f99c62801..c567edaf3 100644 --- a/app/Entities/Managers/TrashCan.php +++ b/app/Entities/Managers/TrashCan.php @@ -240,26 +240,21 @@ class TrashCan $count = 1; $entity->restore(); - if ($entity->isA('chapter') || $entity->isA('book')) { - foreach ($entity->pages()->withTrashed()->withCount('deletions')->get() as $page) { - if ($page->deletions_count > 0) { - $page->deletions()->delete(); - } - - $page->restore(); - $count++; + $restoreAction = function ($entity) use (&$count) { + if ($entity->deletions_count > 0) { + $entity->deletions()->delete(); } + + $entity->restore(); + $count++; + }; + + if ($entity->isA('chapter') || $entity->isA('book')) { + $entity->pages()->withTrashed()->withCount('deletions')->get()->each($restoreAction); } if ($entity->isA('book')) { - foreach ($entity->chapters()->withTrashed()->withCount('deletions')->get() as $chapter) { - if ($chapter->deletions_count === 0) { - $chapter->deletions()->delete(); - } - - $chapter->restore(); - $count++; - } + $entity->chapters()->withTrashed()->withCount('deletions')->get()->each($restoreAction); } return $count; From 34dc4a1b6df2baae28120103272d202c3031ed1b Mon Sep 17 00:00:00 2001 From: Anthony Ronda Date: Tue, 3 Nov 2020 20:46:47 -0500 Subject: [PATCH 14/72] Automatic Restored Revision Changelog Summary Text --- app/Entities/Repos/PageRepo.php | 5 +++-- resources/lang/en/entities.php | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/Entities/Repos/PageRepo.php b/app/Entities/Repos/PageRepo.php index e5f13463c..1467feff5 100644 --- a/app/Entities/Repos/PageRepo.php +++ b/app/Entities/Repos/PageRepo.php @@ -273,9 +273,10 @@ class PageRepo public function restoreRevision(Page $page, int $revisionId): Page { $page->revision_count++; - $this->savePageRevision($page); - $revision = $page->revisions()->where('id', '=', $revisionId)->first(); + $summary = trans('entities.pages_revision_restored_from', ['id' => strval($revisionId), 'summary' => $revision->summary]); + $this->savePageRevision($page, $summary); + $page->fill($revision->toArray()); $content = new PageContent($page); $content->setNewHTML($revision->html); diff --git a/resources/lang/en/entities.php b/resources/lang/en/entities.php index f64867a56..6de8328af 100644 --- a/resources/lang/en/entities.php +++ b/resources/lang/en/entities.php @@ -208,6 +208,7 @@ return [ 'pages_revisions' => 'Page Revisions', 'pages_revisions_named' => 'Page Revisions for :pageName', 'pages_revision_named' => 'Page Revision for :pageName', + 'pages_revision_restored_from' => 'Restored from #:id ":summary"', 'pages_revisions_created_by' => 'Created By', 'pages_revisions_date' => 'Revision Date', 'pages_revisions_number' => '#', From 483cb41665c9d5994b47c762670d5fd98188cf14 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Fri, 6 Nov 2020 12:54:39 +0000 Subject: [PATCH 15/72] Started testing work for recycle bin implementation --- app/Entities/Entity.php | 2 +- app/Entities/Managers/TrashCan.php | 10 +-- app/Http/Controllers/AuditLogController.php | 7 +- app/Http/Controllers/BookController.php | 3 +- app/Http/Controllers/BookshelfController.php | 2 +- app/Http/Controllers/ChapterController.php | 2 +- app/Http/Controllers/PageController.php | 3 +- app/Http/Controllers/RecycleBinController.php | 3 +- tests/AuditLogTest.php | 4 +- tests/Entity/BookShelfTest.php | 27 +++++--- tests/Entity/BookTest.php | 34 ++++++++++ tests/Entity/ChapterTest.php | 31 +++++++++ tests/Entity/EntityTest.php | 52 +------------- tests/Entity/PageTest.php | 27 ++++++++ tests/RecycleBinTest.php | 68 +++++++++++++++++++ tests/SharedTestHelpers.php | 27 ++++++-- tests/TestResponse.php | 21 +++--- tests/Uploads/AttachmentTest.php | 5 +- 18 files changed, 235 insertions(+), 93 deletions(-) create mode 100644 tests/Entity/BookTest.php create mode 100644 tests/Entity/ChapterTest.php create mode 100644 tests/Entity/PageTest.php create mode 100644 tests/RecycleBinTest.php diff --git a/app/Entities/Entity.php b/app/Entities/Entity.php index ed3040929..34cdb4b8c 100644 --- a/app/Entities/Entity.php +++ b/app/Entities/Entity.php @@ -295,7 +295,7 @@ class Entity extends Ownable public function getParent(): ?Entity { if ($this->isA('page')) { - return $this->chapter_id ? $this->chapter()->withTrashed()->first() : $this->book->withTrashed()->first(); + return $this->chapter_id ? $this->chapter()->withTrashed()->first() : $this->book()->withTrashed()->first(); } if ($this->isA('chapter')) { return $this->book->withTrashed()->first(); diff --git a/app/Entities/Managers/TrashCan.php b/app/Entities/Managers/TrashCan.php index c567edaf3..686918ce2 100644 --- a/app/Entities/Managers/TrashCan.php +++ b/app/Entities/Managers/TrashCan.php @@ -90,7 +90,7 @@ class TrashCan * Remove a bookshelf from the system. * @throws Exception */ - public function destroyShelf(Bookshelf $shelf): int + protected function destroyShelf(Bookshelf $shelf): int { $this->destroyCommonRelations($shelf); $shelf->forceDelete(); @@ -102,7 +102,7 @@ class TrashCan * Destroys any child chapters and pages. * @throws Exception */ - public function destroyBook(Book $book): int + protected function destroyBook(Book $book): int { $count = 0; $pages = $book->pages()->withTrashed()->get(); @@ -127,7 +127,7 @@ class TrashCan * Destroys all pages within. * @throws Exception */ - public function destroyChapter(Chapter $chapter): int + protected function destroyChapter(Chapter $chapter): int { $count = 0; $pages = $chapter->pages()->withTrashed()->get(); @@ -147,7 +147,7 @@ class TrashCan * Remove a page from the system. * @throws Exception */ - public function destroyPage(Page $page): int + protected function destroyPage(Page $page): int { $this->destroyCommonRelations($page); @@ -182,7 +182,7 @@ class TrashCan * Destroy all items that have pending deletions. * @throws Exception */ - public function destroyFromAllDeletions(): int + public function empty(): int { $deletions = Deletion::all(); $deleteCount = 0; diff --git a/app/Http/Controllers/AuditLogController.php b/app/Http/Controllers/AuditLogController.php index a3ef01baa..fad4e8d38 100644 --- a/app/Http/Controllers/AuditLogController.php +++ b/app/Http/Controllers/AuditLogController.php @@ -23,7 +23,12 @@ class AuditLogController extends Controller ]; $query = Activity::query() - ->with(['entity', 'user']) + ->with([ + 'entity' => function ($query) { + $query->withTrashed(); + }, + 'user' + ]) ->orderBy($listDetails['sort'], $listDetails['order']); if ($listDetails['event']) { diff --git a/app/Http/Controllers/BookController.php b/app/Http/Controllers/BookController.php index 1643c62f9..25dc65194 100644 --- a/app/Http/Controllers/BookController.php +++ b/app/Http/Controllers/BookController.php @@ -181,14 +181,13 @@ class BookController extends Controller /** * Remove the specified book from the system. * @throws Throwable - * @throws NotifyException */ public function destroy(string $bookSlug) { $book = $this->bookRepo->getBySlug($bookSlug); $this->checkOwnablePermission('book-delete', $book); - Activity::addMessage('book_delete', $book->name); + Activity::add($book, 'book_delete', $book->id); $this->bookRepo->destroy($book); return redirect('/books'); diff --git a/app/Http/Controllers/BookshelfController.php b/app/Http/Controllers/BookshelfController.php index f2cc11c7b..efe280235 100644 --- a/app/Http/Controllers/BookshelfController.php +++ b/app/Http/Controllers/BookshelfController.php @@ -182,7 +182,7 @@ class BookshelfController extends Controller $shelf = $this->bookshelfRepo->getBySlug($slug); $this->checkOwnablePermission('bookshelf-delete', $shelf); - Activity::addMessage('bookshelf_delete', $shelf->name); + Activity::add($shelf, 'bookshelf_delete'); $this->bookshelfRepo->destroy($shelf); return redirect('/shelves'); diff --git a/app/Http/Controllers/ChapterController.php b/app/Http/Controllers/ChapterController.php index 135597910..5d8631154 100644 --- a/app/Http/Controllers/ChapterController.php +++ b/app/Http/Controllers/ChapterController.php @@ -128,7 +128,7 @@ class ChapterController extends Controller $chapter = $this->chapterRepo->getBySlug($bookSlug, $chapterSlug); $this->checkOwnablePermission('chapter-delete', $chapter); - Activity::addMessage('chapter_delete', $chapter->name, $chapter->book->id); + Activity::add($chapter, 'chapter_delete', $chapter->book->id); $this->chapterRepo->destroy($chapter); return redirect($chapter->book->getUrl()); diff --git a/app/Http/Controllers/PageController.php b/app/Http/Controllers/PageController.php index ee998996f..6396da23e 100644 --- a/app/Http/Controllers/PageController.php +++ b/app/Http/Controllers/PageController.php @@ -308,9 +308,8 @@ class PageController extends Controller $book = $page->book; $parent = $page->chapter ?? $book; $this->pageRepo->destroy($page); - Activity::addMessage('page_delete', $page->name, $book->id); + Activity::add($page, 'page_delete', $page->book_id); - $this->showSuccessNotification(trans('entities.pages_delete_success')); return redirect($parent->getUrl()); } diff --git a/app/Http/Controllers/RecycleBinController.php b/app/Http/Controllers/RecycleBinController.php index 64459da23..459dbb39d 100644 --- a/app/Http/Controllers/RecycleBinController.php +++ b/app/Http/Controllers/RecycleBinController.php @@ -14,7 +14,6 @@ class RecycleBinController extends Controller */ public function __construct() { - // TODO - Check this is enforced. $this->middleware(function ($request, $next) { $this->checkPermission('settings-manage'); $this->checkPermission('restrictions-manage-all'); @@ -96,7 +95,7 @@ class RecycleBinController extends Controller */ public function empty() { - $deleteCount = (new TrashCan())->destroyFromAllDeletions(); + $deleteCount = (new TrashCan())->empty(); $this->showSuccessNotification(trans('settings.recycle_bin_destroy_notification', ['count' => $deleteCount])); return redirect($this->recycleBinBaseUrl); diff --git a/tests/AuditLogTest.php b/tests/AuditLogTest.php index a2cdc33ff..94eb02599 100644 --- a/tests/AuditLogTest.php +++ b/tests/AuditLogTest.php @@ -3,6 +3,7 @@ use BookStack\Actions\Activity; use BookStack\Actions\ActivityService; use BookStack\Auth\UserRepo; +use BookStack\Entities\Managers\TrashCan; use BookStack\Entities\Page; use BookStack\Entities\Repos\PageRepo; use Carbon\Carbon; @@ -40,7 +41,7 @@ class AuditLogTest extends TestCase $resp->assertSeeText($page->name); $resp->assertSeeText('page_create'); $resp->assertSeeText($activity->created_at->toDateTimeString()); - $resp->assertElementContains('.audit-log-user', $admin->name); + $resp->assertElementContains('.table-user-item', $admin->name); } public function test_shows_name_for_deleted_items() @@ -51,6 +52,7 @@ class AuditLogTest extends TestCase app(ActivityService::class)->add($page, 'page_create', $page->book->id); app(PageRepo::class)->destroy($page); + app(TrashCan::class)->empty(); $resp = $this->get('settings/audit'); $resp->assertSeeText('Deleted Item'); diff --git a/tests/Entity/BookShelfTest.php b/tests/Entity/BookShelfTest.php index cb3acfb1e..c1748281e 100644 --- a/tests/Entity/BookShelfTest.php +++ b/tests/Entity/BookShelfTest.php @@ -222,16 +222,25 @@ class BookShelfTest extends TestCase public function test_shelf_delete() { - $shelf = Bookshelf::first(); - $resp = $this->asEditor()->get($shelf->getUrl('/delete')); - $resp->assertSeeText('Delete Bookshelf'); - $resp->assertSee("action=\"{$shelf->getUrl()}\""); + $shelf = Bookshelf::query()->whereHas('books')->first(); + $this->assertNull($shelf->deleted_at); + $bookCount = $shelf->books()->count(); - $resp = $this->delete($shelf->getUrl()); - $resp->assertRedirect('/shelves'); - $this->assertDatabaseMissing('bookshelves', ['id' => $shelf->id]); - $this->assertDatabaseMissing('bookshelves_books', ['bookshelf_id' => $shelf->id]); - $this->assertSessionHas('success'); + $deleteViewReq = $this->asEditor()->get($shelf->getUrl('/delete')); + $deleteViewReq->assertSeeText('Are you sure you want to delete this bookshelf?'); + + $deleteReq = $this->delete($shelf->getUrl()); + $deleteReq->assertRedirect(url('/shelves')); + $this->assertActivityExists('bookshelf_delete', $shelf); + + $shelf->refresh(); + $this->assertNotNull($shelf->deleted_at); + + $this->assertTrue($shelf->books()->count() === $bookCount); + $this->assertTrue($shelf->deletions()->count() === 1); + + $redirectReq = $this->get($deleteReq->baseResponse->headers->get('location')); + $redirectReq->assertNotificationContains('Bookshelf Successfully Deleted'); } public function test_shelf_copy_permissions() diff --git a/tests/Entity/BookTest.php b/tests/Entity/BookTest.php new file mode 100644 index 000000000..b502bdcc5 --- /dev/null +++ b/tests/Entity/BookTest.php @@ -0,0 +1,34 @@ +whereHas('pages')->whereHas('chapters')->first(); + $this->assertNull($book->deleted_at); + $pageCount = $book->pages()->count(); + $chapterCount = $book->chapters()->count(); + + $deleteViewReq = $this->asEditor()->get($book->getUrl('/delete')); + $deleteViewReq->assertSeeText('Are you sure you want to delete this book?'); + + $deleteReq = $this->delete($book->getUrl()); + $deleteReq->assertRedirect(url('/books')); + $this->assertActivityExists('book_delete', $book); + + $book->refresh(); + $this->assertNotNull($book->deleted_at); + + $this->assertTrue($book->pages()->count() === 0); + $this->assertTrue($book->chapters()->count() === 0); + $this->assertTrue($book->pages()->withTrashed()->count() === $pageCount); + $this->assertTrue($book->chapters()->withTrashed()->count() === $chapterCount); + $this->assertTrue($book->deletions()->count() === 1); + + $redirectReq = $this->get($deleteReq->baseResponse->headers->get('location')); + $redirectReq->assertNotificationContains('Book Successfully Deleted'); + } +} \ No newline at end of file diff --git a/tests/Entity/ChapterTest.php b/tests/Entity/ChapterTest.php new file mode 100644 index 000000000..d072f8d8b --- /dev/null +++ b/tests/Entity/ChapterTest.php @@ -0,0 +1,31 @@ +whereHas('pages')->first(); + $this->assertNull($chapter->deleted_at); + $pageCount = $chapter->pages()->count(); + + $deleteViewReq = $this->asEditor()->get($chapter->getUrl('/delete')); + $deleteViewReq->assertSeeText('Are you sure you want to delete this chapter?'); + + $deleteReq = $this->delete($chapter->getUrl()); + $deleteReq->assertRedirect($chapter->getParent()->getUrl()); + $this->assertActivityExists('chapter_delete', $chapter); + + $chapter->refresh(); + $this->assertNotNull($chapter->deleted_at); + + $this->assertTrue($chapter->pages()->count() === 0); + $this->assertTrue($chapter->pages()->withTrashed()->count() === $pageCount); + $this->assertTrue($chapter->deletions()->count() === 1); + + $redirectReq = $this->get($deleteReq->baseResponse->headers->get('location')); + $redirectReq->assertNotificationContains('Chapter Successfully Deleted'); + } +} \ No newline at end of file diff --git a/tests/Entity/EntityTest.php b/tests/Entity/EntityTest.php index de1e025ad..4aad6622f 100644 --- a/tests/Entity/EntityTest.php +++ b/tests/Entity/EntityTest.php @@ -7,7 +7,6 @@ use BookStack\Entities\Page; use BookStack\Auth\UserRepo; use BookStack\Entities\Repos\PageRepo; use Carbon\Carbon; -use Illuminate\Support\Facades\DB; use Tests\BrowserKitTest; class EntityTest extends BrowserKitTest @@ -18,27 +17,10 @@ class EntityTest extends BrowserKitTest // Test Creation $book = $this->bookCreation(); $chapter = $this->chapterCreation($book); - $page = $this->pageCreation($chapter); + $this->pageCreation($chapter); // Test Updating - $book = $this->bookUpdate($book); - - // Test Deletion - $this->bookDelete($book); - } - - public function bookDelete(Book $book) - { - $this->asAdmin() - ->visit($book->getUrl()) - // Check link works correctly - ->click('Delete') - ->seePageIs($book->getUrl() . '/delete') - // Ensure the book name is show to user - ->see($book->name) - ->press('Confirm') - ->seePageIs('/books') - ->notSeeInDatabase('books', ['id' => $book->id]); + $this->bookUpdate($book); } public function bookUpdate(Book $book) @@ -332,34 +314,4 @@ class EntityTest extends BrowserKitTest ->seePageIs($chapter->getUrl()); } - public function test_page_delete_removes_entity_from_its_activity() - { - $page = Page::query()->first(); - - $this->asEditor()->put($page->getUrl(), [ - 'name' => 'My updated page', - 'html' => '

updated content

', - ]); - $page->refresh(); - - $this->seeInDatabase('activities', [ - 'entity_id' => $page->id, - 'entity_type' => $page->getMorphClass(), - ]); - - $resp = $this->delete($page->getUrl()); - $resp->assertResponseStatus(302); - - $this->dontSeeInDatabase('activities', [ - 'entity_id' => $page->id, - 'entity_type' => $page->getMorphClass(), - ]); - - $this->seeInDatabase('activities', [ - 'extra' => 'My updated page', - 'entity_id' => 0, - 'entity_type' => '', - ]); - } - } diff --git a/tests/Entity/PageTest.php b/tests/Entity/PageTest.php new file mode 100644 index 000000000..742fd1151 --- /dev/null +++ b/tests/Entity/PageTest.php @@ -0,0 +1,27 @@ +first(); + $this->assertNull($page->deleted_at); + + $deleteViewReq = $this->asEditor()->get($page->getUrl('/delete')); + $deleteViewReq->assertSeeText('Are you sure you want to delete this page?'); + + $deleteReq = $this->delete($page->getUrl()); + $deleteReq->assertRedirect($page->getParent()->getUrl()); + $this->assertActivityExists('page_delete', $page); + + $page->refresh(); + $this->assertNotNull($page->deleted_at); + $this->assertTrue($page->deletions()->count() === 1); + + $redirectReq = $this->get($deleteReq->baseResponse->headers->get('location')); + $redirectReq->assertNotificationContains('Page Successfully Deleted'); + } +} \ No newline at end of file diff --git a/tests/RecycleBinTest.php b/tests/RecycleBinTest.php new file mode 100644 index 000000000..086f63679 --- /dev/null +++ b/tests/RecycleBinTest.php @@ -0,0 +1,68 @@ +first(); + $editor = $this->getEditor(); + $this->actingAs($editor)->delete($page->getUrl()); + $deletion = Deletion::query()->firstOrFail(); + + $routes = [ + 'GET:/settings/recycle-bin', + 'POST:/settings/recycle-bin/empty', + "GET:/settings/recycle-bin/{$deletion->id}/destroy", + "GET:/settings/recycle-bin/{$deletion->id}/restore", + "POST:/settings/recycle-bin/{$deletion->id}/restore", + "DELETE:/settings/recycle-bin/{$deletion->id}", + ]; + + foreach($routes as $route) { + [$method, $url] = explode(':', $route); + $resp = $this->call($method, $url); + $this->assertPermissionError($resp); + } + + $this->giveUserPermissions($editor, ['restrictions-manage-all']); + + foreach($routes as $route) { + [$method, $url] = explode(':', $route); + $resp = $this->call($method, $url); + $this->assertPermissionError($resp); + } + + $this->giveUserPermissions($editor, ['settings-manage']); + + foreach($routes as $route) { + \DB::beginTransaction(); + [$method, $url] = explode(':', $route); + $resp = $this->call($method, $url); + $this->assertNotPermissionError($resp); + \DB::rollBack(); + } + + } + + public function test_recycle_bin_view() + { + $page = Page::query()->first(); + $book = Book::query()->whereHas('pages')->whereHas('chapters')->withCount(['pages', 'chapters'])->first(); + $editor = $this->getEditor(); + $this->actingAs($editor)->delete($page->getUrl()); + $this->actingAs($editor)->delete($book->getUrl()); + + $viewReq = $this->asAdmin()->get('/settings/recycle-bin'); + $viewReq->assertElementContains('table.table', $page->name); + $viewReq->assertElementContains('table.table', $editor->name); + $viewReq->assertElementContains('table.table', $book->name); + $viewReq->assertElementContains('table.table', $book->pages_count . ' Pages'); + $viewReq->assertElementContains('table.table', $book->chapters_count . ' Chapters'); + } +} \ No newline at end of file diff --git a/tests/SharedTestHelpers.php b/tests/SharedTestHelpers.php index c7659a02d..1ba474d76 100644 --- a/tests/SharedTestHelpers.php +++ b/tests/SharedTestHelpers.php @@ -15,12 +15,14 @@ use BookStack\Auth\Permissions\PermissionService; use BookStack\Entities\Repos\PageRepo; use BookStack\Settings\SettingService; use BookStack\Uploads\HttpFetcher; +use Illuminate\Http\Response; use Illuminate\Support\Env; use Illuminate\Support\Facades\Log; use Mockery; use Monolog\Handler\TestHandler; use Monolog\Logger; use Throwable; +use Illuminate\Foundation\Testing\Assert as PHPUnit; trait SharedTestHelpers { @@ -270,14 +272,25 @@ trait SharedTestHelpers */ protected function assertPermissionError($response) { - if ($response instanceof BrowserKitTest) { - $response = \Illuminate\Foundation\Testing\TestResponse::fromBaseResponse($response->response); - } + PHPUnit::assertTrue($this->isPermissionError($response->baseResponse ?? $response->response), "Failed asserting the response contains a permission error."); + } - $response->assertRedirect('/'); - $this->assertSessionHas('error'); - $error = session()->pull('error'); - $this->assertStringStartsWith('You do not have permission to access', $error); + /** + * Assert a permission error has occurred. + */ + protected function assertNotPermissionError($response) + { + PHPUnit::assertFalse($this->isPermissionError($response->baseResponse ?? $response->response), "Failed asserting the response does not contain a permission error."); + } + + /** + * Check if the given response is a permission error. + */ + private function isPermissionError($response): bool + { + return $response->status() === 302 + && $response->headers->get('Location') === url('/') + && strpos(session()->pull('error', ''), 'You do not have permission to access') === 0; } /** diff --git a/tests/TestResponse.php b/tests/TestResponse.php index a68a5783f..9c6b78782 100644 --- a/tests/TestResponse.php +++ b/tests/TestResponse.php @@ -15,9 +15,8 @@ class TestResponse extends BaseTestResponse { /** * Get the DOM Crawler for the response content. - * @return Crawler */ - protected function crawler() + protected function crawler(): Crawler { if (!is_object($this->crawlerInstance)) { $this->crawlerInstance = new Crawler($this->getContent()); @@ -27,7 +26,6 @@ class TestResponse extends BaseTestResponse { /** * Assert the response contains the specified element. - * @param string $selector * @return $this */ public function assertElementExists(string $selector) @@ -45,7 +43,6 @@ class TestResponse extends BaseTestResponse { /** * Assert the response does not contain the specified element. - * @param string $selector * @return $this */ public function assertElementNotExists(string $selector) @@ -63,8 +60,6 @@ class TestResponse extends BaseTestResponse { /** * Assert the response includes a specific element containing the given text. - * @param string $selector - * @param string $text * @return $this */ public function assertElementContains(string $selector, string $text) @@ -95,8 +90,6 @@ class TestResponse extends BaseTestResponse { /** * Assert the response does not include a specific element containing the given text. - * @param string $selector - * @param string $text * @return $this */ public function assertElementNotContains(string $selector, string $text) @@ -125,12 +118,20 @@ class TestResponse extends BaseTestResponse { return $this; } + /** + * Assert there's a notification within the view containing the given text. + * @return $this + */ + public function assertNotificationContains(string $text) + { + return $this->assertElementContains('[notification]', $text); + } + /** * Get the escaped text pattern for the constraint. - * @param string $text * @return string */ - protected function getEscapedPattern($text) + protected function getEscapedPattern(string $text) { $rawPattern = preg_quote($text, '/'); $escapedPattern = preg_quote(e($text), '/'); diff --git a/tests/Uploads/AttachmentTest.php b/tests/Uploads/AttachmentTest.php index a7efe08ab..4614c8e22 100644 --- a/tests/Uploads/AttachmentTest.php +++ b/tests/Uploads/AttachmentTest.php @@ -1,5 +1,7 @@ $fileName ]); - $this->call('DELETE', $page->getUrl()); + app(PageRepo::class)->destroy($page); + app(TrashCan::class)->empty(); $this->assertDatabaseMissing('attachments', [ 'name' => $fileName From 68b1d87ebecd4f60a2d7b4c3dff481e9f905bb9a Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 7 Nov 2020 13:19:23 +0000 Subject: [PATCH 16/72] Added test coverage of recycle bin actions --- tests/RecycleBinTest.php | 93 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 91 insertions(+), 2 deletions(-) diff --git a/tests/RecycleBinTest.php b/tests/RecycleBinTest.php index 086f63679..6a10f271b 100644 --- a/tests/RecycleBinTest.php +++ b/tests/RecycleBinTest.php @@ -6,8 +6,6 @@ use BookStack\Entities\Page; class RecycleBinTest extends TestCase { - // TODO - Test activity updating on destroy - public function test_recycle_bin_routes_permissions() { $page = Page::query()->first(); @@ -65,4 +63,95 @@ class RecycleBinTest extends TestCase $viewReq->assertElementContains('table.table', $book->pages_count . ' Pages'); $viewReq->assertElementContains('table.table', $book->chapters_count . ' Chapters'); } + + public function test_recycle_bin_empty() + { + $page = Page::query()->first(); + $book = Book::query()->where('id' , '!=', $page->book_id)->whereHas('pages')->whereHas('chapters')->with(['pages', 'chapters'])->firstOrFail(); + $editor = $this->getEditor(); + $this->actingAs($editor)->delete($page->getUrl()); + $this->actingAs($editor)->delete($book->getUrl()); + + $this->assertTrue(Deletion::query()->count() === 2); + $emptyReq = $this->asAdmin()->post('/settings/recycle-bin/empty'); + $emptyReq->assertRedirect('/settings/recycle-bin'); + + $this->assertTrue(Deletion::query()->count() === 0); + $this->assertDatabaseMissing('books', ['id' => $book->id]); + $this->assertDatabaseMissing('pages', ['id' => $page->id]); + $this->assertDatabaseMissing('pages', ['id' => $book->pages->first()->id]); + $this->assertDatabaseMissing('chapters', ['id' => $book->chapters->first()->id]); + + $itemCount = 2 + $book->pages->count() + $book->chapters->count(); + $redirectReq = $this->get('/settings/recycle-bin'); + $redirectReq->assertNotificationContains('Deleted '.$itemCount.' total items from the recycle bin'); + } + + public function test_entity_restore() + { + $book = Book::query()->whereHas('pages')->whereHas('chapters')->with(['pages', 'chapters'])->firstOrFail(); + $this->asEditor()->delete($book->getUrl()); + $deletion = Deletion::query()->firstOrFail(); + + $this->assertEquals($book->pages->count(), \DB::table('pages')->where('book_id', '=', $book->id)->whereNotNull('deleted_at')->count()); + $this->assertEquals($book->chapters->count(), \DB::table('chapters')->where('book_id', '=', $book->id)->whereNotNull('deleted_at')->count()); + + $restoreReq = $this->asAdmin()->post("/settings/recycle-bin/{$deletion->id}/restore"); + $restoreReq->assertRedirect('/settings/recycle-bin'); + $this->assertTrue(Deletion::query()->count() === 0); + + $this->assertEquals($book->pages->count(), \DB::table('pages')->where('book_id', '=', $book->id)->whereNull('deleted_at')->count()); + $this->assertEquals($book->chapters->count(), \DB::table('chapters')->where('book_id', '=', $book->id)->whereNull('deleted_at')->count()); + + $itemCount = 1 + $book->pages->count() + $book->chapters->count(); + $redirectReq = $this->get('/settings/recycle-bin'); + $redirectReq->assertNotificationContains('Restored '.$itemCount.' total items from the recycle bin'); + } + + public function test_permanent_delete() + { + $book = Book::query()->whereHas('pages')->whereHas('chapters')->with(['pages', 'chapters'])->firstOrFail(); + $this->asEditor()->delete($book->getUrl()); + $deletion = Deletion::query()->firstOrFail(); + + $deleteReq = $this->asAdmin()->delete("/settings/recycle-bin/{$deletion->id}"); + $deleteReq->assertRedirect('/settings/recycle-bin'); + $this->assertTrue(Deletion::query()->count() === 0); + + $this->assertDatabaseMissing('books', ['id' => $book->id]); + $this->assertDatabaseMissing('pages', ['id' => $book->pages->first()->id]); + $this->assertDatabaseMissing('chapters', ['id' => $book->chapters->first()->id]); + + $itemCount = 1 + $book->pages->count() + $book->chapters->count(); + $redirectReq = $this->get('/settings/recycle-bin'); + $redirectReq->assertNotificationContains('Deleted '.$itemCount.' total items from the recycle bin'); + } + + public function test_permanent_entity_delete_updates_existing_activity_with_entity_name() + { + $page = Page::query()->firstOrFail(); + $this->asEditor()->delete($page->getUrl()); + $deletion = $page->deletions()->firstOrFail(); + + $this->assertDatabaseHas('activities', [ + 'key' => 'page_delete', + 'entity_id' => $page->id, + 'entity_type' => $page->getMorphClass(), + ]); + + $this->asAdmin()->delete("/settings/recycle-bin/{$deletion->id}"); + + $this->assertDatabaseMissing('activities', [ + 'key' => 'page_delete', + 'entity_id' => $page->id, + 'entity_type' => $page->getMorphClass(), + ]); + + $this->assertDatabaseHas('activities', [ + 'key' => 'page_delete', + 'entity_id' => 0, + 'entity_type' => '', + 'extra' => $page->name, + ]); + } } \ No newline at end of file From ec3aeb3315db201251e48b9d3713b022e7d88188 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 7 Nov 2020 13:58:23 +0000 Subject: [PATCH 17/72] Added recycle bin auto-clear lifetime functionality --- .env.example.complete | 8 +++ app/Config/app.php | 7 +++ app/Entities/Managers/TrashCan.php | 25 ++++++++ app/Entities/Repos/BookRepo.php | 1 + app/Entities/Repos/BookshelfRepo.php | 1 + app/Entities/Repos/ChapterRepo.php | 1 + app/Entities/Repos/PageRepo.php | 1 + resources/lang/en/settings.php | 2 +- .../views/settings/maintenance.blade.php | 38 ++++++------- tests/RecycleBinTest.php | 57 +++++++++++++++++-- 10 files changed, 115 insertions(+), 26 deletions(-) diff --git a/.env.example.complete b/.env.example.complete index 39e7b4360..0e62b3ea6 100644 --- a/.env.example.complete +++ b/.env.example.complete @@ -255,6 +255,14 @@ APP_VIEWS_BOOKSHELVES=grid # If set to 'false' a limit will not be enforced. REVISION_LIMIT=50 +# Recycle Bin Lifetime +# The number of days that content will remain in the recycle bin before +# being considered for auto-removal. It is not a guarantee that content will +# be removed after this time. +# Set to 0 for no recycle bin functionality. +# Set to -1 for unlimited recycle bin lifetime. +RECYCLE_BIN_LIFETIME=30 + # Allow

Hello

"; + $page->save(); + + $resp = $this->getJson($this->baseEndpoint . "/{$page->id}"); + $html = $resp->json('html'); + $this->assertStringNotContainsString('script', $html); + $this->assertStringContainsString('Hello', $html); + $this->assertStringContainsString('testing', $html); + } + + public function test_update_endpoint() + { + $this->actingAsApiEditor(); + $page = Page::visible()->first(); + $details = [ + 'name' => 'My updated API page', + 'html' => '

A page created via the API

', + 'tags' => [ + [ + 'name' => 'freshtag', + 'value' => 'freshtagval', + ] + ], + ]; + + $resp = $this->putJson($this->baseEndpoint . "/{$page->id}", $details); + $page->refresh(); + + $resp->assertStatus(200); + unset($details['html']); + $resp->assertJson(array_merge($details, [ + 'id' => $page->id, 'slug' => $page->slug, 'book_id' => $page->book_id + ])); + $this->assertActivityExists('page_update', $page); + } + + public function test_providing_new_chapter_id_on_update_will_move_page() + { + $this->actingAsApiEditor(); + $page = Page::visible()->first(); + $chapter = Chapter::visible()->where('book_id', '!=', $page->book_id)->first(); + $details = [ + 'name' => 'My updated API page', + 'chapter_id' => $chapter->id, + 'html' => '

A page created via the API

', + ]; + + $resp = $this->putJson($this->baseEndpoint . "/{$page->id}", $details); + $resp->assertStatus(200); + $resp->assertJson([ + 'chapter_id' => $chapter->id, + 'book_id' => $chapter->book_id, + ]); + } + + public function test_providing_move_via_update_requires_page_create_permission_on_new_parent() + { + $this->actingAsApiEditor(); + $page = Page::visible()->first(); + $chapter = Chapter::visible()->where('book_id', '!=', $page->book_id)->first(); + $this->setEntityRestrictions($chapter, ['view'], [$this->getEditor()->roles()->first()]); + $details = [ + 'name' => 'My updated API page', + 'chapter_id' => $chapter->id, + 'html' => '

A page created via the API

', + ]; + + $resp = $this->putJson($this->baseEndpoint . "/{$page->id}", $details); + $resp->assertStatus(403); + } + + public function test_delete_endpoint() + { + $this->actingAsApiEditor(); + $page = Page::visible()->first(); + $resp = $this->deleteJson($this->baseEndpoint . "/{$page->id}"); + + $resp->assertStatus(204); + $this->assertActivityExists('page_delete', $page); + } + + public function test_export_html_endpoint() + { + $this->actingAsApiEditor(); + $page = Page::visible()->first(); + + $resp = $this->get($this->baseEndpoint . "/{$page->id}/export/html"); + $resp->assertStatus(200); + $resp->assertSee($page->name); + $resp->assertHeader('Content-Disposition', 'attachment; filename="' . $page->slug . '.html"'); + } + + public function test_export_plain_text_endpoint() + { + $this->actingAsApiEditor(); + $page = Page::visible()->first(); + + $resp = $this->get($this->baseEndpoint . "/{$page->id}/export/plaintext"); + $resp->assertStatus(200); + $resp->assertSee($page->name); + $resp->assertHeader('Content-Disposition', 'attachment; filename="' . $page->slug . '.txt"'); + } + + public function test_export_pdf_endpoint() + { + $this->actingAsApiEditor(); + $page = Page::visible()->first(); + + $resp = $this->get($this->baseEndpoint . "/{$page->id}/export/pdf"); + $resp->assertStatus(200); + $resp->assertHeader('Content-Disposition', 'attachment; filename="' . $page->slug . '.pdf"'); + } +} \ No newline at end of file From bf8716bb22e307e94abaf4bf7ef89b5caa46aeed Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 28 Nov 2020 16:42:12 +0000 Subject: [PATCH 39/72] Fixed bad collection/array mixing causing error on seed --- app/Entities/Tools/SearchIndex.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/Entities/Tools/SearchIndex.php b/app/Entities/Tools/SearchIndex.php index 687b9d072..81a5022ce 100644 --- a/app/Entities/Tools/SearchIndex.php +++ b/app/Entities/Tools/SearchIndex.php @@ -3,6 +3,7 @@ use BookStack\Entities\EntityProvider; use BookStack\Entities\Models\Entity; use BookStack\Entities\Models\SearchTerm; +use Illuminate\Support\Collection; class SearchIndex { @@ -75,8 +76,8 @@ class SearchIndex $entityModel->newQuery() ->withTrashed() ->select($selectFields) - ->chunk(1000, function ($entities) { - $this->indexEntities($entities); + ->chunk(1000, function (Collection $entities) { + $this->indexEntities($entities->all()); }); } } From 0b01a77c16413a142e138b85ddbd9ae7c41081d8 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 29 Nov 2020 19:08:13 +0000 Subject: [PATCH 40/72] Swapped out HTML diff implementation for own, removes tidy depdendancy --- .../Controllers/PageRevisionController.php | 4 +- composer.json | 5 +- composer.lock | 151 ++++++------------ 3 files changed, 52 insertions(+), 108 deletions(-) diff --git a/app/Http/Controllers/PageRevisionController.php b/app/Http/Controllers/PageRevisionController.php index d5520166d..4c4333016 100644 --- a/app/Http/Controllers/PageRevisionController.php +++ b/app/Http/Controllers/PageRevisionController.php @@ -3,7 +3,7 @@ use BookStack\Entities\Tools\PageContent; use BookStack\Entities\Repos\PageRepo; use BookStack\Exceptions\NotFoundException; -use GatherContent\Htmldiff\Htmldiff; +use Ssddanbrown\HtmlDiff\Diff; class PageRevisionController extends Controller { @@ -72,7 +72,7 @@ class PageRevisionController extends Controller $prev = $revision->getPrevious(); $prevContent = $prev->html ?? ''; - $diff = (new Htmldiff)->diff($prevContent, $revision->html); + $diff = Diff::excecute($prevContent, $revision->html); $page->fill($revision->toArray()); // TODO - Refactor PageContent so we don't need to juggle this diff --git a/composer.json b/composer.json index 8a2b7d656..17bc12e4a 100644 --- a/composer.json +++ b/composer.json @@ -11,14 +11,12 @@ "ext-gd": "*", "ext-json": "*", "ext-mbstring": "*", - "ext-tidy": "*", "ext-xml": "*", "barryvdh/laravel-dompdf": "^0.8.6", "barryvdh/laravel-snappy": "^0.4.7", "doctrine/dbal": "^2.9", "facade/ignition": "^1.4", "fideloper/proxy": "^4.0", - "gathercontent/htmldiff": "^0.2.1", "intervention/image": "^2.5", "laravel/framework": "^6.18", "laravel/socialite": "^4.3.2", @@ -32,7 +30,8 @@ "socialiteproviders/microsoft-azure": "^3.0", "socialiteproviders/okta": "^1.0", "socialiteproviders/slack": "^3.0", - "socialiteproviders/twitch": "^5.0" + "socialiteproviders/twitch": "^5.0", + "ssddanbrown/htmldiff": "^1.0" }, "require-dev": { "barryvdh/laravel-debugbar": "^3.2.8", diff --git a/composer.lock b/composer.lock index b22874455..dcfc3beb4 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": "34390536dd685e0bc49b179babaa06ec", + "content-hash": "a61fd1c287bd93fa496202c6583c7bb1", "packages": [ { "name": "aws/aws-sdk-php", @@ -214,57 +214,6 @@ ], "time": "2020-09-07T12:33:10+00:00" }, - { - "name": "cogpowered/finediff", - "version": "0.3.1", - "source": { - "type": "git", - "url": "https://github.com/cogpowered/FineDiff.git", - "reference": "339ddc8c3afb656efed4f2f0a80e5c3d026f8ea8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/cogpowered/FineDiff/zipball/339ddc8c3afb656efed4f2f0a80e5c3d026f8ea8", - "reference": "339ddc8c3afb656efed4f2f0a80e5c3d026f8ea8", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "require-dev": { - "mockery/mockery": "*", - "phpunit/phpunit": "*" - }, - "type": "library", - "autoload": { - "psr-0": { - "cogpowered\\FineDiff": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Rob Crowe", - "email": "rob@cogpowered.com" - }, - { - "name": "Raymond Hill" - } - ], - "description": "PHP implementation of a Fine granularity Diff engine", - "homepage": "https://github.com/cogpowered/FineDiff", - "keywords": [ - "diff", - "finediff", - "opcode", - "string", - "text" - ], - "time": "2014-05-19T10:25:02+00:00" - }, { "name": "doctrine/cache", "version": "1.10.2", @@ -1203,55 +1152,6 @@ ], "time": "2020-06-14T09:00:00+00:00" }, - { - "name": "gathercontent/htmldiff", - "version": "0.2.1", - "source": { - "type": "git", - "url": "https://github.com/gathercontent/htmldiff.git", - "reference": "24674a62315f64330134b4a4c5b01a7b59193c93" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/gathercontent/htmldiff/zipball/24674a62315f64330134b4a4c5b01a7b59193c93", - "reference": "24674a62315f64330134b4a4c5b01a7b59193c93", - "shasum": "" - }, - "require": { - "cogpowered/finediff": "0.3.1", - "ext-tidy": "*" - }, - "require-dev": { - "phpunit/phpunit": "4.*", - "squizlabs/php_codesniffer": "1.*" - }, - "type": "library", - "autoload": { - "psr-0": { - "GatherContent\\Htmldiff": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Andrew Cairns", - "email": "andrew@gathercontent.com" - }, - { - "name": "Mathew Chapman", - "email": "mat@gathercontent.com" - }, - { - "name": "Peter Legierski", - "email": "peter@gathercontent.com" - } - ], - "description": "Compare two HTML strings", - "time": "2015-04-15T15:39:46+00:00" - }, { "name": "guzzlehttp/guzzle", "version": "6.5.5", @@ -3625,6 +3525,52 @@ "description": "Twitch OAuth2 Provider for Laravel Socialite", "time": "2020-05-06T22:51:30+00:00" }, + { + "name": "ssddanbrown/htmldiff", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/ssddanbrown/HtmlDiff.git", + "reference": "d1978c7d1c685800997f982a0ae9cff1e45df70c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ssddanbrown/HtmlDiff/zipball/d1978c7d1c685800997f982a0ae9cff1e45df70c", + "reference": "d1978c7d1c685800997f982a0ae9cff1e45df70c", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": ">=7.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5|^9.4.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Ssddanbrown\\HtmlDiff\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Dan Brown", + "email": "ssddanbrown@googlemail.com", + "role": "Developer" + } + ], + "description": "HTML Content Diff Generator", + "homepage": "https://github.com/ssddanbrown/htmldiff", + "support": { + "issues": "https://github.com/ssddanbrown/HtmlDiff/issues", + "source": "https://github.com/ssddanbrown/HtmlDiff/tree/v1.0.0" + }, + "time": "2020-11-29T18:38:45+00:00" + }, { "name": "swiftmailer/swiftmailer", "version": "v6.2.3", @@ -8690,12 +8636,11 @@ "ext-gd": "*", "ext-json": "*", "ext-mbstring": "*", - "ext-tidy": "*", "ext-xml": "*" }, "platform-dev": [], "platform-overrides": { "php": "7.2.0" }, - "plugin-api-version": "1.1.0" + "plugin-api-version": "2.0.0" } From 6c09334ba07e6ca76405311aea816991081fb4c2 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 6 Dec 2020 22:23:21 +0000 Subject: [PATCH 41/72] Fixed issue where page export contain system would miss images --- app/Entities/Tools/ExportFormatter.php | 2 +- tests/Entity/ExportTest.php | 20 ++++++++++++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/app/Entities/Tools/ExportFormatter.php b/app/Entities/Tools/ExportFormatter.php index 92469a9b0..9cf8b56af 100644 --- a/app/Entities/Tools/ExportFormatter.php +++ b/app/Entities/Tools/ExportFormatter.php @@ -143,7 +143,7 @@ class ExportFormatter protected function containHtml(string $htmlContent): string { $imageTagsOutput = []; - preg_match_all("/\/i", $htmlContent, $imageTagsOutput); + preg_match_all("/\/i", $htmlContent, $imageTagsOutput); // Replace image src with base64 encoded image strings if (isset($imageTagsOutput[0]) && count($imageTagsOutput[0]) > 0) { diff --git a/tests/Entity/ExportTest.php b/tests/Entity/ExportTest.php index 7c56a7268..1e44f015a 100644 --- a/tests/Entity/ExportTest.php +++ b/tests/Entity/ExportTest.php @@ -167,12 +167,28 @@ class ExportTest extends TestCase $resp->assertSee(''; + $page->save(); + + $resp = $this->asEditor()->get($page->getUrl('/export/html')); + Storage::disk('local')->delete('uploads/images/gallery/svg_test.svg'); + Storage::disk('local')->delete('uploads/images/gallery/svg_test2.svg'); + + $resp->assertDontSee('http://localhost/uploads/images/gallery/svg_test'); + } + public function test_page_export_contained_html_image_fetches_only_run_when_url_points_to_image_upload_folder() { $page = Page::first(); $page->html = '' - ."\n".'' - ."\n".''; + .'' + .''; $storageDisk = Storage::disk('local'); $storageDisk->makeDirectory('uploads/images/gallery'); $storageDisk->put('uploads/images/gallery/svg_test.svg', 'good'); From 00308ad4ab9302293afd0a65f815feeaca06b626 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Tue, 8 Dec 2020 23:46:38 +0000 Subject: [PATCH 42/72] Cleaned up some user/image areas of the app Further cleanup of docblocks and standardisation of repos. --- app/Auth/Role.php | 5 +- app/Auth/UserRepo.php | 87 ++++++---------- app/Console/Commands/CreateAdmin.php | 2 - app/Entities/Models/Entity.php | 8 +- app/Http/Controllers/UserController.php | 2 +- app/Ownable.php | 8 -- app/Uploads/ImageService.php | 85 +--------------- app/Uploads/UserAvatars.php | 100 +++++++++++++++++++ resources/views/books/sort-box.blade.php | 4 +- resources/views/partials/book-tree.blade.php | 2 +- 10 files changed, 146 insertions(+), 157 deletions(-) create mode 100644 app/Uploads/UserAvatars.php diff --git a/app/Auth/Role.php b/app/Auth/Role.php index 255158afb..629cd6a95 100644 --- a/app/Auth/Role.php +++ b/app/Auth/Role.php @@ -5,6 +5,7 @@ use BookStack\Auth\Permissions\RolePermission; use BookStack\Interfaces\Loggable; use BookStack\Model; use Illuminate\Database\Eloquent\Collection; +use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\HasMany; /** @@ -23,7 +24,7 @@ class Role extends Model implements Loggable /** * The roles that belong to the role. */ - public function users() + public function users(): BelongsToMany { return $this->belongsToMany(User::class)->orderBy('name', 'asc'); } @@ -39,7 +40,7 @@ class Role extends Model implements Loggable /** * The RolePermissions that belong to the role. */ - public function permissions() + public function permissions(): BelongsToMany { return $this->belongsToMany(RolePermission::class, 'permission_role', 'role_id', 'permission_id'); } diff --git a/app/Auth/UserRepo.php b/app/Auth/UserRepo.php index 884f53463..6b7de3259 100644 --- a/app/Auth/UserRepo.php +++ b/app/Auth/UserRepo.php @@ -8,25 +8,24 @@ use BookStack\Entities\Models\Page; use BookStack\Exceptions\NotFoundException; use BookStack\Exceptions\UserUpdateException; use BookStack\Uploads\Image; +use BookStack\Uploads\UserAvatars; use Exception; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Collection; use Illuminate\Pagination\LengthAwarePaginator; use Images; use Log; class UserRepo { - - protected $user; - protected $role; + protected $userAvatar; /** * UserRepo constructor. */ - public function __construct(User $user, Role $role) + public function __construct(UserAvatars $userAvatar) { - $this->user = $user; - $this->role = $role; + $this->userAvatar = $userAvatar; } /** @@ -34,25 +33,23 @@ class UserRepo */ public function getByEmail(string $email): ?User { - return $this->user->where('email', '=', $email)->first(); + return User::query()->where('email', '=', $email)->first(); } /** - * @param int $id - * @return User + * Get a user by their ID. */ - public function getById($id) + public function getById(int $id): User { - return $this->user->newQuery()->findOrFail($id); + return User::query()->findOrFail($id); } /** * Get all the users with their permissions. - * @return Builder|static */ - public function getAllUsers() + public function getAllUsers(): Collection { - return $this->user->with('roles', 'avatar')->orderBy('name', 'asc')->get(); + return User::query()->with('roles', 'avatar')->orderBy('name', 'asc')->get(); } /** @@ -68,7 +65,7 @@ class UserRepo ->take(1); } - $query = $this->user->with(['roles', 'avatar', 'latestActivity']) + $query = User::query()->with(['roles', 'avatar', 'latestActivity']) ->orderBy($sort, $sortData['order']); if ($sortData['search']) { @@ -96,14 +93,12 @@ class UserRepo /** * Assign a user to a system-level role. - * @param User $user - * @param $systemRoleName * @throws NotFoundException */ - public function attachSystemRole(User $user, $systemRoleName) + public function attachSystemRole(User $user, string $systemRoleName) { - $role = $this->role->newQuery()->where('system_name', '=', $systemRoleName)->first(); - if ($role === null) { + $role = Role::getSystemRole($systemRoleName); + if (is_null($role)) { throw new NotFoundException("Role '{$systemRoleName}' not found"); } $user->attachRole($role); @@ -111,26 +106,23 @@ class UserRepo /** * Checks if the give user is the only admin. - * @param User $user - * @return bool */ - public function isOnlyAdmin(User $user) + public function isOnlyAdmin(User $user): bool { if (!$user->hasSystemRole('admin')) { return false; } - $adminRole = $this->role->getSystemRole('admin'); - if ($adminRole->users->count() > 1) { + $adminRole = Role::getSystemRole('admin'); + if ($adminRole->users()->count() > 1) { return false; } + return true; } /** * Set the assigned user roles via an array of role IDs. - * @param User $user - * @param array $roles * @throws UserUpdateException */ public function setUserRoles(User $user, array $roles) @@ -145,14 +137,11 @@ class UserRepo /** * Check if the given user is the last admin and their new roles no longer * contains the admin role. - * @param User $user - * @param array $newRoles - * @return bool */ protected function demotingLastAdmin(User $user, array $newRoles) : bool { if ($this->isOnlyAdmin($user)) { - $adminRole = $this->role->getSystemRole('admin'); + $adminRole = Role::getSystemRole('admin'); if (!in_array(strval($adminRole->id), $newRoles)) { return true; } @@ -166,18 +155,18 @@ class UserRepo */ public function create(array $data, bool $emailConfirmed = false): User { - return $this->user->forceCreate([ + $details = [ 'name' => $data['name'], 'email' => $data['email'], 'password' => bcrypt($data['password']), 'email_confirmed' => $emailConfirmed, 'external_auth_id' => $data['external_auth_id'] ?? '', - ]); + ]; + return User::query()->forceCreate($details); } /** * Remove the given user from storage, Delete all related content. - * @param User $user * @throws Exception */ public function destroy(User $user) @@ -187,7 +176,10 @@ class UserRepo $user->delete(); // Delete user profile images - $profileImages = Image::where('type', '=', 'user')->where('uploaded_to', '=', $user->id)->get(); + $profileImages = Image::query()->where('type', '=', 'user') + ->where('uploaded_to', '=', $user->id) + ->get(); + foreach ($profileImages as $image) { Images::destroy($image); } @@ -195,12 +187,8 @@ class UserRepo /** * Get the latest activity for a user. - * @param User $user - * @param int $count - * @param int $page - * @return array */ - public function getActivity(User $user, $count = 20, $page = 0) + public function getActivity(User $user, int $count = 20, int $page = 0): array { return Activity::userActivity($user, $count, $page); } @@ -241,33 +229,22 @@ class UserRepo /** * Get the roles in the system that are assignable to a user. - * @return mixed */ - public function getAllRoles() + public function getAllRoles(): Collection { - return $this->role->newQuery()->orderBy('display_name', 'asc')->get(); + return Role::query()->orderBy('display_name', 'asc')->get(); } /** * Get an avatar image for a user and set it as their avatar. * Returns early if avatars disabled or not set in config. - * @param User $user - * @return bool */ - public function downloadAndAssignUserAvatar(User $user) + public function downloadAndAssignUserAvatar(User $user): void { - if (!Images::avatarFetchEnabled()) { - return false; - } - try { - $avatar = Images::saveUserAvatar($user); - $user->avatar()->associate($avatar); - $user->save(); - return true; + $this->userAvatar->fetchAndAssignToUser($user); } catch (Exception $e) { Log::error('Failed to save user avatar image'); - return false; } } } diff --git a/app/Console/Commands/CreateAdmin.php b/app/Console/Commands/CreateAdmin.php index e67da8717..3d1a3dca0 100644 --- a/app/Console/Commands/CreateAdmin.php +++ b/app/Console/Commands/CreateAdmin.php @@ -28,8 +28,6 @@ class CreateAdmin extends Command /** * Create a new command instance. - * - * @param UserRepo $userRepo */ public function __construct(UserRepo $userRepo) { diff --git a/app/Entities/Models/Entity.php b/app/Entities/Models/Entity.php index f764ad16e..e681a4e22 100644 --- a/app/Entities/Models/Entity.php +++ b/app/Entities/Models/Entity.php @@ -205,12 +205,12 @@ abstract class Entity extends Ownable } /** - * Get entity type. - * @return mixed + * Get the entity type as a simple lowercase word. */ - public static function getType() + public static function getType(): string { - return strtolower(static::getClassName()); + $className = array_slice(explode('\\', static::class), -1, 1)[0]; + return strtolower($className); } /** diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index 1713565fc..8d688ed84 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -188,7 +188,7 @@ class UserController extends Controller $user->image_id = $image->id; } - // Delete the profile image if set to + // Delete the profile image if reset option is in request if ($request->has('profile_image_reset')) { $this->imageRepo->destroyImage($user->avatar); } diff --git a/app/Ownable.php b/app/Ownable.php index bf24fad5d..b118bc742 100644 --- a/app/Ownable.php +++ b/app/Ownable.php @@ -26,12 +26,4 @@ abstract class Ownable extends Model return $this->belongsTo(User::class, 'updated_by'); } - /** - * Gets the class name. - * @return string - */ - public static function getClassName() - { - return strtolower(array_slice(explode('\\', static::class), -1, 1)[0]); - } } diff --git a/app/Uploads/ImageService.php b/app/Uploads/ImageService.php index 1e5ad8aa1..5c16827cb 100644 --- a/app/Uploads/ImageService.php +++ b/app/Uploads/ImageService.php @@ -1,7 +1,5 @@ image = $image; $this->imageTool = $imageTool; $this->fileSystem = $fileSystem; $this->cache = $cache; - $this->http = $http; } /** @@ -77,14 +72,9 @@ class ImageService /** * Save a new image from a uri-encoded base64 string of data. - * @param string $base64Uri - * @param string $name - * @param string $type - * @param int $uploadedTo - * @return Image * @throws ImageUploadException */ - public function saveNewFromBase64Uri(string $base64Uri, string $name, string $type, $uploadedTo = 0) + public function saveNewFromBase64Uri(string $base64Uri, string $name, string $type, int $uploadedTo = 0): Image { $splitData = explode(';base64,', $base64Uri); if (count($splitData) < 2) { @@ -94,30 +84,11 @@ class ImageService return $this->saveNew($name, $data, $type, $uploadedTo); } - /** - * Gets an image from url and saves it to the database. - * @param $url - * @param string $type - * @param bool|string $imageName - * @return mixed - * @throws Exception - */ - private function saveNewFromUrl($url, $type, $imageName = false) - { - $imageName = $imageName ? $imageName : basename($url); - try { - $imageData = $this->http->fetch($url); - } catch (HttpFetchException $exception) { - throw new Exception(trans('errors.cannot_get_image_from_url', ['url' => $url])); - } - return $this->saveNew($imageName, $imageData, $type); - } - /** * Save a new image into storage. * @throws ImageUploadException */ - private function saveNew(string $imageName, string $imageData, string $type, int $uploadedTo = 0): Image + public function saveNew(string $imageName, string $imageData, string $type, int $uploadedTo = 0): Image { $storage = $this->getStorage($type); $secureUploads = setting('app-secure-images'); @@ -327,56 +298,6 @@ class ImageService return (count($files) === 0 && count($folders) === 0); } - /** - * Save an avatar image from an external service. - * @throws Exception - */ - public function saveUserAvatar(User $user, int $size = 500): Image - { - $avatarUrl = $this->getAvatarUrl(); - $email = strtolower(trim($user->email)); - - $replacements = [ - '${hash}' => md5($email), - '${size}' => $size, - '${email}' => urlencode($email), - ]; - - $userAvatarUrl = strtr($avatarUrl, $replacements); - $imageName = str_replace(' ', '-', $user->name . '-avatar.png'); - $image = $this->saveNewFromUrl($userAvatarUrl, 'user', $imageName); - $image->created_by = $user->id; - $image->updated_by = $user->id; - $image->uploaded_to = $user->id; - $image->save(); - - return $image; - } - - /** - * Check if fetching external avatars is enabled. - */ - public function avatarFetchEnabled(): bool - { - $fetchUrl = $this->getAvatarUrl(); - return is_string($fetchUrl) && strpos($fetchUrl, 'http') === 0; - } - - /** - * Get the URL to fetch avatars from. - * @return string|mixed - */ - protected function getAvatarUrl() - { - $url = trim(config('services.avatar_url')); - - if (empty($url) && !config('services.disable_services')) { - $url = 'https://www.gravatar.com/avatar/${hash}?s=${size}&d=identicon'; - } - - return $url; - } - /** * Delete gallery and drawings that are not within HTML content of pages or page revisions. * Checks based off of only the image name. diff --git a/app/Uploads/UserAvatars.php b/app/Uploads/UserAvatars.php new file mode 100644 index 000000000..92b06bc8a --- /dev/null +++ b/app/Uploads/UserAvatars.php @@ -0,0 +1,100 @@ +imageService = $imageService; + $this->http = $http; + } + + /** + * Fetch and assign an avatar image to the given user. + */ + public function fetchAndAssignToUser(User $user): void + { + if (!$this->avatarFetchEnabled()) { + return; + } + + try { + $avatar = $this->saveAvatarImage($user); + $user->avatar()->associate($avatar); + $user->save(); + } catch (Exception $e) { + Log::error('Failed to save user avatar image'); + } + } + + /** + * Save an avatar image from an external service. + * @throws Exception + */ + protected function saveAvatarImage(User $user, int $size = 500): Image + { + $avatarUrl = $this->getAvatarUrl(); + $email = strtolower(trim($user->email)); + + $replacements = [ + '${hash}' => md5($email), + '${size}' => $size, + '${email}' => urlencode($email), + ]; + + $userAvatarUrl = strtr($avatarUrl, $replacements); + $imageName = str_replace(' ', '-', $user->id . '-avatar.png'); + $imageData = $this->getAvatarImageData($userAvatarUrl); + + $image = $this->imageService->saveNew($imageName, $imageData, 'user', $user->id); + $image->created_by = $user->id; + $image->updated_by = $user->id; + $image->save(); + + return $image; + } + + /** + * Gets an image from url and returns it as a string of image data. + * @throws Exception + */ + protected function getAvatarImageData(string $url): string + { + try { + $imageData = $this->http->fetch($url); + } catch (HttpFetchException $exception) { + throw new Exception(trans('errors.cannot_get_image_from_url', ['url' => $url])); + } + return $imageData; + } + + /** + * Check if fetching external avatars is enabled. + */ + protected function avatarFetchEnabled(): bool + { + $fetchUrl = $this->getAvatarUrl(); + return is_string($fetchUrl) && strpos($fetchUrl, 'http') === 0; + } + + /** + * Get the URL to fetch avatars from. + */ + protected function getAvatarUrl(): string + { + $url = trim(config('services.avatar_url')); + + if (empty($url) && !config('services.disable_services')) { + $url = 'https://www.gravatar.com/avatar/${hash}?s=${size}&d=identicon'; + } + + return $url; + } + +} \ No newline at end of file diff --git a/resources/views/books/sort-box.blade.php b/resources/views/books/sort-box.blade.php index 98f0af87e..5d14e3598 100644 --- a/resources/views/books/sort-box.blade.php +++ b/resources/views/books/sort-box.blade.php @@ -13,8 +13,8 @@
    @foreach($bookChildren as $bookChild) -
  • diff --git a/resources/views/partials/book-tree.blade.php b/resources/views/partials/book-tree.blade.php index 5131af1aa..dcc76cd83 100644 --- a/resources/views/partials/book-tree.blade.php +++ b/resources/views/partials/book-tree.blade.php @@ -12,7 +12,7 @@ @endif @foreach($sidebarTree as $bookChild) -
  • +
  • @include('partials.entity-list-item-basic', ['entity' => $bookChild, 'classes' => $current->matches($bookChild)? 'selected' : '']) @if($bookChild->isA('chapter') && count($bookChild->pages) > 0) From 5ab0db969027a154c5677f7d09fe08bad9789341 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Thu, 17 Dec 2020 02:29:53 +0000 Subject: [PATCH 43/72] Updated chapter delete wording to fit with new logic --- resources/lang/en/entities.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/lang/en/entities.php b/resources/lang/en/entities.php index f64867a56..485ecb7bc 100644 --- a/resources/lang/en/entities.php +++ b/resources/lang/en/entities.php @@ -146,7 +146,7 @@ return [ 'chapters_create' => 'Create New Chapter', 'chapters_delete' => 'Delete Chapter', 'chapters_delete_named' => 'Delete Chapter :chapterName', - 'chapters_delete_explain' => 'This will delete the chapter with the name \':chapterName\'. All pages will be removed and added directly to the parent book.', + 'chapters_delete_explain' => 'This will delete the chapter with the name \':chapterName\'. All pages that exist within this chapter will also be deleted.', 'chapters_delete_confirm' => 'Are you sure you want to delete this chapter?', 'chapters_edit' => 'Edit Chapter', 'chapters_edit_named' => 'Edit Chapter :chapterName', From d7e0d3e2d6c66891f3466a47578185819dcaa863 Mon Sep 17 00:00:00 2001 From: shubhamosmosys <57482557+shubhamosmosys@users.noreply.github.com> Date: Thu, 17 Dec 2020 19:47:15 +0530 Subject: [PATCH 44/72] Fix issue with viewing export dropdown list There is issue with viewing all the export list --- resources/sass/_layout.scss | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/resources/sass/_layout.scss b/resources/sass/_layout.scss index c4e412f0e..be86d0498 100644 --- a/resources/sass/_layout.scss +++ b/resources/sass/_layout.scss @@ -282,6 +282,9 @@ body.flexbox { max-width: 940px; margin: 0 auto; } + .tri-layout-right-contents { + height: 1000px; + } } @include smaller-than($l) { @@ -350,4 +353,4 @@ body.flexbox { margin-inline-start: 0; margin-inline-end: 0; } -} \ No newline at end of file +} From 20bb76afdba57def0cf8fc025fe381193162caae Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Fri, 18 Dec 2020 20:04:48 +0000 Subject: [PATCH 45/72] Fixed changed namespaces for merged test --- tests/Permissions/ExportPermissionsTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Permissions/ExportPermissionsTest.php b/tests/Permissions/ExportPermissionsTest.php index 32ee9e7d6..e5a1146a5 100644 --- a/tests/Permissions/ExportPermissionsTest.php +++ b/tests/Permissions/ExportPermissionsTest.php @@ -1,7 +1,7 @@ Date: Sun, 13 Dec 2020 15:07:58 +0000 Subject: [PATCH 46/72] Updated deps based on changes done for php8 readiness Commit cherry-picked from branch then made further changes. Updates min php version. --- composer.json | 58 +- composer.lock | 2599 ++++++++++++++++++++++++++++++------------------- 2 files changed, 1633 insertions(+), 1024 deletions(-) diff --git a/composer.json b/composer.json index 17bc12e4a..a58905095 100644 --- a/composer.json +++ b/composer.json @@ -5,43 +5,42 @@ "license": "MIT", "type": "project", "require": { - "php": "^7.2", + "php": "^7.2.5", "ext-curl": "*", "ext-dom": "*", "ext-gd": "*", "ext-json": "*", "ext-mbstring": "*", "ext-xml": "*", - "barryvdh/laravel-dompdf": "^0.8.6", - "barryvdh/laravel-snappy": "^0.4.7", + "barryvdh/laravel-dompdf": "^0.8.7", + "barryvdh/laravel-snappy": "^0.4.8", "doctrine/dbal": "^2.9", - "facade/ignition": "^1.4", - "fideloper/proxy": "^4.0", - "intervention/image": "^2.5", - "laravel/framework": "^6.18", - "laravel/socialite": "^4.3.2", - "league/commonmark": "^1.4", - "league/flysystem-aws-s3-v3": "^1.0", - "nunomaduro/collision": "^3.0", + "facade/ignition": "^1.16.4", + "fideloper/proxy": "^4.4.1", + "intervention/image": "^2.5.1", + "laravel/framework": "^6.20", + "laravel/socialite": "^5.1", + "league/commonmark": "^1.5", + "league/flysystem-aws-s3-v3": "^1.0.29", + "nunomaduro/collision": "^3.1", "onelogin/php-saml": "^3.3", - "predis/predis": "^1.1", - "socialiteproviders/discord": "^2.0", - "socialiteproviders/gitlab": "^3.0", - "socialiteproviders/microsoft-azure": "^3.0", - "socialiteproviders/okta": "^1.0", - "socialiteproviders/slack": "^3.0", - "socialiteproviders/twitch": "^5.0", + "predis/predis": "^1.1.6", + "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" }, "require-dev": { - "barryvdh/laravel-debugbar": "^3.2.8", - "barryvdh/laravel-ide-helper": "^2.6.4", - "fzaninotto/faker": "^1.4", - "laravel/browser-kit-testing": "^5.1", - "mockery/mockery": "^1.0", + "barryvdh/laravel-debugbar": "^3.5.1", + "barryvdh/laravel-ide-helper": "^2.8.2", + "fakerphp/faker": "^1.9.1", + "laravel/browser-kit-testing": "^5.2", + "mockery/mockery": "^1.3.3", "phpunit/phpunit": "^8.0", - "squizlabs/php_codesniffer": "^3.4", - "wnx/laravel-stats": "^2.0" + "squizlabs/php_codesniffer": "^3.5.8" }, "autoload": { "classmap": [ @@ -67,13 +66,8 @@ "post-create-project-cmd": [ "@php artisan key:generate --ansi" ], - "pre-update-cmd": [ - "@php -r \"!file_exists('bootstrap/cache/services.php') || @unlink('bootstrap/cache/services.php');\"", - "@php -r \"!file_exists('bootstrap/cache/compiled.php') || @unlink('bootstrap/cache/compiled.php');\"" - ], "pre-install-cmd": [ - "@php -r \"!file_exists('bootstrap/cache/services.php') || @unlink('bootstrap/cache/services.php');\"", - "@php -r \"!file_exists('bootstrap/cache/compiled.php') || @unlink('bootstrap/cache/compiled.php');\"" + "@php -r \"!file_exists('bootstrap/cache/services.php') || @unlink('bootstrap/cache/services.php');\"" ], "post-install-cmd": [ "@php artisan cache:clear", @@ -93,7 +87,7 @@ "preferred-install": "dist", "sort-packages": true, "platform": { - "php": "7.2.0" + "php": "7.2.5" } }, "extra": { diff --git a/composer.lock b/composer.lock index dcfc3beb4..360bd57a6 100644 --- a/composer.lock +++ b/composer.lock @@ -4,20 +4,20 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "a61fd1c287bd93fa496202c6583c7bb1", + "content-hash": "e89dcb5443300c86da774d0abd956d71", "packages": [ { "name": "aws/aws-sdk-php", - "version": "3.154.6", + "version": "3.171.2", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "83a1382930359e4d4f4c9187239f059d5b282520" + "reference": "742663a85ec84647f74dea454d2dc45bba180f9d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/83a1382930359e4d4f4c9187239f059d5b282520", - "reference": "83a1382930359e4d4f4c9187239f059d5b282520", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/742663a85ec84647f74dea454d2dc45bba180f9d", + "reference": "742663a85ec84647f74dea454d2dc45bba180f9d", "shasum": "" }, "require": { @@ -89,7 +89,12 @@ "s3", "sdk" ], - "time": "2020-09-18T18:16:42+00:00" + "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.171.2" + }, + "time": "2020-12-18T19:12:13+00:00" }, { "name": "barryvdh/laravel-dompdf", @@ -145,6 +150,10 @@ "laravel", "pdf" ], + "support": { + "issues": "https://github.com/barryvdh/laravel-dompdf/issues", + "source": "https://github.com/barryvdh/laravel-dompdf/tree/master" + }, "funding": [ { "url": "https://github.com/barryvdh", @@ -212,6 +221,10 @@ "wkhtmltoimage", "wkhtmltopdf" ], + "support": { + "issues": "https://github.com/barryvdh/laravel-snappy/issues", + "source": "https://github.com/barryvdh/laravel-snappy/tree/master" + }, "time": "2020-09-07T12:33:10+00:00" }, { @@ -294,6 +307,10 @@ "redis", "xcache" ], + "support": { + "issues": "https://github.com/doctrine/cache/issues", + "source": "https://github.com/doctrine/cache/tree/1.10.x" + }, "funding": [ { "url": "https://www.doctrine-project.org/sponsorship.html", @@ -403,6 +420,10 @@ "sqlserver", "sqlsrv" ], + "support": { + "issues": "https://github.com/doctrine/dbal/issues", + "source": "https://github.com/doctrine/dbal/tree/2.10.4" + }, "funding": [ { "url": "https://www.doctrine-project.org/sponsorship.html", @@ -493,6 +514,10 @@ "event system", "events" ], + "support": { + "issues": "https://github.com/doctrine/event-manager/issues", + "source": "https://github.com/doctrine/event-manager/tree/1.1.x" + }, "funding": [ { "url": "https://www.doctrine-project.org/sponsorship.html", @@ -584,6 +609,10 @@ "uppercase", "words" ], + "support": { + "issues": "https://github.com/doctrine/inflector/issues", + "source": "https://github.com/doctrine/inflector/tree/2.0.x" + }, "funding": [ { "url": "https://www.doctrine-project.org/sponsorship.html", @@ -660,6 +689,10 @@ "parser", "php" ], + "support": { + "issues": "https://github.com/doctrine/lexer/issues", + "source": "https://github.com/doctrine/lexer/tree/1.2.1" + }, "funding": [ { "url": "https://www.doctrine-project.org/sponsorship.html", @@ -742,27 +775,31 @@ ], "description": "DOMPDF is a CSS 2.1 compliant HTML to PDF converter", "homepage": "https://github.com/dompdf/dompdf", + "support": { + "issues": "https://github.com/dompdf/dompdf/issues", + "source": "https://github.com/dompdf/dompdf/tree/master" + }, "time": "2020-08-30T22:54:22+00:00" }, { "name": "dragonmantank/cron-expression", - "version": "v2.3.0", + "version": "v2.3.1", "source": { "type": "git", "url": "https://github.com/dragonmantank/cron-expression.git", - "reference": "72b6fbf76adb3cf5bc0db68559b33d41219aba27" + "reference": "65b2d8ee1f10915efb3b55597da3404f096acba2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/72b6fbf76adb3cf5bc0db68559b33d41219aba27", - "reference": "72b6fbf76adb3cf5bc0db68559b33d41219aba27", + "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/65b2d8ee1f10915efb3b55597da3404f096acba2", + "reference": "65b2d8ee1f10915efb3b55597da3404f096acba2", "shasum": "" }, "require": { - "php": "^7.0" + "php": "^7.0|^8.0" }, "require-dev": { - "phpunit/phpunit": "^6.4|^7.0" + "phpunit/phpunit": "^6.4|^7.0|^8.0|^9.0" }, "type": "library", "extra": { @@ -796,20 +833,30 @@ "cron", "schedule" ], - "time": "2019-03-31T00:38:28+00:00" + "support": { + "issues": "https://github.com/dragonmantank/cron-expression/issues", + "source": "https://github.com/dragonmantank/cron-expression/tree/v2.3.1" + }, + "funding": [ + { + "url": "https://github.com/dragonmantank", + "type": "github" + } + ], + "time": "2020-10-13T00:52:37+00:00" }, { "name": "egulias/email-validator", - "version": "2.1.20", + "version": "2.1.24", "source": { "type": "git", "url": "https://github.com/egulias/EmailValidator.git", - "reference": "f46887bc48db66c7f38f668eb7d6ae54583617ff" + "reference": "ca90a3291eee1538cd48ff25163240695bd95448" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/f46887bc48db66c7f38f668eb7d6ae54583617ff", - "reference": "f46887bc48db66c7f38f668eb7d6ae54583617ff", + "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/ca90a3291eee1538cd48ff25163240695bd95448", + "reference": "ca90a3291eee1538cd48ff25163240695bd95448", "shasum": "" }, "require": { @@ -854,26 +901,36 @@ "validation", "validator" ], - "time": "2020-09-06T13:44:32+00:00" + "support": { + "issues": "https://github.com/egulias/EmailValidator/issues", + "source": "https://github.com/egulias/EmailValidator/tree/2.1.24" + }, + "funding": [ + { + "url": "https://github.com/egulias", + "type": "github" + } + ], + "time": "2020-11-14T15:56:27+00:00" }, { "name": "facade/flare-client-php", - "version": "1.3.6", + "version": "1.3.7", "source": { "type": "git", "url": "https://github.com/facade/flare-client-php.git", - "reference": "451fadf38e9f635e7f8e1f5b3cf5c9eb82f11799" + "reference": "fd688d3c06658f2b3b5f7bb19f051ee4ddf02492" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/facade/flare-client-php/zipball/451fadf38e9f635e7f8e1f5b3cf5c9eb82f11799", - "reference": "451fadf38e9f635e7f8e1f5b3cf5c9eb82f11799", + "url": "https://api.github.com/repos/facade/flare-client-php/zipball/fd688d3c06658f2b3b5f7bb19f051ee4ddf02492", + "reference": "fd688d3c06658f2b3b5f7bb19f051ee4ddf02492", "shasum": "" }, "require": { "facade/ignition-contracts": "~1.0", "illuminate/pipeline": "^5.5|^6.0|^7.0|^8.0", - "php": "^7.1", + "php": "^7.1|^8.0", "symfony/http-foundation": "^3.3|^4.1|^5.0", "symfony/mime": "^3.4|^4.0|^5.1", "symfony/var-dumper": "^3.4|^4.0|^5.0" @@ -909,26 +966,30 @@ "flare", "reporting" ], + "support": { + "issues": "https://github.com/facade/flare-client-php/issues", + "source": "https://github.com/facade/flare-client-php/tree/1.3.7" + }, "funding": [ { "url": "https://github.com/spatie", "type": "github" } ], - "time": "2020-09-18T06:35:11+00:00" + "time": "2020-10-21T16:02:39+00:00" }, { "name": "facade/ignition", - "version": "1.16.3", + "version": "1.16.4", "source": { "type": "git", "url": "https://github.com/facade/ignition.git", - "reference": "19674150bb46a4de0ba138c747f538fe7be11dbc" + "reference": "1da1705e7f6b24ed45af05461463228da424e14f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/facade/ignition/zipball/19674150bb46a4de0ba138c747f538fe7be11dbc", - "reference": "19674150bb46a4de0ba138c747f538fe7be11dbc", + "url": "https://api.github.com/repos/facade/ignition/zipball/1da1705e7f6b24ed45af05461463228da424e14f", + "reference": "1da1705e7f6b24ed45af05461463228da424e14f", "shasum": "" }, "require": { @@ -939,14 +1000,13 @@ "filp/whoops": "^2.4", "illuminate/support": "~5.5.0 || ~5.6.0 || ~5.7.0 || ~5.8.0 || ^6.0", "monolog/monolog": "^1.12 || ^2.0", - "php": "^7.1", + "php": "^7.1|^8.0", "scrivo/highlight.php": "^9.15", "symfony/console": "^3.4 || ^4.0", "symfony/var-dumper": "^3.4 || ^4.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^2.14", - "mockery/mockery": "^1.2", + "mockery/mockery": "~1.3.3|^1.4.2", "orchestra/testbench": "^3.5 || ^3.6 || ^3.7 || ^3.8 || ^4.0" }, "suggest": { @@ -986,7 +1046,13 @@ "laravel", "page" ], - "time": "2020-07-13T15:54:05+00:00" + "support": { + "docs": "https://flareapp.io/docs/ignition-for-laravel/introduction", + "forum": "https://twitter.com/flareappio", + "issues": "https://github.com/facade/ignition/issues", + "source": "https://github.com/facade/ignition" + }, + "time": "2020-10-30T13:40:01+00:00" }, { "name": "facade/ignition-contracts", @@ -1035,28 +1101,32 @@ "flare", "ignition" ], + "support": { + "issues": "https://github.com/facade/ignition-contracts/issues", + "source": "https://github.com/facade/ignition-contracts/tree/1.0.1" + }, "time": "2020-07-14T10:10:28+00:00" }, { "name": "fideloper/proxy", - "version": "4.4.0", + "version": "4.4.1", "source": { "type": "git", "url": "https://github.com/fideloper/TrustedProxy.git", - "reference": "9beebf48a1c344ed67c1d36bb1b8709db7c3c1a8" + "reference": "c073b2bd04d1c90e04dc1b787662b558dd65ade0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fideloper/TrustedProxy/zipball/9beebf48a1c344ed67c1d36bb1b8709db7c3c1a8", - "reference": "9beebf48a1c344ed67c1d36bb1b8709db7c3c1a8", + "url": "https://api.github.com/repos/fideloper/TrustedProxy/zipball/c073b2bd04d1c90e04dc1b787662b558dd65ade0", + "reference": "c073b2bd04d1c90e04dc1b787662b558dd65ade0", "shasum": "" }, "require": { - "illuminate/contracts": "^5.0|^6.0|^7.0|^8.0", + "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", + "illuminate/http": "^5.0|^6.0|^7.0|^8.0|^9.0", "mockery/mockery": "^1.0", "phpunit/phpunit": "^6.0" }, @@ -1089,29 +1159,33 @@ "proxy", "trusted proxy" ], - "time": "2020-06-23T01:36:47+00:00" + "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.7.3", + "version": "2.9.1", "source": { "type": "git", "url": "https://github.com/filp/whoops.git", - "reference": "5d5fe9bb3d656b514d455645b3addc5f7ba7714d" + "reference": "307fb34a5ab697461ec4c9db865b20ff2fd40771" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filp/whoops/zipball/5d5fe9bb3d656b514d455645b3addc5f7ba7714d", - "reference": "5d5fe9bb3d656b514d455645b3addc5f7ba7714d", + "url": "https://api.github.com/repos/filp/whoops/zipball/307fb34a5ab697461ec4c9db865b20ff2fd40771", + "reference": "307fb34a5ab697461ec4c9db865b20ff2fd40771", "shasum": "" }, "require": { - "php": "^5.5.9 || ^7.0", + "php": "^5.5.9 || ^7.0 || ^8.0", "psr/log": "^1.0.1" }, "require-dev": { "mockery/mockery": "^0.9 || ^1.0", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0", + "phpunit/phpunit": "^4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.8 || ^9.3.3", "symfony/var-dumper": "^2.6 || ^3.0 || ^4.0 || ^5.0" }, "suggest": { @@ -1121,7 +1195,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "2.7-dev" } }, "autoload": { @@ -1150,41 +1224,51 @@ "throwable", "whoops" ], - "time": "2020-06-14T09:00:00+00:00" + "support": { + "issues": "https://github.com/filp/whoops/issues", + "source": "https://github.com/filp/whoops/tree/2.9.1" + }, + "time": "2020-11-01T12:00:00+00:00" }, { "name": "guzzlehttp/guzzle", - "version": "6.5.5", + "version": "7.2.0", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "9d4290de1cfd701f38099ef7e183b64b4b7b0c5e" + "reference": "0aa74dfb41ae110835923ef10a9d803a22d50e79" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/9d4290de1cfd701f38099ef7e183b64b4b7b0c5e", - "reference": "9d4290de1cfd701f38099ef7e183b64b4b7b0c5e", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/0aa74dfb41ae110835923ef10a9d803a22d50e79", + "reference": "0aa74dfb41ae110835923ef10a9d803a22d50e79", "shasum": "" }, "require": { "ext-json": "*", - "guzzlehttp/promises": "^1.0", - "guzzlehttp/psr7": "^1.6.1", - "php": ">=5.5", - "symfony/polyfill-intl-idn": "^1.17.0" + "guzzlehttp/promises": "^1.4", + "guzzlehttp/psr7": "^1.7", + "php": "^7.2.5 || ^8.0", + "psr/http-client": "^1.0" + }, + "provide": { + "psr/http-client-implementation": "1.0" }, "require-dev": { "ext-curl": "*", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0", + "php-http/client-integration-tests": "^3.0", + "phpunit/phpunit": "^8.5.5 || ^9.3.5", "psr/log": "^1.1" }, "suggest": { + "ext-curl": "Required for CURL handler support", + "ext-intl": "Required for Internationalized Domain Name (IDN) support", "psr/log": "Required for using the Log middleware" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "6.5-dev" + "dev-master": "7.1-dev" } }, "autoload": { @@ -1204,6 +1288,11 @@ "name": "Michael Dowling", "email": "mtdowling@gmail.com", "homepage": "https://github.com/mtdowling" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" } ], "description": "Guzzle is a PHP HTTP client library", @@ -1214,30 +1303,54 @@ "framework", "http", "http client", + "psr-18", + "psr-7", "rest", "web service" ], - "time": "2020-06-16T21:01:06+00:00" + "support": { + "issues": "https://github.com/guzzle/guzzle/issues", + "source": "https://github.com/guzzle/guzzle/tree/7.2.0" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://github.com/alexeyshockov", + "type": "github" + }, + { + "url": "https://github.com/gmponos", + "type": "github" + } + ], + "time": "2020-10-10T11:47:56+00:00" }, { "name": "guzzlehttp/promises", - "version": "v1.3.1", + "version": "1.4.0", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646" + "reference": "60d379c243457e073cff02bc323a2a86cb355631" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646", - "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646", + "url": "https://api.github.com/repos/guzzle/promises/zipball/60d379c243457e073cff02bc323a2a86cb355631", + "reference": "60d379c243457e073cff02bc323a2a86cb355631", "shasum": "" }, "require": { - "php": ">=5.5.0" + "php": ">=5.5" }, "require-dev": { - "phpunit/phpunit": "^4.0" + "symfony/phpunit-bridge": "^4.4 || ^5.1" }, "type": "library", "extra": { @@ -1268,20 +1381,24 @@ "keywords": [ "promise" ], - "time": "2016-12-20T10:07:11+00:00" + "support": { + "issues": "https://github.com/guzzle/promises/issues", + "source": "https://github.com/guzzle/promises/tree/1.4.0" + }, + "time": "2020-09-30T07:37:28+00:00" }, { "name": "guzzlehttp/psr7", - "version": "1.6.1", + "version": "1.7.0", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "239400de7a173fe9901b9ac7c06497751f00727a" + "reference": "53330f47520498c0ae1f61f7e2c90f55690c06a3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/239400de7a173fe9901b9ac7c06497751f00727a", - "reference": "239400de7a173fe9901b9ac7c06497751f00727a", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/53330f47520498c0ae1f61f7e2c90f55690c06a3", + "reference": "53330f47520498c0ae1f61f7e2c90f55690c06a3", "shasum": "" }, "require": { @@ -1294,15 +1411,15 @@ }, "require-dev": { "ext-zlib": "*", - "phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.8" + "phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.8 || ^9.3.10" }, "suggest": { - "zendframework/zend-httphandlerrunner": "Emit PSR-7 responses" + "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.6-dev" + "dev-master": "1.7-dev" } }, "autoload": { @@ -1339,7 +1456,11 @@ "uri", "url" ], - "time": "2019-07-01T23:21:34+00:00" + "support": { + "issues": "https://github.com/guzzle/psr7/issues", + "source": "https://github.com/guzzle/psr7/tree/1.7.0" + }, + "time": "2020-09-30T07:37:11+00:00" }, { "name": "intervention/image", @@ -1409,6 +1530,10 @@ "thumbnail", "watermark" ], + "support": { + "issues": "https://github.com/Intervention/image/issues", + "source": "https://github.com/Intervention/image/tree/master" + }, "time": "2019-11-02T09:15:47+00:00" }, { @@ -1451,6 +1576,10 @@ "email": "jakub.onderka@gmail.com" } ], + "support": { + "issues": "https://github.com/JakubOnderka/PHP-Console-Color/issues", + "source": "https://github.com/JakubOnderka/PHP-Console-Color/tree/master" + }, "abandoned": "php-parallel-lint/php-console-color", "time": "2018-09-29T17:23:10+00:00" }, @@ -1498,6 +1627,10 @@ } ], "description": "Highlight PHP code in terminal", + "support": { + "issues": "https://github.com/JakubOnderka/PHP-Console-Highlighter/issues", + "source": "https://github.com/JakubOnderka/PHP-Console-Highlighter/tree/master" + }, "abandoned": "php-parallel-lint/php-console-highlighter", "time": "2018-09-29T18:48:56+00:00" }, @@ -1565,35 +1698,39 @@ "thumbnail", "wkhtmltopdf" ], + "support": { + "issues": "https://github.com/KnpLabs/snappy/issues", + "source": "https://github.com/KnpLabs/snappy/tree/master" + }, "time": "2020-01-20T08:30:30+00:00" }, { "name": "laravel/framework", - "version": "v6.18.40", + "version": "v6.20.7", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "e42450df0896b7130ccdb5290a114424e18887c9" + "reference": "bdc79701b567c5f8ed44d212dd4a261b8300b9c3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/e42450df0896b7130ccdb5290a114424e18887c9", - "reference": "e42450df0896b7130ccdb5290a114424e18887c9", + "url": "https://api.github.com/repos/laravel/framework/zipball/bdc79701b567c5f8ed44d212dd4a261b8300b9c3", + "reference": "bdc79701b567c5f8ed44d212dd4a261b8300b9c3", "shasum": "" }, "require": { "doctrine/inflector": "^1.4|^2.0", - "dragonmantank/cron-expression": "^2.0", + "dragonmantank/cron-expression": "^2.3.1", "egulias/email-validator": "^2.1.10", "ext-json": "*", "ext-mbstring": "*", "ext-openssl": "*", "league/commonmark": "^1.3", - "league/flysystem": "^1.0.34", + "league/flysystem": "^1.1", "monolog/monolog": "^1.12|^2.0", - "nesbot/carbon": "^2.0", - "opis/closure": "^3.1", - "php": "^7.2", + "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", @@ -1644,21 +1781,21 @@ "illuminate/view": "self.version" }, "require-dev": { - "aws/aws-sdk-php": "^3.0", + "aws/aws-sdk-php": "^3.155", "doctrine/dbal": "^2.6", - "filp/whoops": "^2.4", - "guzzlehttp/guzzle": "^6.3|^7.0", + "filp/whoops": "^2.8", + "guzzlehttp/guzzle": "^6.3.1|^7.0.1", "league/flysystem-cached-adapter": "^1.0", - "mockery/mockery": "^1.3.1", + "mockery/mockery": "~1.3.3|^1.4.2", "moontoast/math": "^1.1", - "orchestra/testbench-core": "^4.0", + "orchestra/testbench-core": "^4.8", "pda/pheanstalk": "^4.0", - "phpunit/phpunit": "^7.5.15|^8.4|^9.0", + "phpunit/phpunit": "^7.5.15|^8.4|^9.3.3", "predis/predis": "^1.1.1", "symfony/cache": "^4.3.4" }, "suggest": { - "aws/aws-sdk-php": "Required to use the SQS queue driver, DynamoDb failed job storage and SES mail driver (^3.0).", + "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).", "ext-ftp": "Required to use the Flysystem FTP driver.", "ext-gd": "Required to use Illuminate\\Http\\Testing\\FileFactory::image().", @@ -1666,9 +1803,9 @@ "ext-pcntl": "Required to use all features of the queue worker.", "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).", - "filp/whoops": "Required for friendly error pages in development (^2.4).", - "fzaninotto/faker": "Required to use the eloquent factory builder (^1.9.1).", - "guzzlehttp/guzzle": "Required to use the Mailgun mail driver and the ping methods on schedules (^6.0|^7.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).", "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).", @@ -1714,40 +1851,44 @@ "framework", "laravel" ], - "time": "2020-09-09T15:02:20+00:00" + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2020-12-08T15:31:27+00:00" }, { "name": "laravel/socialite", - "version": "v4.4.1", + "version": "v5.1.2", "source": { "type": "git", "url": "https://github.com/laravel/socialite.git", - "reference": "80951df0d93435b773aa00efe1fad6d5015fac75" + "reference": "19fc65ac28e0b4684a8735b14c1dc6f6ef5d62c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/socialite/zipball/80951df0d93435b773aa00efe1fad6d5015fac75", - "reference": "80951df0d93435b773aa00efe1fad6d5015fac75", + "url": "https://api.github.com/repos/laravel/socialite/zipball/19fc65ac28e0b4684a8735b14c1dc6f6ef5d62c7", + "reference": "19fc65ac28e0b4684a8735b14c1dc6f6ef5d62c7", "shasum": "" }, "require": { "ext-json": "*", "guzzlehttp/guzzle": "^6.0|^7.0", - "illuminate/http": "~5.7.0|~5.8.0|^6.0|^7.0", - "illuminate/support": "~5.7.0|~5.8.0|^6.0|^7.0", + "illuminate/http": "^6.0|^7.0|^8.0", + "illuminate/support": "^6.0|^7.0|^8.0", "league/oauth1-client": "^1.0", - "php": "^7.1.3" + "php": "^7.2|^8.0" }, "require-dev": { - "illuminate/contracts": "~5.7.0|~5.8.0|^6.0|^7.0", + "illuminate/contracts": "^6.0|^7.0", "mockery/mockery": "^1.0", - "orchestra/testbench": "^3.7|^3.8|^4.0|^5.0", - "phpunit/phpunit": "^7.0|^8.0" + "orchestra/testbench": "^4.0|^5.0|^6.0", + "phpunit/phpunit": "^8.0|^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.x-dev" + "dev-master": "5.x-dev" }, "laravel": { "providers": [ @@ -1779,20 +1920,24 @@ "laravel", "oauth" ], - "time": "2020-06-03T13:30:03+00:00" + "support": { + "issues": "https://github.com/laravel/socialite/issues", + "source": "https://github.com/laravel/socialite" + }, + "time": "2020-12-04T15:30:50+00:00" }, { "name": "league/commonmark", - "version": "1.5.5", + "version": "1.5.7", "source": { "type": "git", "url": "https://github.com/thephpleague/commonmark.git", - "reference": "45832dfed6007b984c0d40addfac48d403dc6432" + "reference": "11df9b36fd4f1d2b727a73bf14931d81373b9a54" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/45832dfed6007b984c0d40addfac48d403dc6432", - "reference": "45832dfed6007b984c0d40addfac48d403dc6432", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/11df9b36fd4f1d2b727a73bf14931d81373b9a54", + "reference": "11df9b36fd4f1d2b727a73bf14931d81373b9a54", "shasum": "" }, "require": { @@ -1848,6 +1993,12 @@ "md", "parser" ], + "support": { + "docs": "https://commonmark.thephpleague.com/", + "issues": "https://github.com/thephpleague/commonmark/issues", + "rss": "https://github.com/thephpleague/commonmark/releases.atom", + "source": "https://github.com/thephpleague/commonmark" + }, "funding": [ { "url": "https://enjoy.gitstore.app/repositories/thephpleague/commonmark", @@ -1874,32 +2025,33 @@ "type": "tidelift" } ], - "time": "2020-09-13T14:44:46+00:00" + "time": "2020-10-31T13:49:32+00:00" }, { "name": "league/flysystem", - "version": "1.0.70", + "version": "1.1.3", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem.git", - "reference": "585824702f534f8d3cf7fab7225e8466cc4b7493" + "reference": "9be3b16c877d477357c015cec057548cf9b2a14a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/585824702f534f8d3cf7fab7225e8466cc4b7493", - "reference": "585824702f534f8d3cf7fab7225e8466cc4b7493", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/9be3b16c877d477357c015cec057548cf9b2a14a", + "reference": "9be3b16c877d477357c015cec057548cf9b2a14a", "shasum": "" }, "require": { "ext-fileinfo": "*", - "php": ">=5.5.9" + "league/mime-type-detection": "^1.3", + "php": "^7.2.5 || ^8.0" }, "conflict": { "league/flysystem-sftp": "<1.0.6" }, "require-dev": { - "phpspec/phpspec": "^3.4 || ^4.0 || ^5.0 || ^6.0", - "phpunit/phpunit": "^5.7.26" + "phpspec/prophecy": "^1.11.1", + "phpunit/phpunit": "^8.5.8" }, "suggest": { "ext-fileinfo": "Required for MimeType", @@ -1958,26 +2110,30 @@ "sftp", "storage" ], + "support": { + "issues": "https://github.com/thephpleague/flysystem/issues", + "source": "https://github.com/thephpleague/flysystem/tree/1.x" + }, "funding": [ { "url": "https://offset.earth/frankdejonge", "type": "other" } ], - "time": "2020-07-26T07:20:36+00:00" + "time": "2020-08-23T07:39:11+00:00" }, { "name": "league/flysystem-aws-s3-v3", - "version": "1.0.28", + "version": "1.0.29", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem-aws-s3-v3.git", - "reference": "af7384a12f7cd7d08183390d930c9d0ec629c990" + "reference": "4e25cc0582a36a786c31115e419c6e40498f6972" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/af7384a12f7cd7d08183390d930c9d0ec629c990", - "reference": "af7384a12f7cd7d08183390d930c9d0ec629c990", + "url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/4e25cc0582a36a786c31115e419c6e40498f6972", + "reference": "4e25cc0582a36a786c31115e419c6e40498f6972", "shasum": "" }, "require": { @@ -2011,20 +2167,79 @@ } ], "description": "Flysystem adapter for the AWS S3 SDK v3.x", - "time": "2020-08-22T08:43:01+00:00" + "support": { + "issues": "https://github.com/thephpleague/flysystem-aws-s3-v3/issues", + "source": "https://github.com/thephpleague/flysystem-aws-s3-v3/tree/1.0.29" + }, + "time": "2020-10-08T18:58:37+00:00" }, { - "name": "league/oauth1-client", - "version": "v1.8.1", + "name": "league/mime-type-detection", + "version": "1.5.1", "source": { "type": "git", - "url": "https://github.com/thephpleague/oauth1-client.git", - "reference": "3a68155c3f27a91f4b66a2dc03996cd6f3281c9f" + "url": "https://github.com/thephpleague/mime-type-detection.git", + "reference": "353f66d7555d8a90781f6f5e7091932f9a4250aa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/oauth1-client/zipball/3a68155c3f27a91f4b66a2dc03996cd6f3281c9f", - "reference": "3a68155c3f27a91f4b66a2dc03996cd6f3281c9f", + "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/353f66d7555d8a90781f6f5e7091932f9a4250aa", + "reference": "353f66d7555d8a90781f6f5e7091932f9a4250aa", + "shasum": "" + }, + "require": { + "ext-fileinfo": "*", + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^0.12.36", + "phpunit/phpunit": "^8.5.8" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\MimeTypeDetection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "Mime-type detection for Flysystem", + "support": { + "issues": "https://github.com/thephpleague/mime-type-detection/issues", + "source": "https://github.com/thephpleague/mime-type-detection/tree/1.5.1" + }, + "funding": [ + { + "url": "https://github.com/frankdejonge", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/league/flysystem", + "type": "tidelift" + } + ], + "time": "2020-10-18T11:50:25+00:00" + }, + { + "name": "league/oauth1-client", + "version": "v1.8.2", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/oauth1-client.git", + "reference": "159c3d2bf27568f9af87d6c3f4bb616a251eb12b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/oauth1-client/zipball/159c3d2bf27568f9af87d6c3f4bb616a251eb12b", + "reference": "159c3d2bf27568f9af87d6c3f4bb616a251eb12b", "shasum": "" }, "require": { @@ -2082,20 +2297,24 @@ "tumblr", "twitter" ], - "time": "2020-09-04T11:07:03+00:00" + "support": { + "issues": "https://github.com/thephpleague/oauth1-client/issues", + "source": "https://github.com/thephpleague/oauth1-client/tree/v1.8.2" + }, + "time": "2020-09-28T09:39:08+00:00" }, { "name": "monolog/monolog", - "version": "2.1.1", + "version": "2.2.0", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "f9eee5cec93dfb313a38b6b288741e84e53f02d5" + "reference": "1cb1cde8e8dd0f70cc0fe51354a59acad9302084" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/f9eee5cec93dfb313a38b6b288741e84e53f02d5", - "reference": "f9eee5cec93dfb313a38b6b288741e84e53f02d5", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/1cb1cde8e8dd0f70cc0fe51354a59acad9302084", + "reference": "1cb1cde8e8dd0f70cc0fe51354a59acad9302084", "shasum": "" }, "require": { @@ -2108,16 +2327,17 @@ "require-dev": { "aws/aws-sdk-php": "^2.4.9 || ^3.0", "doctrine/couchdb": "~1.0@dev", - "elasticsearch/elasticsearch": "^6.0", + "elasticsearch/elasticsearch": "^7", "graylog2/gelf-php": "^1.4.2", + "mongodb/mongodb": "^1.8", "php-amqplib/php-amqplib": "~2.4", "php-console/php-console": "^3.1.3", - "php-parallel-lint/php-parallel-lint": "^1.0", "phpspec/prophecy": "^1.6.1", + "phpstan/phpstan": "^0.12.59", "phpunit/phpunit": "^8.5", "predis/predis": "^1.1", "rollbar/rollbar": "^1.3", - "ruflin/elastica": ">=0.90 <3.0", + "ruflin/elastica": ">=0.90 <7.0.1", "swiftmailer/swiftmailer": "^5.3|^6.0" }, "suggest": { @@ -2137,7 +2357,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.x-dev" + "dev-main": "2.x-dev" } }, "autoload": { @@ -2153,16 +2373,20 @@ { "name": "Jordi Boggiano", "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" + "homepage": "https://seld.be" } ], "description": "Sends your logs to files, sockets, inboxes, databases and various web services", - "homepage": "http://github.com/Seldaek/monolog", + "homepage": "https://github.com/Seldaek/monolog", "keywords": [ "log", "logging", "psr-3" ], + "support": { + "issues": "https://github.com/Seldaek/monolog/issues", + "source": "https://github.com/Seldaek/monolog/tree/2.2.0" + }, "funding": [ { "url": "https://github.com/Seldaek", @@ -2173,7 +2397,7 @@ "type": "tidelift" } ], - "time": "2020-07-23T08:41:23+00:00" + "time": "2020-12-14T13:15:25+00:00" }, { "name": "mtdowling/jmespath.php", @@ -2230,20 +2454,24 @@ "json", "jsonpath" ], + "support": { + "issues": "https://github.com/jmespath/jmespath.php/issues", + "source": "https://github.com/jmespath/jmespath.php/tree/2.6.0" + }, "time": "2020-07-31T21:01:56+00:00" }, { "name": "nesbot/carbon", - "version": "2.40.0", + "version": "2.42.0", "source": { "type": "git", "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "6c7646154181013ecd55e80c201b9fd873c6ee5d" + "reference": "d0463779663437392fe42ff339ebc0213bd55498" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/6c7646154181013ecd55e80c201b9fd873c6ee5d", - "reference": "6c7646154181013ecd55e80c201b9fd873c6ee5d", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/d0463779663437392fe42ff339ebc0213bd55498", + "reference": "d0463779663437392fe42ff339ebc0213bd55498", "shasum": "" }, "require": { @@ -2258,7 +2486,7 @@ "kylekatarnls/multi-tester": "^2.0", "phpmd/phpmd": "^2.9", "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^0.12.35", + "phpstan/phpstan": "^0.12.54", "phpunit/phpunit": "^7.5 || ^8.0", "squizlabs/php_codesniffer": "^3.4" }, @@ -2309,6 +2537,10 @@ "datetime", "time" ], + "support": { + "issues": "https://github.com/briannesbitt/Carbon/issues", + "source": "https://github.com/briannesbitt/Carbon" + }, "funding": [ { "url": "https://opencollective.com/Carbon", @@ -2319,33 +2551,31 @@ "type": "tidelift" } ], - "time": "2020-09-11T19:00:58+00:00" + "time": "2020-11-28T14:25:28+00:00" }, { "name": "nunomaduro/collision", - "version": "v3.0.1", + "version": "v3.1.0", "source": { "type": "git", "url": "https://github.com/nunomaduro/collision.git", - "reference": "af42d339fe2742295a54f6fdd42aaa6f8c4aca68" + "reference": "88b58b5bd9bdcc54756480fb3ce87234696544ee" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/collision/zipball/af42d339fe2742295a54f6fdd42aaa6f8c4aca68", - "reference": "af42d339fe2742295a54f6fdd42aaa6f8c4aca68", + "url": "https://api.github.com/repos/nunomaduro/collision/zipball/88b58b5bd9bdcc54756480fb3ce87234696544ee", + "reference": "88b58b5bd9bdcc54756480fb3ce87234696544ee", "shasum": "" }, "require": { "filp/whoops": "^2.1.4", "jakub-onderka/php-console-highlighter": "0.3.*|0.4.*", - "php": "^7.1", + "php": "^7.1 || ^8.0", "symfony/console": "~2.8|~3.3|~4.0" }, "require-dev": { - "laravel/framework": "5.8.*", - "nunomaduro/larastan": "^0.3.0", - "phpstan/phpstan": "^0.11", - "phpunit/phpunit": "~8.0" + "laravel/framework": "^6.0", + "phpunit/phpunit": "^8.0 || ^9.0" }, "type": "library", "extra": { @@ -2383,25 +2613,43 @@ "php", "symfony" ], - "time": "2019-03-07T21:35:13+00:00" + "support": { + "issues": "https://github.com/nunomaduro/collision/issues", + "source": "https://github.com/nunomaduro/collision" + }, + "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-29T16:05:21+00:00" }, { "name": "onelogin/php-saml", - "version": "3.4.1", + "version": "3.5.1", "source": { "type": "git", "url": "https://github.com/onelogin/php-saml.git", - "reference": "5fbf3486704ac9835b68184023ab54862c95f213" + "reference": "593aca859b67d607923fe50d8ad7315373f5b6dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/onelogin/php-saml/zipball/5fbf3486704ac9835b68184023ab54862c95f213", - "reference": "5fbf3486704ac9835b68184023ab54862c95f213", + "url": "https://api.github.com/repos/onelogin/php-saml/zipball/593aca859b67d607923fe50d8ad7315373f5b6dd", + "reference": "593aca859b67d607923fe50d8ad7315373f5b6dd", "shasum": "" }, "require": { "php": ">=5.4", - "robrichards/xmlseclibs": ">=3.0.4" + "robrichards/xmlseclibs": ">=3.1.1" }, "require-dev": { "pdepend/pdepend": "^2.5.0", @@ -2433,33 +2681,38 @@ "onelogin", "saml" ], - "time": "2019-11-25T17:30:07+00:00" + "support": { + "email": "sixto.garcia@onelogin.com", + "issues": "https://github.com/onelogin/php-saml/issues", + "source": "https://github.com/onelogin/php-saml/" + }, + "time": "2020-12-03T20:08:41+00:00" }, { "name": "opis/closure", - "version": "3.5.7", + "version": "3.6.1", "source": { "type": "git", "url": "https://github.com/opis/closure.git", - "reference": "4531e53afe2fc660403e76fb7644e95998bff7bf" + "reference": "943b5d70cc5ae7483f6aff6ff43d7e34592ca0f5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opis/closure/zipball/4531e53afe2fc660403e76fb7644e95998bff7bf", - "reference": "4531e53afe2fc660403e76fb7644e95998bff7bf", + "url": "https://api.github.com/repos/opis/closure/zipball/943b5d70cc5ae7483f6aff6ff43d7e34592ca0f5", + "reference": "943b5d70cc5ae7483f6aff6ff43d7e34592ca0f5", "shasum": "" }, "require": { - "php": "^5.4 || ^7.0" + "php": "^5.4 || ^7.0 || ^8.0" }, "require-dev": { "jeremeamia/superclosure": "^2.0", - "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.5.x-dev" + "dev-master": "3.6.x-dev" } }, "autoload": { @@ -2494,7 +2747,11 @@ "serialization", "serialize" ], - "time": "2020-09-06T17:02:15+00:00" + "support": { + "issues": "https://github.com/opis/closure/issues", + "source": "https://github.com/opis/closure/tree/3.6.1" + }, + "time": "2020-11-07T02:01:34+00:00" }, { "name": "paragonie/random_compat", @@ -2539,6 +2796,11 @@ "pseudorandom", "random" ], + "support": { + "email": "info@paragonie.com", + "issues": "https://github.com/paragonie/random_compat/issues", + "source": "https://github.com/paragonie/random_compat" + }, "time": "2018-07-02T15:55:56+00:00" }, { @@ -2576,6 +2838,10 @@ ], "description": "A library to read, parse, export and make subsets of different types of font files.", "homepage": "https://github.com/PhenX/php-font-lib", + "support": { + "issues": "https://github.com/PhenX/php-font-lib/issues", + "source": "https://github.com/PhenX/php-font-lib/tree/0.5.2" + }, "time": "2020-03-08T15:31:32+00:00" }, { @@ -2616,6 +2882,10 @@ ], "description": "A library to read, parse and export to PDF SVG files.", "homepage": "https://github.com/PhenX/php-svg-lib", + "support": { + "issues": "https://github.com/PhenX/php-svg-lib/issues", + "source": "https://github.com/PhenX/php-svg-lib/tree/master" + }, "time": "2019-09-11T20:02:13+00:00" }, { @@ -2671,6 +2941,10 @@ "php", "type" ], + "support": { + "issues": "https://github.com/schmittjoh/php-option/issues", + "source": "https://github.com/schmittjoh/php-option/tree/1.7.5" + }, "funding": [ { "url": "https://github.com/GrahamCampbell", @@ -2750,6 +3024,10 @@ "predis", "redis" ], + "support": { + "issues": "https://github.com/predis/predis/issues", + "source": "https://github.com/predis/predis/tree/v1.1.6" + }, "funding": [ { "url": "https://github.com/sponsors/tillkruss", @@ -2805,8 +3083,64 @@ "container-interop", "psr" ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/master" + }, "time": "2017-02-14T16:28:37+00:00" }, + { + "name": "psr/http-client", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-client.git", + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "support": { + "source": "https://github.com/php-fig/http-client/tree/master" + }, + "time": "2020-06-29T06:28:15+00:00" + }, { "name": "psr/http-message", "version": "1.0.1", @@ -2855,6 +3189,9 @@ "request", "response" ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/master" + }, "time": "2016-08-06T14:39:51+00:00" }, { @@ -2902,6 +3239,9 @@ "psr", "psr-3" ], + "support": { + "source": "https://github.com/php-fig/log/tree/1.1.3" + }, "time": "2020-03-23T09:12:05+00:00" }, { @@ -2950,6 +3290,9 @@ "psr-16", "simple-cache" ], + "support": { + "source": "https://github.com/php-fig/simple-cache/tree/master" + }, "time": "2017-10-23T01:57:42+00:00" }, { @@ -2990,6 +3333,10 @@ } ], "description": "A polyfill for getallheaders.", + "support": { + "issues": "https://github.com/ralouphie/getallheaders/issues", + "source": "https://github.com/ralouphie/getallheaders/tree/develop" + }, "time": "2019-03-08T08:55:37+00:00" }, { @@ -3077,6 +3424,12 @@ "identifier", "uuid" ], + "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" + }, "time": "2020-02-21T04:36:14+00:00" }, { @@ -3115,6 +3468,10 @@ "xml", "xmldsig" ], + "support": { + "issues": "https://github.com/robrichards/xmlseclibs/issues", + "source": "https://github.com/robrichards/xmlseclibs/tree/3.1.1" + }, "time": "2020-09-05T13:00:25+00:00" }, { @@ -3160,20 +3517,24 @@ "parser", "stylesheet" ], + "support": { + "issues": "https://github.com/sabberworm/PHP-CSS-Parser/issues", + "source": "https://github.com/sabberworm/PHP-CSS-Parser/tree/8.3.1" + }, "time": "2020-06-01T09:10:00+00:00" }, { "name": "scrivo/highlight.php", - "version": "v9.18.1.2", + "version": "v9.18.1.5", "source": { "type": "git", "url": "https://github.com/scrivo/highlight.php.git", - "reference": "efb6e445494a9458aa59b0af5edfa4bdcc6809d9" + "reference": "fa75a865928a4a5d49e5e77faca6bd2f2410baaf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/scrivo/highlight.php/zipball/efb6e445494a9458aa59b0af5edfa4bdcc6809d9", - "reference": "efb6e445494a9458aa59b0af5edfa4bdcc6809d9", + "url": "https://api.github.com/repos/scrivo/highlight.php/zipball/fa75a865928a4a5d49e5e77faca6bd2f2410baaf", + "reference": "fa75a865928a4a5d49e5e77faca6bd2f2410baaf", "shasum": "" }, "require": { @@ -3229,31 +3590,36 @@ "highlight.php", "syntax" ], + "support": { + "issues": "https://github.com/scrivo/highlight.php/issues", + "source": "https://github.com/scrivo/highlight.php" + }, "funding": [ { "url": "https://github.com/allejo", "type": "github" } ], - "time": "2020-08-27T03:24:44+00:00" + "time": "2020-11-22T06:07:40+00:00" }, { "name": "socialiteproviders/discord", - "version": "v2.0.2", + "version": "4.1.0", "source": { "type": "git", "url": "https://github.com/SocialiteProviders/Discord.git", - "reference": "e0cd8895f321943b36f533e7bf21ad29bcdece9a" + "reference": "34c62db509c9680e120982f9239db5ce905eb027" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/SocialiteProviders/Discord/zipball/e0cd8895f321943b36f533e7bf21ad29bcdece9a", - "reference": "e0cd8895f321943b36f533e7bf21ad29bcdece9a", + "url": "https://api.github.com/repos/SocialiteProviders/Discord/zipball/34c62db509c9680e120982f9239db5ce905eb027", + "reference": "34c62db509c9680e120982f9239db5ce905eb027", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0", - "socialiteproviders/manager": "~2.0 || ~3.0" + "ext-json": "*", + "php": "^7.2 || ^8.0", + "socialiteproviders/manager": "~4.0" }, "type": "library", "autoload": { @@ -3272,25 +3638,29 @@ } ], "description": "Discord OAuth2 Provider for Laravel Socialite", - "time": "2018-05-26T03:40:07+00:00" + "support": { + "source": "https://github.com/SocialiteProviders/Discord/tree/4.1.0" + }, + "time": "2020-12-01T23:10:59+00:00" }, { "name": "socialiteproviders/gitlab", - "version": "v3.1", + "version": "4.1.0", "source": { "type": "git", "url": "https://github.com/SocialiteProviders/GitLab.git", - "reference": "69e537f6192ca15483e98b8662495384f44299ca" + "reference": "a8f67d3b02c9ee8c70c25c6728417c0eddcbbb9d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/SocialiteProviders/GitLab/zipball/69e537f6192ca15483e98b8662495384f44299ca", - "reference": "69e537f6192ca15483e98b8662495384f44299ca", + "url": "https://api.github.com/repos/SocialiteProviders/GitLab/zipball/a8f67d3b02c9ee8c70c25c6728417c0eddcbbb9d", + "reference": "a8f67d3b02c9ee8c70c25c6728417c0eddcbbb9d", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0", - "socialiteproviders/manager": "~2.0 || ~3.0" + "ext-json": "*", + "php": "^7.2 || ^8.0", + "socialiteproviders/manager": "~4.0" }, "type": "library", "autoload": { @@ -3309,30 +3679,33 @@ } ], "description": "GitLab OAuth2 Provider for Laravel Socialite", - "time": "2018-06-27T05:10:32+00:00" + "support": { + "source": "https://github.com/SocialiteProviders/GitLab/tree/4.1.0" + }, + "time": "2020-12-01T23:10:59+00:00" }, { "name": "socialiteproviders/manager", - "version": "v3.6", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/SocialiteProviders/Manager.git", - "reference": "fc8dbcf0061f12bfe0cc347e9655af932860ad36" + "reference": "0f5e82af0404df0080bdc5c105cef936c1711524" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/SocialiteProviders/Manager/zipball/fc8dbcf0061f12bfe0cc347e9655af932860ad36", - "reference": "fc8dbcf0061f12bfe0cc347e9655af932860ad36", + "url": "https://api.github.com/repos/SocialiteProviders/Manager/zipball/0f5e82af0404df0080bdc5c105cef936c1711524", + "reference": "0f5e82af0404df0080bdc5c105cef936c1711524", "shasum": "" }, "require": { "illuminate/support": "^6.0|^7.0|^8.0", "laravel/socialite": "~4.0|~5.0", - "php": "^7.2" + "php": "^7.2 || ^8.0" }, "require-dev": { "mockery/mockery": "^1.2", - "phpunit/phpunit": "^8.0" + "phpunit/phpunit": "^9.0" }, "type": "library", "extra": { @@ -3372,26 +3745,30 @@ ], "description": "Easily add new or override built-in providers in Laravel Socialite.", "homepage": "https://socialiteproviders.com/", - "time": "2020-09-08T10:41:06+00:00" + "support": { + "issues": "https://github.com/SocialiteProviders/Manager/issues", + "source": "https://github.com/SocialiteProviders/Manager/tree/4.0.1" + }, + "time": "2020-12-01T23:09:06+00:00" }, { "name": "socialiteproviders/microsoft-azure", - "version": "v3.1.0", + "version": "4.1.0", "source": { "type": "git", "url": "https://github.com/SocialiteProviders/Microsoft-Azure.git", - "reference": "b22f4696cccecd6de902cf0bc923de7fc2e4608e" + "reference": "7808764f777a01df88be9ca6b14d683e50aaf88a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/SocialiteProviders/Microsoft-Azure/zipball/b22f4696cccecd6de902cf0bc923de7fc2e4608e", - "reference": "b22f4696cccecd6de902cf0bc923de7fc2e4608e", + "url": "https://api.github.com/repos/SocialiteProviders/Microsoft-Azure/zipball/7808764f777a01df88be9ca6b14d683e50aaf88a", + "reference": "7808764f777a01df88be9ca6b14d683e50aaf88a", "shasum": "" }, "require": { "ext-json": "*", - "php": "^5.6 || ^7.0", - "socialiteproviders/manager": "~2.0 || ~3.0" + "php": "^7.2 || ^8.0", + "socialiteproviders/manager": "~4.0" }, "type": "library", "autoload": { @@ -3410,26 +3787,29 @@ } ], "description": "Microsoft Azure OAuth2 Provider for Laravel Socialite", - "time": "2020-04-30T23:01:40+00:00" + "support": { + "source": "https://github.com/SocialiteProviders/Microsoft-Azure/tree/4.1.0" + }, + "time": "2020-12-01T23:10:59+00:00" }, { "name": "socialiteproviders/okta", - "version": "v1.1.0", + "version": "4.1.0", "source": { "type": "git", "url": "https://github.com/SocialiteProviders/Okta.git", - "reference": "7c2512f0872316b139e3eea1c50c9351747a57ea" + "reference": "60f88b8e8c88508889c61346af83290131b72fe7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/SocialiteProviders/Okta/zipball/7c2512f0872316b139e3eea1c50c9351747a57ea", - "reference": "7c2512f0872316b139e3eea1c50c9351747a57ea", + "url": "https://api.github.com/repos/SocialiteProviders/Okta/zipball/60f88b8e8c88508889c61346af83290131b72fe7", + "reference": "60f88b8e8c88508889c61346af83290131b72fe7", "shasum": "" }, "require": { "ext-json": "*", - "php": "^5.6 || ^7.0", - "socialiteproviders/manager": "~2.0 || ~3.0" + "php": "^7.2 || ^8.0", + "socialiteproviders/manager": "~4.0" }, "type": "library", "autoload": { @@ -3448,25 +3828,29 @@ } ], "description": "Okta OAuth2 Provider for Laravel Socialite", - "time": "2019-09-06T15:27:03+00:00" + "support": { + "source": "https://github.com/SocialiteProviders/Okta/tree/4.1.0" + }, + "time": "2020-12-01T23:10:59+00:00" }, { "name": "socialiteproviders/slack", - "version": "v3.1", + "version": "4.1.0", "source": { "type": "git", "url": "https://github.com/SocialiteProviders/Slack.git", - "reference": "d46826640fbeae8f34328d99c358404a1e1050a3" + "reference": "8efb25c71d98bedf4010a829d1e41ff9fe449bcc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/SocialiteProviders/Slack/zipball/d46826640fbeae8f34328d99c358404a1e1050a3", - "reference": "d46826640fbeae8f34328d99c358404a1e1050a3", + "url": "https://api.github.com/repos/SocialiteProviders/Slack/zipball/8efb25c71d98bedf4010a829d1e41ff9fe449bcc", + "reference": "8efb25c71d98bedf4010a829d1e41ff9fe449bcc", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0", - "socialiteproviders/manager": "~2.0 || ~3.0" + "ext-json": "*", + "php": "^7.2|^8.0", + "socialiteproviders/manager": "~4.0" }, "type": "library", "autoload": { @@ -3485,26 +3869,29 @@ } ], "description": "Slack OAuth2 Provider for Laravel Socialite", - "time": "2019-01-11T19:48:14+00:00" + "support": { + "source": "https://github.com/SocialiteProviders/Slack/tree/4.1.0" + }, + "time": "2020-11-26T17:57:15+00:00" }, { "name": "socialiteproviders/twitch", - "version": "v5.2.0", + "version": "5.3.1", "source": { "type": "git", "url": "https://github.com/SocialiteProviders/Twitch.git", - "reference": "9ee6fe196d7c28777139b3cde04cbd537cf7e652" + "reference": "7accf30ae7a3139b757b4ca8f34989c09a3dbee7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/SocialiteProviders/Twitch/zipball/9ee6fe196d7c28777139b3cde04cbd537cf7e652", - "reference": "9ee6fe196d7c28777139b3cde04cbd537cf7e652", + "url": "https://api.github.com/repos/SocialiteProviders/Twitch/zipball/7accf30ae7a3139b757b4ca8f34989c09a3dbee7", + "reference": "7accf30ae7a3139b757b4ca8f34989c09a3dbee7", "shasum": "" }, "require": { "ext-json": "*", - "php": "^5.6 || ^7.0", - "socialiteproviders/manager": "~2.0 || ~3.0" + "php": "^7.2 || ^8.0", + "socialiteproviders/manager": "~4.0" }, "type": "library", "autoload": { @@ -3523,7 +3910,10 @@ } ], "description": "Twitch OAuth2 Provider for Laravel Socialite", - "time": "2020-05-06T22:51:30+00:00" + "support": { + "source": "https://github.com/SocialiteProviders/Twitch/tree/5.3.1" + }, + "time": "2020-12-01T23:10:59+00:00" }, { "name": "ssddanbrown/htmldiff", @@ -3573,32 +3963,31 @@ }, { "name": "swiftmailer/swiftmailer", - "version": "v6.2.3", + "version": "v6.2.4", "source": { "type": "git", "url": "https://github.com/swiftmailer/swiftmailer.git", - "reference": "149cfdf118b169f7840bbe3ef0d4bc795d1780c9" + "reference": "56f0ab23f54c4ccbb0d5dcc67ff8552e0c98d59e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/149cfdf118b169f7840bbe3ef0d4bc795d1780c9", - "reference": "149cfdf118b169f7840bbe3ef0d4bc795d1780c9", + "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/56f0ab23f54c4ccbb0d5dcc67ff8552e0c98d59e", + "reference": "56f0ab23f54c4ccbb0d5dcc67ff8552e0c98d59e", "shasum": "" }, "require": { - "egulias/email-validator": "~2.0", + "egulias/email-validator": "^2.0", "php": ">=7.0.0", "symfony/polyfill-iconv": "^1.0", "symfony/polyfill-intl-idn": "^1.10", "symfony/polyfill-mbstring": "^1.0" }, "require-dev": { - "mockery/mockery": "~0.9.1", - "symfony/phpunit-bridge": "^3.4.19|^4.1.8" + "mockery/mockery": "^1.0", + "symfony/phpunit-bridge": "^4.4|^5.0" }, "suggest": { - "ext-intl": "Needed to support internationalized email addresses", - "true/punycode": "Needed to support internationalized email addresses, if ext-intl is not installed" + "ext-intl": "Needed to support internationalized email addresses" }, "type": "library", "extra": { @@ -3631,20 +4020,34 @@ "mail", "mailer" ], - "time": "2019-11-12T09:31:26+00:00" + "support": { + "issues": "https://github.com/swiftmailer/swiftmailer/issues", + "source": "https://github.com/swiftmailer/swiftmailer/tree/v6.2.4" + }, + "funding": [ + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/swiftmailer/swiftmailer", + "type": "tidelift" + } + ], + "time": "2020-12-08T18:02:06+00:00" }, { "name": "symfony/console", - "version": "v4.4.13", + "version": "v4.4.18", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "b39fd99b9297b67fb7633b7d8083957a97e1e727" + "reference": "12e071278e396cc3e1c149857337e9e192deca0b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/b39fd99b9297b67fb7633b7d8083957a97e1e727", - "reference": "b39fd99b9297b67fb7633b7d8083957a97e1e727", + "url": "https://api.github.com/repos/symfony/console/zipball/12e071278e396cc3e1c149857337e9e192deca0b", + "reference": "12e071278e396cc3e1c149857337e9e192deca0b", "shasum": "" }, "require": { @@ -3679,11 +4082,6 @@ "symfony/process": "" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.4-dev" - } - }, "autoload": { "psr-4": { "Symfony\\Component\\Console\\": "" @@ -3708,6 +4106,9 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/console/tree/v4.4.18" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -3722,31 +4123,26 @@ "type": "tidelift" } ], - "time": "2020-09-02T07:07:21+00:00" + "time": "2020-12-18T07:41:31+00:00" }, { "name": "symfony/css-selector", - "version": "v4.4.13", + "version": "v4.4.18", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "bf17dc9f6ce144e41f786c32435feea4d8e11dcc" + "reference": "74bd82e75da256ad20851af6ded07823332216c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/bf17dc9f6ce144e41f786c32435feea4d8e11dcc", - "reference": "bf17dc9f6ce144e41f786c32435feea4d8e11dcc", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/74bd82e75da256ad20851af6ded07823332216c7", + "reference": "74bd82e75da256ad20851af6ded07823332216c7", "shasum": "" }, "require": { "php": ">=7.1.3" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.4-dev" - } - }, "autoload": { "psr-4": { "Symfony\\Component\\CssSelector\\": "" @@ -3775,6 +4171,9 @@ ], "description": "Symfony CssSelector Component", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/css-selector/tree/v4.4.18" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -3789,20 +4188,20 @@ "type": "tidelift" } ], - "time": "2020-07-05T09:39:30+00:00" + "time": "2020-12-08T16:59:59+00:00" }, { "name": "symfony/debug", - "version": "v4.4.13", + "version": "v4.4.18", "source": { "type": "git", "url": "https://github.com/symfony/debug.git", - "reference": "aeb73aca16a8f1fe958230fe44e6cf4c84cbb85e" + "reference": "5dfc7825f3bfe9bb74b23d8b8ce0e0894e32b544" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/aeb73aca16a8f1fe958230fe44e6cf4c84cbb85e", - "reference": "aeb73aca16a8f1fe958230fe44e6cf4c84cbb85e", + "url": "https://api.github.com/repos/symfony/debug/zipball/5dfc7825f3bfe9bb74b23d8b8ce0e0894e32b544", + "reference": "5dfc7825f3bfe9bb74b23d8b8ce0e0894e32b544", "shasum": "" }, "require": { @@ -3817,11 +4216,6 @@ "symfony/http-kernel": "^3.4|^4.0|^5.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.4-dev" - } - }, "autoload": { "psr-4": { "Symfony\\Component\\Debug\\": "" @@ -3846,6 +4240,9 @@ ], "description": "Symfony Debug Component", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/debug/tree/v4.4.18" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -3860,20 +4257,87 @@ "type": "tidelift" } ], - "time": "2020-08-10T07:47:39+00:00" + "time": "2020-12-10T16:34:26+00:00" }, { - "name": "symfony/error-handler", - "version": "v4.4.13", + "name": "symfony/deprecation-contracts", + "version": "v2.2.0", "source": { "type": "git", - "url": "https://github.com/symfony/error-handler.git", - "reference": "2434fb32851f252e4f27691eee0b77c16198db62" + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "5fa56b4074d1ae755beb55617ddafe6f5d78f665" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/2434fb32851f252e4f27691eee0b77c16198db62", - "reference": "2434fb32851f252e4f27691eee0b77c16198db62", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/5fa56b4074d1ae755beb55617ddafe6f5d78f665", + "reference": "5fa56b4074d1ae755beb55617ddafe6f5d78f665", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.2-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "files": [ + "function.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": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/master" + }, + "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": "2020-09-07T11:33:47+00:00" + }, + { + "name": "symfony/error-handler", + "version": "v4.4.18", + "source": { + "type": "git", + "url": "https://github.com/symfony/error-handler.git", + "reference": "ef2f7ddd3b9177bbf8ff2ecd8d0e970ed48da0c3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/ef2f7ddd3b9177bbf8ff2ecd8d0e970ed48da0c3", + "reference": "ef2f7ddd3b9177bbf8ff2ecd8d0e970ed48da0c3", "shasum": "" }, "require": { @@ -3888,11 +4352,6 @@ "symfony/serializer": "^4.4|^5.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.4-dev" - } - }, "autoload": { "psr-4": { "Symfony\\Component\\ErrorHandler\\": "" @@ -3917,6 +4376,9 @@ ], "description": "Symfony ErrorHandler Component", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/error-handler/tree/v4.4.18" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -3931,20 +4393,20 @@ "type": "tidelift" } ], - "time": "2020-08-17T09:56:45+00:00" + "time": "2020-12-09T11:15:38+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v4.4.13", + "version": "v4.4.18", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "3e8ea5ccddd00556b86d69d42f99f1061a704030" + "reference": "5d4c874b0eb1c32d40328a09dbc37307a5a910b0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/3e8ea5ccddd00556b86d69d42f99f1061a704030", - "reference": "3e8ea5ccddd00556b86d69d42f99f1061a704030", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/5d4c874b0eb1c32d40328a09dbc37307a5a910b0", + "reference": "5d4c874b0eb1c32d40328a09dbc37307a5a910b0", "shasum": "" }, "require": { @@ -3962,6 +4424,7 @@ "psr/log": "~1.0", "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/service-contracts": "^1.1|^2", @@ -3972,11 +4435,6 @@ "symfony/http-kernel": "" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.4-dev" - } - }, "autoload": { "psr-4": { "Symfony\\Component\\EventDispatcher\\": "" @@ -4001,6 +4459,9 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/event-dispatcher/tree/v4.4.18" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -4015,7 +4476,7 @@ "type": "tidelift" } ], - "time": "2020-08-13T14:18:44+00:00" + "time": "2020-12-18T07:41:31+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -4077,6 +4538,9 @@ "interoperability", "standards" ], + "support": { + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v1.1.9" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -4095,27 +4559,22 @@ }, { "name": "symfony/finder", - "version": "v4.4.13", + "version": "v4.4.18", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "2a78590b2c7e3de5c429628457c47541c58db9c7" + "reference": "ebd0965f2dc2d4e0f11487c16fbb041e50b5c09b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/2a78590b2c7e3de5c429628457c47541c58db9c7", - "reference": "2a78590b2c7e3de5c429628457c47541c58db9c7", + "url": "https://api.github.com/repos/symfony/finder/zipball/ebd0965f2dc2d4e0f11487c16fbb041e50b5c09b", + "reference": "ebd0965f2dc2d4e0f11487c16fbb041e50b5c09b", "shasum": "" }, "require": { "php": ">=7.1.3" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.4-dev" - } - }, "autoload": { "psr-4": { "Symfony\\Component\\Finder\\": "" @@ -4140,6 +4599,9 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/finder/tree/v4.4.18" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -4154,37 +4616,112 @@ "type": "tidelift" } ], - "time": "2020-08-17T09:56:45+00:00" + "time": "2020-12-08T16:59:59+00:00" }, { - "name": "symfony/http-foundation", - "version": "v4.4.13", + "name": "symfony/http-client-contracts", + "version": "v2.3.1", "source": { "type": "git", - "url": "https://github.com/symfony/http-foundation.git", - "reference": "e3e5a62a6631a461954d471e7206e3750dbe8ee1" + "url": "https://github.com/symfony/http-client-contracts.git", + "reference": "41db680a15018f9c1d4b23516059633ce280ca33" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/e3e5a62a6631a461954d471e7206e3750dbe8ee1", - "reference": "e3e5a62a6631a461954d471e7206e3750dbe8ee1", + "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/41db680a15018f9c1d4b23516059633ce280ca33", + "reference": "41db680a15018f9c1d4b23516059633ce280ca33", + "shasum": "" + }, + "require": { + "php": ">=7.2.5" + }, + "suggest": { + "symfony/http-client-implementation": "" + }, + "type": "library", + "extra": { + "branch-version": "2.3", + "branch-alias": { + "dev-main": "2.3-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\HttpClient\\": "" + } + }, + "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": "Generic abstractions related to HTTP clients", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/http-client-contracts/tree/v2.3.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": "2020-10-14T17:08:19+00:00" + }, + { + "name": "symfony/http-foundation", + "version": "v4.4.18", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-foundation.git", + "reference": "5ebda66b51612516bf338d5f87da2f37ff74cf34" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/5ebda66b51612516bf338d5f87da2f37ff74cf34", + "reference": "5ebda66b51612516bf338d5f87da2f37ff74cf34", "shasum": "" }, "require": { "php": ">=7.1.3", "symfony/mime": "^4.3|^5.0", - "symfony/polyfill-mbstring": "~1.1" + "symfony/polyfill-mbstring": "~1.1", + "symfony/polyfill-php80": "^1.15" }, "require-dev": { "predis/predis": "~1.0", "symfony/expression-language": "^3.4|^4.0|^5.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.4-dev" - } - }, "autoload": { "psr-4": { "Symfony\\Component\\HttpFoundation\\": "" @@ -4209,6 +4746,9 @@ ], "description": "Symfony HttpFoundation Component", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/http-foundation/tree/v4.4.18" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -4223,20 +4763,20 @@ "type": "tidelift" } ], - "time": "2020-08-17T07:39:58+00:00" + "time": "2020-12-18T07:41:31+00:00" }, { "name": "symfony/http-kernel", - "version": "v4.4.13", + "version": "v4.4.18", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "2bb7b90ecdc79813c0bf237b7ff20e79062b5188" + "reference": "eaff9a43e74513508867ecfa66ef94fbb96ab128" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/2bb7b90ecdc79813c0bf237b7ff20e79062b5188", - "reference": "2bb7b90ecdc79813c0bf237b7ff20e79062b5188", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/eaff9a43e74513508867ecfa66ef94fbb96ab128", + "reference": "eaff9a43e74513508867ecfa66ef94fbb96ab128", "shasum": "" }, "require": { @@ -4244,6 +4784,7 @@ "psr/log": "~1.0", "symfony/error-handler": "^4.4", "symfony/event-dispatcher": "^4.4", + "symfony/http-client-contracts": "^1.1|^2", "symfony/http-foundation": "^4.4|^5.0", "symfony/polyfill-ctype": "^1.8", "symfony/polyfill-php73": "^1.9", @@ -4285,11 +4826,6 @@ "symfony/dependency-injection": "" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.4-dev" - } - }, "autoload": { "psr-4": { "Symfony\\Component\\HttpKernel\\": "" @@ -4314,6 +4850,9 @@ ], "description": "Symfony HttpKernel Component", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/http-kernel/tree/v4.4.18" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -4328,40 +4867,41 @@ "type": "tidelift" } ], - "time": "2020-09-02T08:09:29+00:00" + "time": "2020-12-18T13:32:33+00:00" }, { "name": "symfony/mime", - "version": "v4.4.13", + "version": "v5.2.1", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "50ad671306d3d3ffb888d95b4fb1859496831e3a" + "reference": "de97005aef7426ba008c46ba840fc301df577ada" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/50ad671306d3d3ffb888d95b4fb1859496831e3a", - "reference": "50ad671306d3d3ffb888d95b4fb1859496831e3a", + "url": "https://api.github.com/repos/symfony/mime/zipball/de97005aef7426ba008c46ba840fc301df577ada", + "reference": "de97005aef7426ba008c46ba840fc301df577ada", "shasum": "" }, "require": { - "php": ">=7.1.3", + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1", "symfony/polyfill-intl-idn": "^1.10", - "symfony/polyfill-mbstring": "^1.0" + "symfony/polyfill-mbstring": "^1.0", + "symfony/polyfill-php80": "^1.15" }, "conflict": { "symfony/mailer": "<4.4" }, "require-dev": { "egulias/email-validator": "^2.1.10", - "symfony/dependency-injection": "^3.4|^4.1|^5.0" + "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/property-access": "^4.4|^5.1", + "symfony/property-info": "^4.4|^5.1", + "symfony/serializer": "^5.2" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.4-dev" - } - }, "autoload": { "psr-4": { "Symfony\\Component\\Mime\\": "" @@ -4390,6 +4930,9 @@ "mime", "mime-type" ], + "support": { + "source": "https://github.com/symfony/mime/tree/v5.2.1" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -4404,24 +4947,24 @@ "type": "tidelift" } ], - "time": "2020-08-17T09:56:45+00:00" + "time": "2020-12-09T18:54:12+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.18.1", + "version": "v1.20.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "1c302646f6efc070cd46856e600e5e0684d6b454" + "reference": "f4ba089a5b6366e453971d3aad5fe8e897b37f41" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/1c302646f6efc070cd46856e600e5e0684d6b454", - "reference": "1c302646f6efc070cd46856e600e5e0684d6b454", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/f4ba089a5b6366e453971d3aad5fe8e897b37f41", + "reference": "f4ba089a5b6366e453971d3aad5fe8e897b37f41", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=7.1" }, "suggest": { "ext-ctype": "For best performance" @@ -4429,7 +4972,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.18-dev" + "dev-main": "1.20-dev" }, "thanks": { "name": "symfony/polyfill", @@ -4466,6 +5009,9 @@ "polyfill", "portable" ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.20.0" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -4480,24 +5026,24 @@ "type": "tidelift" } ], - "time": "2020-07-14T12:35:20+00:00" + "time": "2020-10-23T14:02:19+00:00" }, { "name": "symfony/polyfill-iconv", - "version": "v1.18.1", + "version": "v1.20.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-iconv.git", - "reference": "6c2f78eb8f5ab8eaea98f6d414a5915f2e0fce36" + "reference": "c536646fdb4f29104dd26effc2fdcb9a5b085024" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/6c2f78eb8f5ab8eaea98f6d414a5915f2e0fce36", - "reference": "6c2f78eb8f5ab8eaea98f6d414a5915f2e0fce36", + "url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/c536646fdb4f29104dd26effc2fdcb9a5b085024", + "reference": "c536646fdb4f29104dd26effc2fdcb9a5b085024", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=7.1" }, "suggest": { "ext-iconv": "For best performance" @@ -4505,7 +5051,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.18-dev" + "dev-main": "1.20-dev" }, "thanks": { "name": "symfony/polyfill", @@ -4543,6 +5089,9 @@ "portable", "shim" ], + "support": { + "source": "https://github.com/symfony/polyfill-iconv/tree/v1.20.0" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -4557,26 +5106,25 @@ "type": "tidelift" } ], - "time": "2020-07-14T12:35:20+00:00" + "time": "2020-10-23T14:02:19+00:00" }, { "name": "symfony/polyfill-intl-idn", - "version": "v1.18.1", + "version": "v1.20.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-idn.git", - "reference": "5dcab1bc7146cf8c1beaa4502a3d9be344334251" + "reference": "3b75acd829741c768bc8b1f84eb33265e7cc5117" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/5dcab1bc7146cf8c1beaa4502a3d9be344334251", - "reference": "5dcab1bc7146cf8c1beaa4502a3d9be344334251", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/3b75acd829741c768bc8b1f84eb33265e7cc5117", + "reference": "3b75acd829741c768bc8b1f84eb33265e7cc5117", "shasum": "" }, "require": { - "php": ">=5.3.3", + "php": ">=7.1", "symfony/polyfill-intl-normalizer": "^1.10", - "symfony/polyfill-php70": "^1.10", "symfony/polyfill-php72": "^1.10" }, "suggest": { @@ -4585,7 +5133,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.18-dev" + "dev-main": "1.20-dev" }, "thanks": { "name": "symfony/polyfill", @@ -4628,6 +5176,9 @@ "portable", "shim" ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.20.0" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -4642,24 +5193,24 @@ "type": "tidelift" } ], - "time": "2020-08-04T06:02:08+00:00" + "time": "2020-10-23T14:02:19+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.18.1", + "version": "v1.20.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "37078a8dd4a2a1e9ab0231af7c6cb671b2ed5a7e" + "reference": "727d1096295d807c309fb01a851577302394c897" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/37078a8dd4a2a1e9ab0231af7c6cb671b2ed5a7e", - "reference": "37078a8dd4a2a1e9ab0231af7c6cb671b2ed5a7e", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/727d1096295d807c309fb01a851577302394c897", + "reference": "727d1096295d807c309fb01a851577302394c897", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=7.1" }, "suggest": { "ext-intl": "For best performance" @@ -4667,7 +5218,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.18-dev" + "dev-main": "1.20-dev" }, "thanks": { "name": "symfony/polyfill", @@ -4709,6 +5260,9 @@ "portable", "shim" ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.20.0" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -4723,24 +5277,24 @@ "type": "tidelift" } ], - "time": "2020-07-14T12:35:20+00:00" + "time": "2020-10-23T14:02:19+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.18.1", + "version": "v1.20.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "a6977d63bf9a0ad4c65cd352709e230876f9904a" + "reference": "39d483bdf39be819deabf04ec872eb0b2410b531" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/a6977d63bf9a0ad4c65cd352709e230876f9904a", - "reference": "a6977d63bf9a0ad4c65cd352709e230876f9904a", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/39d483bdf39be819deabf04ec872eb0b2410b531", + "reference": "39d483bdf39be819deabf04ec872eb0b2410b531", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=7.1" }, "suggest": { "ext-mbstring": "For best performance" @@ -4748,7 +5302,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.18-dev" + "dev-main": "1.20-dev" }, "thanks": { "name": "symfony/polyfill", @@ -4786,6 +5340,9 @@ "portable", "shim" ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.20.0" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -4800,106 +5357,29 @@ "type": "tidelift" } ], - "time": "2020-07-14T12:35:20+00:00" - }, - { - "name": "symfony/polyfill-php70", - "version": "v1.18.1", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php70.git", - "reference": "0dd93f2c578bdc9c72697eaa5f1dd25644e618d3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/0dd93f2c578bdc9c72697eaa5f1dd25644e618d3", - "reference": "0dd93f2c578bdc9c72697eaa5f1dd25644e618d3", - "shasum": "" - }, - "require": { - "paragonie/random_compat": "~1.0|~2.0|~9.99", - "php": ">=5.3.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.18-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Php70\\": "" - }, - "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 7.0+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "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": "2020-07-14T12:35:20+00:00" + "time": "2020-10-23T14:02:19+00:00" }, { "name": "symfony/polyfill-php72", - "version": "v1.18.1", + "version": "v1.20.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "639447d008615574653fb3bc60d1986d7172eaae" + "reference": "cede45fcdfabdd6043b3592e83678e42ec69e930" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/639447d008615574653fb3bc60d1986d7172eaae", - "reference": "639447d008615574653fb3bc60d1986d7172eaae", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/cede45fcdfabdd6043b3592e83678e42ec69e930", + "reference": "cede45fcdfabdd6043b3592e83678e42ec69e930", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=7.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.18-dev" + "dev-main": "1.20-dev" }, "thanks": { "name": "symfony/polyfill", @@ -4936,6 +5416,9 @@ "portable", "shim" ], + "support": { + "source": "https://github.com/symfony/polyfill-php72/tree/v1.20.0" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -4950,29 +5433,29 @@ "type": "tidelift" } ], - "time": "2020-07-14T12:35:20+00:00" + "time": "2020-10-23T14:02:19+00:00" }, { "name": "symfony/polyfill-php73", - "version": "v1.18.1", + "version": "v1.20.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "fffa1a52a023e782cdcc221d781fe1ec8f87fcca" + "reference": "8ff431c517be11c78c48a39a66d37431e26a6bed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/fffa1a52a023e782cdcc221d781fe1ec8f87fcca", - "reference": "fffa1a52a023e782cdcc221d781fe1ec8f87fcca", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/8ff431c517be11c78c48a39a66d37431e26a6bed", + "reference": "8ff431c517be11c78c48a39a66d37431e26a6bed", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=7.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.18-dev" + "dev-main": "1.20-dev" }, "thanks": { "name": "symfony/polyfill", @@ -5012,6 +5495,9 @@ "portable", "shim" ], + "support": { + "source": "https://github.com/symfony/polyfill-php73/tree/v1.20.0" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -5026,29 +5512,29 @@ "type": "tidelift" } ], - "time": "2020-07-14T12:35:20+00:00" + "time": "2020-10-23T14:02:19+00:00" }, { "name": "symfony/polyfill-php80", - "version": "v1.18.1", + "version": "v1.20.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "d87d5766cbf48d72388a9f6b85f280c8ad51f981" + "reference": "e70aa8b064c5b72d3df2abd5ab1e90464ad009de" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/d87d5766cbf48d72388a9f6b85f280c8ad51f981", - "reference": "d87d5766cbf48d72388a9f6b85f280c8ad51f981", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/e70aa8b064c5b72d3df2abd5ab1e90464ad009de", + "reference": "e70aa8b064c5b72d3df2abd5ab1e90464ad009de", "shasum": "" }, "require": { - "php": ">=7.0.8" + "php": ">=7.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.18-dev" + "dev-main": "1.20-dev" }, "thanks": { "name": "symfony/polyfill", @@ -5092,6 +5578,9 @@ "portable", "shim" ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.20.0" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -5106,31 +5595,26 @@ "type": "tidelift" } ], - "time": "2020-07-14T12:35:20+00:00" + "time": "2020-10-23T14:02:19+00:00" }, { "name": "symfony/process", - "version": "v4.4.13", + "version": "v4.4.18", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "65e70bab62f3da7089a8d4591fb23fbacacb3479" + "reference": "075316ff72233ce3d04a9743414292e834f2cb4a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/65e70bab62f3da7089a8d4591fb23fbacacb3479", - "reference": "65e70bab62f3da7089a8d4591fb23fbacacb3479", + "url": "https://api.github.com/repos/symfony/process/zipball/075316ff72233ce3d04a9743414292e834f2cb4a", + "reference": "075316ff72233ce3d04a9743414292e834f2cb4a", "shasum": "" }, "require": { "php": ">=7.1.3" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.4-dev" - } - }, "autoload": { "psr-4": { "Symfony\\Component\\Process\\": "" @@ -5155,6 +5639,9 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/process/tree/v4.4.18" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -5169,20 +5656,20 @@ "type": "tidelift" } ], - "time": "2020-07-23T08:31:43+00:00" + "time": "2020-12-08T16:59:59+00:00" }, { "name": "symfony/routing", - "version": "v4.4.13", + "version": "v4.4.18", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "e3387963565da9bae51d1d3ab8041646cc93bd04" + "reference": "80b042c20b035818daec844723e23b9825134ba0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/e3387963565da9bae51d1d3ab8041646cc93bd04", - "reference": "e3387963565da9bae51d1d3ab8041646cc93bd04", + "url": "https://api.github.com/repos/symfony/routing/zipball/80b042c20b035818daec844723e23b9825134ba0", + "reference": "80b042c20b035818daec844723e23b9825134ba0", "shasum": "" }, "require": { @@ -5210,11 +5697,6 @@ "symfony/yaml": "For using the YAML loader" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.4-dev" - } - }, "autoload": { "psr-4": { "Symfony\\Component\\Routing\\": "" @@ -5245,6 +5727,9 @@ "uri", "url" ], + "support": { + "source": "https://github.com/symfony/routing/tree/v4.4.18" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -5259,24 +5744,24 @@ "type": "tidelift" } ], - "time": "2020-08-10T07:27:51+00:00" + "time": "2020-12-08T16:59:59+00:00" }, { "name": "symfony/service-contracts", - "version": "v1.1.9", + "version": "v2.2.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "b776d18b303a39f56c63747bcb977ad4b27aca26" + "reference": "d15da7ba4957ffb8f1747218be9e1a121fd298a1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/b776d18b303a39f56c63747bcb977ad4b27aca26", - "reference": "b776d18b303a39f56c63747bcb977ad4b27aca26", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/d15da7ba4957ffb8f1747218be9e1a121fd298a1", + "reference": "d15da7ba4957ffb8f1747218be9e1a121fd298a1", "shasum": "" }, "require": { - "php": ">=7.1.3", + "php": ">=7.2.5", "psr/container": "^1.0" }, "suggest": { @@ -5285,7 +5770,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-master": "2.2-dev" }, "thanks": { "name": "symfony/contracts", @@ -5321,6 +5806,9 @@ "interoperability", "standards" ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/master" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -5335,20 +5823,20 @@ "type": "tidelift" } ], - "time": "2020-07-06T13:19:58+00:00" + "time": "2020-09-07T11:33:47+00:00" }, { "name": "symfony/translation", - "version": "v4.4.13", + "version": "v4.4.18", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "700e6e50174b0cdcf0fa232773bec5c314680575" + "reference": "c1001b7d75b3136648f94b245588209d881c6939" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/700e6e50174b0cdcf0fa232773bec5c314680575", - "reference": "700e6e50174b0cdcf0fa232773bec5c314680575", + "url": "https://api.github.com/repos/symfony/translation/zipball/c1001b7d75b3136648f94b245588209d881c6939", + "reference": "c1001b7d75b3136648f94b245588209d881c6939", "shasum": "" }, "require": { @@ -5382,11 +5870,6 @@ "symfony/yaml": "" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.4-dev" - } - }, "autoload": { "psr-4": { "Symfony\\Component\\Translation\\": "" @@ -5411,6 +5894,9 @@ ], "description": "Symfony Translation Component", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/translation/tree/v4.4.18" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -5425,24 +5911,24 @@ "type": "tidelift" } ], - "time": "2020-08-17T09:56:45+00:00" + "time": "2020-12-08T16:59:59+00:00" }, { "name": "symfony/translation-contracts", - "version": "v1.1.10", + "version": "v2.3.0", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "84180a25fad31e23bebd26ca09d89464f082cacc" + "reference": "e2eaa60b558f26a4b0354e1bbb25636efaaad105" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/84180a25fad31e23bebd26ca09d89464f082cacc", - "reference": "84180a25fad31e23bebd26ca09d89464f082cacc", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/e2eaa60b558f26a4b0354e1bbb25636efaaad105", + "reference": "e2eaa60b558f26a4b0354e1bbb25636efaaad105", "shasum": "" }, "require": { - "php": ">=7.1.3" + "php": ">=7.2.5" }, "suggest": { "symfony/translation-implementation": "" @@ -5450,7 +5936,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-master": "2.3-dev" }, "thanks": { "name": "symfony/contracts", @@ -5486,6 +5972,9 @@ "interoperability", "standards" ], + "support": { + "source": "https://github.com/symfony/translation-contracts/tree/v2.3.0" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -5500,20 +5989,20 @@ "type": "tidelift" } ], - "time": "2020-09-02T16:08:58+00:00" + "time": "2020-09-28T13:05:58+00:00" }, { "name": "symfony/var-dumper", - "version": "v4.4.13", + "version": "v4.4.18", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "1bef32329f3166486ab7cb88599cae4875632b99" + "reference": "4f31364bbc8177f2a6dbc125ac3851634ebe2a03" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/1bef32329f3166486ab7cb88599cae4875632b99", - "reference": "1bef32329f3166486ab7cb88599cae4875632b99", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/4f31364bbc8177f2a6dbc125ac3851634ebe2a03", + "reference": "4f31364bbc8177f2a6dbc125ac3851634ebe2a03", "shasum": "" }, "require": { @@ -5541,11 +6030,6 @@ "Resources/bin/var-dump-server" ], "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.4-dev" - } - }, "autoload": { "files": [ "Resources/functions/dump.php" @@ -5577,6 +6061,9 @@ "debug", "dump" ], + "support": { + "source": "https://github.com/symfony/var-dumper/tree/v4.4.18" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -5591,7 +6078,7 @@ "type": "tidelift" } ], - "time": "2020-08-17T07:31:35+00:00" + "time": "2020-12-08T16:59:59+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", @@ -5640,6 +6127,10 @@ ], "description": "CssToInlineStyles is a class that enables you to convert HTML-pages/files into HTML-pages/files with inline styles. This is very useful when you're sending emails.", "homepage": "https://github.com/tijsverkoyen/CssToInlineStyles", + "support": { + "issues": "https://github.com/tijsverkoyen/CssToInlineStyles/issues", + "source": "https://github.com/tijsverkoyen/CssToInlineStyles/tree/2.2.3" + }, "time": "2020-07-13T06:12:54+00:00" }, { @@ -5703,6 +6194,10 @@ "env", "environment" ], + "support": { + "issues": "https://github.com/vlucas/phpdotenv/issues", + "source": "https://github.com/vlucas/phpdotenv/tree/v3.6.7" + }, "funding": [ { "url": "https://github.com/GrahamCampbell", @@ -5785,6 +6280,10 @@ "profiler", "webprofiler" ], + "support": { + "issues": "https://github.com/barryvdh/laravel-debugbar/issues", + "source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.5.1" + }, "funding": [ { "url": "https://github.com/barryvdh", @@ -5795,21 +6294,21 @@ }, { "name": "barryvdh/laravel-ide-helper", - "version": "v2.8.1", + "version": "v2.8.2", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-ide-helper.git", - "reference": "affa55122f83575888d4ebf1728992686e8223de" + "reference": "5515cabea39b9cf55f98980d0f269dc9d85cfcca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/affa55122f83575888d4ebf1728992686e8223de", - "reference": "affa55122f83575888d4ebf1728992686e8223de", + "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.0@dev", + "composer/composer": "^1.6 || ^2", "doctrine/dbal": "~2.3", "ext-json": "*", "illuminate/console": "^6 || ^7 || ^8", @@ -5819,13 +6318,14 @@ "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", + "mockery/mockery": "^1.3.3", "orchestra/testbench": "^4 || ^5 || ^6", "phpunit/phpunit": "^8.5 || ^9", - "spatie/phpunit-snapshot-assertions": "^1.4 || ^2.2 || ^3", + "spatie/phpunit-snapshot-assertions": "^1.4 || ^2.2 || ^3 || ^4", "vimeo/psalm": "^3.12" }, "type": "library", @@ -5866,13 +6366,17 @@ "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-09-07T07:36:37+00:00" + "time": "2020-12-06T08:55:05+00:00" }, { "name": "barryvdh/reflection-docblock", @@ -5921,6 +6425,9 @@ "email": "mike.vanriel@naenius.com" } ], + "support": { + "source": "https://github.com/barryvdh/ReflectionDocBlock/tree/v2.0.6" + }, "time": "2018-12-13T10:34:14+00:00" }, { @@ -5977,6 +6484,11 @@ "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.8" + }, "funding": [ { "url": "https://packagist.com", @@ -5995,39 +6507,37 @@ }, { "name": "composer/composer", - "version": "1.10.13", + "version": "2.0.8", "source": { "type": "git", "url": "https://github.com/composer/composer.git", - "reference": "47c841ba3b2d3fc0b4b13282cf029ea18b66d78b" + "reference": "62139b2806178adb979d76bd3437534a1a9fd490" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/composer/zipball/47c841ba3b2d3fc0b4b13282cf029ea18b66d78b", - "reference": "47c841ba3b2d3fc0b4b13282cf029ea18b66d78b", + "url": "https://api.github.com/repos/composer/composer/zipball/62139b2806178adb979d76bd3437534a1a9fd490", + "reference": "62139b2806178adb979d76bd3437534a1a9fd490", "shasum": "" }, "require": { "composer/ca-bundle": "^1.0", - "composer/semver": "^1.0", + "composer/semver": "^3.0", "composer/spdx-licenses": "^1.2", "composer/xdebug-handler": "^1.1", "justinrainbow/json-schema": "^5.2.10", - "php": "^5.3.2 || ^7.0", + "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.7 || ^3.0 || ^4.0 || ^5.0", - "symfony/filesystem": "^2.7 || ^3.0 || ^4.0 || ^5.0", - "symfony/finder": "^2.7 || ^3.0 || ^4.0 || ^5.0", - "symfony/process": "^2.7 || ^3.0 || ^4.0 || ^5.0" - }, - "conflict": { - "symfony/console": "2.8.38" + "symfony/console": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0", + "symfony/filesystem": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0", + "symfony/finder": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0", + "symfony/process": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0" }, "require-dev": { "phpspec/prophecy": "^1.10", - "symfony/phpunit-bridge": "^4.2" + "symfony/phpunit-bridge": "^4.2 || ^5.0" }, "suggest": { "ext-openssl": "Enabling the openssl extension allows you to access https URLs for repositories and packages", @@ -6040,7 +6550,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.10-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -6056,12 +6566,12 @@ { "name": "Nils Adermann", "email": "naderman@naderman.de", - "homepage": "http://www.naderman.de" + "homepage": "https://www.naderman.de" }, { "name": "Jordi Boggiano", "email": "j.boggiano@seld.be", - "homepage": "http://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.", @@ -6071,6 +6581,11 @@ "dependency", "package" ], + "support": { + "irc": "irc://irc.freenode.org/composer", + "issues": "https://github.com/composer/composer/issues", + "source": "https://github.com/composer/composer/tree/2.0.8" + }, "funding": [ { "url": "https://packagist.com", @@ -6085,32 +6600,33 @@ "type": "tidelift" } ], - "time": "2020-09-09T09:46:34+00:00" + "time": "2020-12-03T16:20:39+00:00" }, { "name": "composer/semver", - "version": "1.7.0", + "version": "3.2.4", "source": { "type": "git", "url": "https://github.com/composer/semver.git", - "reference": "114f819054a2ea7db03287f5efb757e2af6e4079" + "reference": "a02fdf930a3c1c3ed3a49b5f63859c0c20e10464" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/114f819054a2ea7db03287f5efb757e2af6e4079", - "reference": "114f819054a2ea7db03287f5efb757e2af6e4079", + "url": "https://api.github.com/repos/composer/semver/zipball/a02fdf930a3c1c3ed3a49b5f63859c0c20e10464", + "reference": "a02fdf930a3c1c3ed3a49b5f63859c0c20e10464", "shasum": "" }, "require": { - "php": "^5.3.2 || ^7.0" + "php": "^5.3.2 || ^7.0 || ^8.0" }, "require-dev": { - "phpunit/phpunit": "^4.5 || ^5.0.5" + "phpstan/phpstan": "^0.12.54", + "symfony/phpunit-bridge": "^4.2 || ^5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.x-dev" + "dev-main": "3.x-dev" } }, "autoload": { @@ -6146,6 +6662,11 @@ "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.4" + }, "funding": [ { "url": "https://packagist.com", @@ -6160,20 +6681,20 @@ "type": "tidelift" } ], - "time": "2020-09-09T09:34:06+00:00" + "time": "2020-11-13T08:59:24+00:00" }, { "name": "composer/spdx-licenses", - "version": "1.5.4", + "version": "1.5.5", "source": { "type": "git", "url": "https://github.com/composer/spdx-licenses.git", - "reference": "6946f785871e2314c60b4524851f3702ea4f2223" + "reference": "de30328a7af8680efdc03e396aad24befd513200" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/spdx-licenses/zipball/6946f785871e2314c60b4524851f3702ea4f2223", - "reference": "6946f785871e2314c60b4524851f3702ea4f2223", + "url": "https://api.github.com/repos/composer/spdx-licenses/zipball/de30328a7af8680efdc03e396aad24befd513200", + "reference": "de30328a7af8680efdc03e396aad24befd513200", "shasum": "" }, "require": { @@ -6185,7 +6706,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.x-dev" + "dev-main": "1.x-dev" } }, "autoload": { @@ -6220,6 +6741,11 @@ "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", @@ -6234,20 +6760,20 @@ "type": "tidelift" } ], - "time": "2020-07-15T15:35:07+00:00" + "time": "2020-12-03T16:04:16+00:00" }, { "name": "composer/xdebug-handler", - "version": "1.4.3", + "version": "1.4.5", "source": { "type": "git", "url": "https://github.com/composer/xdebug-handler.git", - "reference": "ebd27a9866ae8254e873866f795491f02418c5a5" + "reference": "f28d44c286812c714741478d968104c5e604a1d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/ebd27a9866ae8254e873866f795491f02418c5a5", - "reference": "ebd27a9866ae8254e873866f795491f02418c5a5", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/f28d44c286812c714741478d968104c5e604a1d4", + "reference": "f28d44c286812c714741478d968104c5e604a1d4", "shasum": "" }, "require": { @@ -6278,6 +6804,11 @@ "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/1.4.5" + }, "funding": [ { "url": "https://packagist.com", @@ -6292,40 +6823,35 @@ "type": "tidelift" } ], - "time": "2020-08-19T10:27:58+00:00" + "time": "2020-11-13T08:04:11+00:00" }, { "name": "doctrine/instantiator", - "version": "1.3.1", + "version": "1.4.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "f350df0268e904597e3bd9c4685c53e0e333feea" + "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/f350df0268e904597e3bd9c4685c53e0e333feea", - "reference": "f350df0268e904597e3bd9c4685c53e0e333feea", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/d56bf6102915de5702778fe20f2de3b2fe570b5b", + "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b", "shasum": "" }, "require": { "php": "^7.1 || ^8.0" }, "require-dev": { - "doctrine/coding-standard": "^6.0", + "doctrine/coding-standard": "^8.0", "ext-pdo": "*", "ext-phar": "*", - "phpbench/phpbench": "^0.13", - "phpstan/phpstan-phpunit": "^0.11", - "phpstan/phpstan-shim": "^0.11", - "phpunit/phpunit": "^7.0" + "phpbench/phpbench": "^0.13 || 1.0.0-alpha2", + "phpstan/phpstan": "^0.12", + "phpstan/phpstan-phpunit": "^0.12", + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2.x-dev" - } - }, "autoload": { "psr-4": { "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" @@ -6339,7 +6865,7 @@ { "name": "Marco Pivetta", "email": "ocramius@gmail.com", - "homepage": "http://ocramius.github.com/" + "homepage": "https://ocramius.github.io/" } ], "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", @@ -6348,6 +6874,10 @@ "constructor", "instantiate" ], + "support": { + "issues": "https://github.com/doctrine/instantiator/issues", + "source": "https://github.com/doctrine/instantiator/tree/1.4.0" + }, "funding": [ { "url": "https://www.doctrine-project.org/sponsorship.html", @@ -6362,36 +6892,34 @@ "type": "tidelift" } ], - "time": "2020-05-29T17:27:14+00:00" + "time": "2020-11-10T18:47:58+00:00" }, { - "name": "fzaninotto/faker", - "version": "v1.9.1", + "name": "fakerphp/faker", + "version": "v1.13.0", "source": { "type": "git", - "url": "https://github.com/fzaninotto/Faker.git", - "reference": "fc10d778e4b84d5bd315dad194661e091d307c6f" + "url": "https://github.com/FakerPHP/Faker.git", + "reference": "ab3f5364d01f2c2c16113442fb987d26e4004913" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fzaninotto/Faker/zipball/fc10d778e4b84d5bd315dad194661e091d307c6f", - "reference": "fc10d778e4b84d5bd315dad194661e091d307c6f", + "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/ab3f5364d01f2c2c16113442fb987d26e4004913", + "reference": "ab3f5364d01f2c2c16113442fb987d26e4004913", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0" + "php": "^7.1 || ^8.0" + }, + "conflict": { + "fzaninotto/faker": "*" }, "require-dev": { + "bamarni/composer-bin-plugin": "^1.4.1", "ext-intl": "*", - "phpunit/phpunit": "^4.8.35 || ^5.7", - "squizlabs/php_codesniffer": "^2.9.2" + "phpunit/phpunit": "^7.5.20 || ^8.5.8 || ^9.4.2" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.9-dev" - } - }, "autoload": { "psr-4": { "Faker\\": "src/Faker/" @@ -6412,7 +6940,11 @@ "faker", "fixtures" ], - "time": "2019-12-12T13:22:17+00:00" + "support": { + "issues": "https://github.com/FakerPHP/Faker/issues", + "source": "https://github.com/FakerPHP/Faker/tree/v1.13.0" + }, + "time": "2020-12-18T16:50:48+00:00" }, { "name": "hamcrest/hamcrest-php", @@ -6459,6 +6991,10 @@ "keywords": [ "test" ], + "support": { + "issues": "https://github.com/hamcrest/hamcrest-php/issues", + "source": "https://github.com/hamcrest/hamcrest-php/tree/v2.0.1" + }, "time": "2020-07-09T08:09:16+00:00" }, { @@ -6525,20 +7061,24 @@ "json", "schema" ], + "support": { + "issues": "https://github.com/justinrainbow/json-schema/issues", + "source": "https://github.com/justinrainbow/json-schema/tree/5.2.10" + }, "time": "2020-05-27T16:41:55+00:00" }, { "name": "laravel/browser-kit-testing", - "version": "v5.1.4", + "version": "v5.2.0", "source": { "type": "git", "url": "https://github.com/laravel/browser-kit-testing.git", - "reference": "7664a30d2dbabcdb0315bfaa867fef2df8cb8fb1" + "reference": "fa0efb279c009e2a276f934f8aff946caf66edc7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/browser-kit-testing/zipball/7664a30d2dbabcdb0315bfaa867fef2df8cb8fb1", - "reference": "7664a30d2dbabcdb0315bfaa867fef2df8cb8fb1", + "url": "https://api.github.com/repos/laravel/browser-kit-testing/zipball/fa0efb279c009e2a276f934f8aff946caf66edc7", + "reference": "fa0efb279c009e2a276f934f8aff946caf66edc7", "shasum": "" }, "require": { @@ -6549,8 +7089,8 @@ "illuminate/http": "~5.7.0|~5.8.0|^6.0", "illuminate/support": "~5.7.0|~5.8.0|^6.0", "mockery/mockery": "^1.0", - "php": ">=7.1.3", - "phpunit/phpunit": "^7.5|^8.0", + "php": "^7.1.3|^8.0", + "phpunit/phpunit": "^7.5|^8.0|^9.3", "symfony/console": "^4.2", "symfony/css-selector": "^4.2", "symfony/dom-crawler": "^4.2", @@ -6586,29 +7126,33 @@ "laravel", "testing" ], - "time": "2020-08-25T16:54:44+00:00" + "support": { + "issues": "https://github.com/laravel/browser-kit-testing/issues", + "source": "https://github.com/laravel/browser-kit-testing/tree/v5.2.0" + }, + "time": "2020-10-30T08:49:09+00:00" }, { "name": "maximebf/debugbar", - "version": "v1.16.3", + "version": "v1.16.4", "source": { "type": "git", "url": "https://github.com/maximebf/php-debugbar.git", - "reference": "1a1605b8e9bacb34cc0c6278206d699772e1d372" + "reference": "c86c717e4bf3c6d98422da5c38bfa7b0f494b04c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/1a1605b8e9bacb34cc0c6278206d699772e1d372", - "reference": "1a1605b8e9bacb34cc0c6278206d699772e1d372", + "url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/c86c717e4bf3c6d98422da5c38bfa7b0f494b04c", + "reference": "c86c717e4bf3c6d98422da5c38bfa7b0f494b04c", "shasum": "" }, "require": { - "php": "^7.1", + "php": "^7.1|^8", "psr/log": "^1.0", "symfony/var-dumper": "^2.6|^3|^4|^5" }, "require-dev": { - "phpunit/phpunit": "^5" + "phpunit/phpunit": "^7.5.20 || ^9.4.2" }, "suggest": { "kriswallsmith/assetic": "The best way to manage assets", @@ -6647,7 +7191,11 @@ "debug", "debugbar" ], - "time": "2020-05-06T07:06:27+00:00" + "support": { + "issues": "https://github.com/maximebf/php-debugbar/issues", + "source": "https://github.com/maximebf/php-debugbar/tree/v1.16.4" + }, + "time": "2020-12-07T10:48:48+00:00" }, { "name": "mockery/mockery", @@ -6712,20 +7260,24 @@ "test double", "testing" ], + "support": { + "issues": "https://github.com/mockery/mockery/issues", + "source": "https://github.com/mockery/mockery/tree/1.3.3" + }, "time": "2020-08-11T18:10:21+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.10.1", + "version": "1.10.2", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "969b211f9a51aa1f6c01d1d2aef56d3bd91598e5" + "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/969b211f9a51aa1f6c01d1d2aef56d3bd91598e5", - "reference": "969b211f9a51aa1f6c01d1d2aef56d3bd91598e5", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/776f831124e9c62e1a2c601ecc52e776d8bb7220", + "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220", "shasum": "" }, "require": { @@ -6760,38 +7312,43 @@ "object", "object graph" ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.10.2" + }, "funding": [ { "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", "type": "tidelift" } ], - "time": "2020-06-29T13:22:24+00:00" + "time": "2020-11-13T09:40:50+00:00" }, { "name": "phar-io/manifest", - "version": "1.0.3", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/phar-io/manifest.git", - "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4" + "reference": "85265efd3af7ba3ca4b2a2c34dbfc5788dd29133" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/7761fcacf03b4d4f16e7ccb606d4879ca431fcf4", - "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/85265efd3af7ba3ca4b2a2c34dbfc5788dd29133", + "reference": "85265efd3af7ba3ca4b2a2c34dbfc5788dd29133", "shasum": "" }, "require": { "ext-dom": "*", "ext-phar": "*", - "phar-io/version": "^2.0", - "php": "^5.6 || ^7.0" + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -6806,39 +7363,43 @@ "authors": [ { "name": "Arne Blankerts", - "role": "Developer", - "email": "arne@blankerts.de" + "email": "arne@blankerts.de", + "role": "Developer" }, { "name": "Sebastian Heuer", - "role": "Developer", - "email": "sebastian@phpeople.de" + "email": "sebastian@phpeople.de", + "role": "Developer" }, { "name": "Sebastian Bergmann", - "role": "Developer", - "email": "sebastian@phpunit.de" + "email": "sebastian@phpunit.de", + "role": "Developer" } ], "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", - "time": "2018-07-08T19:23:20+00:00" + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/master" + }, + "time": "2020-06-27T14:33:11+00:00" }, { "name": "phar-io/version", - "version": "2.0.1", + "version": "3.0.4", "source": { "type": "git", "url": "https://github.com/phar-io/version.git", - "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6" + "reference": "e4782611070e50613683d2b9a57730e9a3ba5451" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/45a2ec53a73c70ce41d55cedef9063630abaf1b6", - "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6", + "url": "https://api.github.com/repos/phar-io/version/zipball/e4782611070e50613683d2b9a57730e9a3ba5451", + "reference": "e4782611070e50613683d2b9a57730e9a3ba5451", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0" + "php": "^7.2 || ^8.0" }, "type": "library", "autoload": { @@ -6868,7 +7429,11 @@ } ], "description": "Library for handling version information and constraints", - "time": "2018-07-08T19:19:57+00:00" + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.0.4" + }, + "time": "2020-12-13T23:18:30+00:00" }, { "name": "phpdocumentor/reflection-common", @@ -6917,6 +7482,10 @@ "reflection", "static analysis" ], + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", + "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" + }, "time": "2020-06-27T09:03:43+00:00" }, { @@ -6969,6 +7538,10 @@ } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/master" + }, "time": "2020-09-03T19:13:55+00:00" }, { @@ -7014,81 +7587,36 @@ } ], "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", + "support": { + "issues": "https://github.com/phpDocumentor/TypeResolver/issues", + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.4.0" + }, "time": "2020-09-17T18:55:26+00:00" }, - { - "name": "phploc/phploc", - "version": "5.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phploc.git", - "reference": "5b714ccb7cb8ca29ccf9caf6eb1aed0131d3a884" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phploc/zipball/5b714ccb7cb8ca29ccf9caf6eb1aed0131d3a884", - "reference": "5b714ccb7cb8ca29ccf9caf6eb1aed0131d3a884", - "shasum": "" - }, - "require": { - "php": "^7.2", - "sebastian/finder-facade": "^1.1", - "sebastian/version": "^2.0", - "symfony/console": "^4.0" - }, - "bin": [ - "phploc" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "A tool for quickly measuring the size of a PHP project.", - "homepage": "https://github.com/sebastianbergmann/phploc", - "time": "2019-03-16T10:41:19+00:00" - }, { "name": "phpspec/prophecy", - "version": "1.11.1", + "version": "1.12.1", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "b20034be5efcdab4fb60ca3a29cba2949aead160" + "reference": "8ce87516be71aae9b956f81906aaf0338e0d8a2d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/b20034be5efcdab4fb60ca3a29cba2949aead160", - "reference": "b20034be5efcdab4fb60ca3a29cba2949aead160", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/8ce87516be71aae9b956f81906aaf0338e0d8a2d", + "reference": "8ce87516be71aae9b956f81906aaf0338e0d8a2d", "shasum": "" }, "require": { "doctrine/instantiator": "^1.2", - "php": "^7.2", - "phpdocumentor/reflection-docblock": "^5.0", + "php": "^7.2 || ~8.0, <8.1", + "phpdocumentor/reflection-docblock": "^5.2", "sebastian/comparator": "^3.0 || ^4.0", "sebastian/recursion-context": "^3.0 || ^4.0" }, "require-dev": { "phpspec/phpspec": "^6.0", - "phpunit/phpunit": "^8.0" + "phpunit/phpunit": "^8.0 || ^9.0 <9.3" }, "type": "library", "extra": { @@ -7126,29 +7654,33 @@ "spy", "stub" ], - "time": "2020-07-08T12:44:21+00:00" + "support": { + "issues": "https://github.com/phpspec/prophecy/issues", + "source": "https://github.com/phpspec/prophecy/tree/1.12.1" + }, + "time": "2020-09-29T09:10:42+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "7.0.10", + "version": "7.0.14", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "f1884187926fbb755a9aaf0b3836ad3165b478bf" + "reference": "bb7c9a210c72e4709cdde67f8b7362f672f2225c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f1884187926fbb755a9aaf0b3836ad3165b478bf", - "reference": "f1884187926fbb755a9aaf0b3836ad3165b478bf", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/bb7c9a210c72e4709cdde67f8b7362f672f2225c", + "reference": "bb7c9a210c72e4709cdde67f8b7362f672f2225c", "shasum": "" }, "require": { "ext-dom": "*", "ext-xmlwriter": "*", - "php": "^7.2", + "php": ">=7.2", "phpunit/php-file-iterator": "^2.0.2", "phpunit/php-text-template": "^1.2.1", - "phpunit/php-token-stream": "^3.1.1", + "phpunit/php-token-stream": "^3.1.1 || ^4.0", "sebastian/code-unit-reverse-lookup": "^1.0.1", "sebastian/environment": "^4.2.2", "sebastian/version": "^2.0.1", @@ -7189,27 +7721,37 @@ "testing", "xunit" ], - "time": "2019-11-20T13:55:58+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/7.0.14" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-12-02T13:39:03+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "2.0.2", + "version": "2.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "050bedf145a257b1ff02746c31894800e5122946" + "reference": "4b49fb70f067272b659ef0174ff9ca40fdaa6357" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/050bedf145a257b1ff02746c31894800e5122946", - "reference": "050bedf145a257b1ff02746c31894800e5122946", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/4b49fb70f067272b659ef0174ff9ca40fdaa6357", + "reference": "4b49fb70f067272b659ef0174ff9ca40fdaa6357", "shasum": "" }, "require": { - "php": "^7.1" + "php": ">=7.1" }, "require-dev": { - "phpunit/phpunit": "^7.1" + "phpunit/phpunit": "^8.5" }, "type": "library", "extra": { @@ -7239,7 +7781,17 @@ "filesystem", "iterator" ], - "time": "2018-09-13T20:33:42+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/2.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T08:25:21+00:00" }, { "name": "phpunit/php-text-template", @@ -7280,27 +7832,31 @@ "keywords": [ "template" ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/1.2.1" + }, "time": "2015-06-21T13:50:34+00:00" }, { "name": "phpunit/php-timer", - "version": "2.1.2", + "version": "2.1.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "1038454804406b0b5f5f520358e78c1c2f71501e" + "reference": "2454ae1765516d20c4ffe103d85a58a9a3bd5662" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/1038454804406b0b5f5f520358e78c1c2f71501e", - "reference": "1038454804406b0b5f5f520358e78c1c2f71501e", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/2454ae1765516d20c4ffe103d85a58a9a3bd5662", + "reference": "2454ae1765516d20c4ffe103d85a58a9a3bd5662", "shasum": "" }, "require": { - "php": "^7.1" + "php": ">=7.1" }, "require-dev": { - "phpunit/phpunit": "^7.0" + "phpunit/phpunit": "^8.5" }, "type": "library", "extra": { @@ -7329,25 +7885,35 @@ "keywords": [ "timer" ], - "time": "2019-06-07T04:22:29+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "source": "https://github.com/sebastianbergmann/php-timer/tree/2.1.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T08:20:02+00:00" }, { "name": "phpunit/php-token-stream", - "version": "3.1.1", + "version": "3.1.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "995192df77f63a59e47f025390d2d1fdf8f425ff" + "reference": "472b687829041c24b25f475e14c2f38a09edf1c2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/995192df77f63a59e47f025390d2d1fdf8f425ff", - "reference": "995192df77f63a59e47f025390d2d1fdf8f425ff", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/472b687829041c24b25f475e14c2f38a09edf1c2", + "reference": "472b687829041c24b25f475e14c2f38a09edf1c2", "shasum": "" }, "require": { "ext-tokenizer": "*", - "php": "^7.1" + "php": ">=7.1" }, "require-dev": { "phpunit/phpunit": "^7.0" @@ -7378,43 +7944,54 @@ "keywords": [ "tokenizer" ], - "time": "2019-09-17T06:23:10+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/php-token-stream/issues", + "source": "https://github.com/sebastianbergmann/php-token-stream/tree/3.1.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "abandoned": true, + "time": "2020-11-30T08:38:46+00:00" }, { "name": "phpunit/phpunit", - "version": "8.5.8", + "version": "8.5.13", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "34c18baa6a44f1d1fbf0338907139e9dce95b997" + "reference": "8e86be391a58104ef86037ba8a846524528d784e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/34c18baa6a44f1d1fbf0338907139e9dce95b997", - "reference": "34c18baa6a44f1d1fbf0338907139e9dce95b997", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/8e86be391a58104ef86037ba8a846524528d784e", + "reference": "8e86be391a58104ef86037ba8a846524528d784e", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.2.0", + "doctrine/instantiator": "^1.3.1", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", "ext-mbstring": "*", "ext-xml": "*", "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.9.1", - "phar-io/manifest": "^1.0.3", - "phar-io/version": "^2.0.1", - "php": "^7.2", - "phpspec/prophecy": "^1.8.1", - "phpunit/php-code-coverage": "^7.0.7", + "myclabs/deep-copy": "^1.10.0", + "phar-io/manifest": "^2.0.1", + "phar-io/version": "^3.0.2", + "php": ">=7.2", + "phpspec/prophecy": "^1.10.3", + "phpunit/php-code-coverage": "^7.0.12", "phpunit/php-file-iterator": "^2.0.2", "phpunit/php-text-template": "^1.2.1", "phpunit/php-timer": "^2.1.2", "sebastian/comparator": "^3.0.2", "sebastian/diff": "^3.0.2", - "sebastian/environment": "^4.2.2", - "sebastian/exporter": "^3.1.1", + "sebastian/environment": "^4.2.3", + "sebastian/exporter": "^3.1.2", "sebastian/global-state": "^3.0.0", "sebastian/object-enumerator": "^3.0.3", "sebastian/resource-operations": "^2.0.1", @@ -7461,6 +8038,10 @@ "testing", "xunit" ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "source": "https://github.com/sebastianbergmann/phpunit/tree/8.5.13" + }, "funding": [ { "url": "https://phpunit.de/donate.html", @@ -7471,27 +8052,77 @@ "type": "github" } ], - "time": "2020-06-22T07:06:58+00:00" + "time": "2020-12-01T04:53:52+00:00" }, { - "name": "sebastian/code-unit-reverse-lookup", - "version": "1.0.1", + "name": "react/promise", + "version": "v2.8.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18" + "url": "https://github.com/reactphp/promise.git", + "reference": "f3cff96a19736714524ca0dd1d4130de73dbbbc4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", - "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", + "url": "https://api.github.com/repos/reactphp/promise/zipball/f3cff96a19736714524ca0dd1d4130de73dbbbc4", + "reference": "f3cff96a19736714524ca0dd1d4130de73dbbbc4", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0" + "php": ">=5.4.0" }, "require-dev": { - "phpunit/phpunit": "^5.7 || ^6.0" + "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/code-unit-reverse-lookup", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "1de8cd5c010cb153fcd68b8d0f64606f523f7619" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/1de8cd5c010cb153fcd68b8d0f64606f523f7619", + "reference": "1de8cd5c010cb153fcd68b8d0f64606f523f7619", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "phpunit/phpunit": "^8.5" }, "type": "library", "extra": { @@ -7516,29 +8147,39 @@ ], "description": "Looks up which function or method a line of code belongs to", "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "time": "2017-03-04T06:30:41+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/1.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T08:15:22+00:00" }, { "name": "sebastian/comparator", - "version": "3.0.2", + "version": "3.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da" + "reference": "1071dfcef776a57013124ff35e1fc41ccd294758" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/5de4fc177adf9bce8df98d8d141a7559d7ccf6da", - "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/1071dfcef776a57013124ff35e1fc41ccd294758", + "reference": "1071dfcef776a57013124ff35e1fc41ccd294758", "shasum": "" }, "require": { - "php": "^7.1", + "php": ">=7.1", "sebastian/diff": "^3.0", "sebastian/exporter": "^3.1" }, "require-dev": { - "phpunit/phpunit": "^7.1" + "phpunit/phpunit": "^8.5" }, "type": "library", "extra": { @@ -7556,6 +8197,10 @@ "BSD-3-Clause" ], "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, { "name": "Jeff Welch", "email": "whatthejeff@gmail.com" @@ -7567,10 +8212,6 @@ { "name": "Bernhard Schussek", "email": "bschussek@2bepublished.at" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" } ], "description": "Provides the functionality to compare PHP values for equality", @@ -7580,24 +8221,34 @@ "compare", "equality" ], - "time": "2018-07-12T15:12:46+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "source": "https://github.com/sebastianbergmann/comparator/tree/3.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T08:04:30+00:00" }, { "name": "sebastian/diff", - "version": "3.0.2", + "version": "3.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29" + "reference": "14f72dd46eaf2f2293cbe79c93cc0bc43161a211" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/720fcc7e9b5cf384ea68d9d930d480907a0c1a29", - "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/14f72dd46eaf2f2293cbe79c93cc0bc43161a211", + "reference": "14f72dd46eaf2f2293cbe79c93cc0bc43161a211", "shasum": "" }, "require": { - "php": "^7.1" + "php": ">=7.1" }, "require-dev": { "phpunit/phpunit": "^7.5 || ^8.0", @@ -7619,13 +8270,13 @@ "BSD-3-Clause" ], "authors": [ - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" } ], "description": "Diff implementation", @@ -7636,24 +8287,34 @@ "unidiff", "unified diff" ], - "time": "2019-02-04T06:01:07+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "source": "https://github.com/sebastianbergmann/diff/tree/3.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T07:59:04+00:00" }, { "name": "sebastian/environment", - "version": "4.2.3", + "version": "4.2.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "464c90d7bdf5ad4e8a6aea15c091fec0603d4368" + "reference": "d47bbbad83711771f167c72d4e3f25f7fcc1f8b0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/464c90d7bdf5ad4e8a6aea15c091fec0603d4368", - "reference": "464c90d7bdf5ad4e8a6aea15c091fec0603d4368", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/d47bbbad83711771f167c72d4e3f25f7fcc1f8b0", + "reference": "d47bbbad83711771f167c72d4e3f25f7fcc1f8b0", "shasum": "" }, "require": { - "php": "^7.1" + "php": ">=7.1" }, "require-dev": { "phpunit/phpunit": "^7.5" @@ -7689,24 +8350,34 @@ "environment", "hhvm" ], - "time": "2019-11-20T08:46:58+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "source": "https://github.com/sebastianbergmann/environment/tree/4.2.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T07:53:42+00:00" }, { "name": "sebastian/exporter", - "version": "3.1.2", + "version": "3.1.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "68609e1261d215ea5b21b7987539cbfbe156ec3e" + "reference": "6b853149eab67d4da22291d36f5b0631c0fd856e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/68609e1261d215ea5b21b7987539cbfbe156ec3e", - "reference": "68609e1261d215ea5b21b7987539cbfbe156ec3e", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/6b853149eab67d4da22291d36f5b0631c0fd856e", + "reference": "6b853149eab67d4da22291d36f5b0631c0fd856e", "shasum": "" }, "require": { - "php": "^7.0", + "php": ">=7.0", "sebastian/recursion-context": "^3.0" }, "require-dev": { @@ -7756,67 +8427,34 @@ "export", "exporter" ], - "time": "2019-09-14T09:02:43+00:00" - }, - { - "name": "sebastian/finder-facade", - "version": "1.2.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/finder-facade.git", - "reference": "167c45d131f7fc3d159f56f191a0a22228765e16" + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "source": "https://github.com/sebastianbergmann/exporter/tree/3.1.3" }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/finder-facade/zipball/167c45d131f7fc3d159f56f191a0a22228765e16", - "reference": "167c45d131f7fc3d159f56f191a0a22228765e16", - "shasum": "" - }, - "require": { - "php": "^7.1", - "symfony/finder": "^2.3|^3.0|^4.0|^5.0", - "theseer/fdomdocument": "^1.6" - }, - "type": "library", - "extra": { - "branch-alias": [] - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ + "funding": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "url": "https://github.com/sebastianbergmann", + "type": "github" } ], - "description": "FinderFacade is a convenience wrapper for Symfony's Finder component.", - "homepage": "https://github.com/sebastianbergmann/finder-facade", - "time": "2020-01-16T08:08:45+00:00" + "time": "2020-11-30T07:47:53+00:00" }, { "name": "sebastian/global-state", - "version": "3.0.0", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "edf8a461cf1d4005f19fb0b6b8b95a9f7fa0adc4" + "reference": "474fb9edb7ab891665d3bfc6317f42a0a150454b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/edf8a461cf1d4005f19fb0b6b8b95a9f7fa0adc4", - "reference": "edf8a461cf1d4005f19fb0b6b8b95a9f7fa0adc4", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/474fb9edb7ab891665d3bfc6317f42a0a150454b", + "reference": "474fb9edb7ab891665d3bfc6317f42a0a150454b", "shasum": "" }, "require": { - "php": "^7.2", + "php": ">=7.2", "sebastian/object-reflector": "^1.1.1", "sebastian/recursion-context": "^3.0" }, @@ -7853,24 +8491,34 @@ "keywords": [ "global state" ], - "time": "2019-02-01T05:30:01+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "source": "https://github.com/sebastianbergmann/global-state/tree/3.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T07:43:24+00:00" }, { "name": "sebastian/object-enumerator", - "version": "3.0.3", + "version": "3.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5" + "reference": "e67f6d32ebd0c749cf9d1dbd9f226c727043cdf2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/7cfd9e65d11ffb5af41198476395774d4c8a84c5", - "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/e67f6d32ebd0c749cf9d1dbd9f226c727043cdf2", + "reference": "e67f6d32ebd0c749cf9d1dbd9f226c727043cdf2", "shasum": "" }, "require": { - "php": "^7.0", + "php": ">=7.0", "sebastian/object-reflector": "^1.1.1", "sebastian/recursion-context": "^3.0" }, @@ -7900,24 +8548,34 @@ ], "description": "Traverses array structures and object graphs to enumerate all referenced objects", "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "time": "2017-08-03T12:35:26+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/3.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T07:40:27+00:00" }, { "name": "sebastian/object-reflector", - "version": "1.1.1", + "version": "1.1.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "773f97c67f28de00d397be301821b06708fca0be" + "reference": "9b8772b9cbd456ab45d4a598d2dd1a1bced6363d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/773f97c67f28de00d397be301821b06708fca0be", - "reference": "773f97c67f28de00d397be301821b06708fca0be", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/9b8772b9cbd456ab45d4a598d2dd1a1bced6363d", + "reference": "9b8772b9cbd456ab45d4a598d2dd1a1bced6363d", "shasum": "" }, "require": { - "php": "^7.0" + "php": ">=7.0" }, "require-dev": { "phpunit/phpunit": "^6.0" @@ -7945,24 +8603,34 @@ ], "description": "Allows reflection of object attributes, including inherited and non-public ones", "homepage": "https://github.com/sebastianbergmann/object-reflector/", - "time": "2017-03-29T09:07:27+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/1.1.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T07:37:18+00:00" }, { "name": "sebastian/recursion-context", - "version": "3.0.0", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8" + "reference": "367dcba38d6e1977be014dc4b22f47a484dac7fb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", - "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/367dcba38d6e1977be014dc4b22f47a484dac7fb", + "reference": "367dcba38d6e1977be014dc4b22f47a484dac7fb", "shasum": "" }, "require": { - "php": "^7.0" + "php": ">=7.0" }, "require-dev": { "phpunit/phpunit": "^6.0" @@ -7983,14 +8651,14 @@ "BSD-3-Clause" ], "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, { "name": "Adam Harvey", "email": "aharvey@php.net" @@ -7998,24 +8666,34 @@ ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2017-03-03T06:23:57+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/3.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T07:34:24+00:00" }, { "name": "sebastian/resource-operations", - "version": "2.0.1", + "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9" + "reference": "31d35ca87926450c44eae7e2611d45a7a65ea8b3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/4d7a795d35b889bf80a0cc04e08d77cedfa917a9", - "reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/31d35ca87926450c44eae7e2611d45a7a65ea8b3", + "reference": "31d35ca87926450c44eae7e2611d45a7a65ea8b3", "shasum": "" }, "require": { - "php": "^7.1" + "php": ">=7.1" }, "type": "library", "extra": { @@ -8040,24 +8718,34 @@ ], "description": "Provides a list of PHP built-in functions that operate on resources", "homepage": "https://www.github.com/sebastianbergmann/resource-operations", - "time": "2018-10-04T04:07:39+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/resource-operations/issues", + "source": "https://github.com/sebastianbergmann/resource-operations/tree/2.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T07:30:19+00:00" }, { "name": "sebastian/type", - "version": "1.1.3", + "version": "1.1.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "3aaaa15fa71d27650d62a948be022fe3b48541a3" + "reference": "0150cfbc4495ed2df3872fb31b26781e4e077eb4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/3aaaa15fa71d27650d62a948be022fe3b48541a3", - "reference": "3aaaa15fa71d27650d62a948be022fe3b48541a3", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/0150cfbc4495ed2df3872fb31b26781e4e077eb4", + "reference": "0150cfbc4495ed2df3872fb31b26781e4e077eb4", "shasum": "" }, "require": { - "php": "^7.2" + "php": ">=7.2" }, "require-dev": { "phpunit/phpunit": "^8.2" @@ -8086,7 +8774,17 @@ ], "description": "Collection of value objects that represent the types of the PHP type system", "homepage": "https://github.com/sebastianbergmann/type", - "time": "2019-07-02T08:10:15+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues", + "source": "https://github.com/sebastianbergmann/type/tree/1.1.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T07:25:11+00:00" }, { "name": "sebastian/version", @@ -8129,20 +8827,24 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "source": "https://github.com/sebastianbergmann/version/tree/master" + }, "time": "2016-10-03T07:35:21+00:00" }, { "name": "seld/jsonlint", - "version": "1.8.2", + "version": "1.8.3", "source": { "type": "git", "url": "https://github.com/Seldaek/jsonlint.git", - "reference": "590cfec960b77fd55e39b7d9246659e95dd6d337" + "reference": "9ad6ce79c342fbd44df10ea95511a1b24dee5b57" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/590cfec960b77fd55e39b7d9246659e95dd6d337", - "reference": "590cfec960b77fd55e39b7d9246659e95dd6d337", + "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/9ad6ce79c342fbd44df10ea95511a1b24dee5b57", + "reference": "9ad6ce79c342fbd44df10ea95511a1b24dee5b57", "shasum": "" }, "require": { @@ -8178,6 +8880,10 @@ "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", @@ -8188,7 +8894,7 @@ "type": "tidelift" } ], - "time": "2020-08-25T06:56:57+00:00" + "time": "2020-11-11T09:19:24+00:00" }, { "name": "seld/phar-utils", @@ -8232,20 +8938,24 @@ "keywords": [ "phar" ], + "support": { + "issues": "https://github.com/Seldaek/phar-utils/issues", + "source": "https://github.com/Seldaek/phar-utils/tree/master" + }, "time": "2020-07-07T18:42:57+00:00" }, { "name": "squizlabs/php_codesniffer", - "version": "3.5.6", + "version": "3.5.8", "source": { "type": "git", "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "e97627871a7eab2f70e59166072a6b767d5834e0" + "reference": "9d583721a7157ee997f235f327de038e7ea6dac4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/e97627871a7eab2f70e59166072a6b767d5834e0", - "reference": "e97627871a7eab2f70e59166072a6b767d5834e0", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/9d583721a7157ee997f235f327de038e7ea6dac4", + "reference": "9d583721a7157ee997f235f327de038e7ea6dac4", "shasum": "" }, "require": { @@ -8283,20 +8993,25 @@ "phpcs", "standards" ], - "time": "2020-08-10T04:50:15+00:00" + "support": { + "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", + "source": "https://github.com/squizlabs/PHP_CodeSniffer", + "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" + }, + "time": "2020-10-23T02:01:07+00:00" }, { "name": "symfony/dom-crawler", - "version": "v4.4.13", + "version": "v4.4.18", "source": { "type": "git", "url": "https://github.com/symfony/dom-crawler.git", - "reference": "6dd1e7adef4b7efeeb9691fd619279027d4dcf85" + "reference": "d44fbb02b458fe18d00fea18f24c97cefb87577e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/6dd1e7adef4b7efeeb9691fd619279027d4dcf85", - "reference": "6dd1e7adef4b7efeeb9691fd619279027d4dcf85", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/d44fbb02b458fe18d00fea18f24c97cefb87577e", + "reference": "d44fbb02b458fe18d00fea18f24c97cefb87577e", "shasum": "" }, "require": { @@ -8315,11 +9030,6 @@ "symfony/css-selector": "" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.4-dev" - } - }, "autoload": { "psr-4": { "Symfony\\Component\\DomCrawler\\": "" @@ -8344,6 +9054,9 @@ ], "description": "Symfony DomCrawler Component", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/dom-crawler/tree/v4.4.18" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -8358,32 +9071,27 @@ "type": "tidelift" } ], - "time": "2020-08-12T06:20:35+00:00" + "time": "2020-12-18T07:41:31+00:00" }, { "name": "symfony/filesystem", - "version": "v4.4.13", + "version": "v5.2.1", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "27575bcbc68db1f6d06218891296572c9b845704" + "reference": "fa8f8cab6b65e2d99a118e082935344c5ba8c60d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/27575bcbc68db1f6d06218891296572c9b845704", - "reference": "27575bcbc68db1f6d06218891296572c9b845704", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/fa8f8cab6b65e2d99a118e082935344c5ba8c60d", + "reference": "fa8f8cab6b65e2d99a118e082935344c5ba8c60d", "shasum": "" }, "require": { - "php": ">=7.1.3", + "php": ">=7.2.5", "symfony/polyfill-ctype": "~1.8" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.4-dev" - } - }, "autoload": { "psr-4": { "Symfony\\Component\\Filesystem\\": "" @@ -8408,6 +9116,9 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/filesystem/tree/v5.2.1" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -8422,47 +9133,7 @@ "type": "tidelift" } ], - "time": "2020-08-21T17:19:37+00:00" - }, - { - "name": "theseer/fdomdocument", - "version": "1.6.6", - "source": { - "type": "git", - "url": "https://github.com/theseer/fDOMDocument.git", - "reference": "6e8203e40a32a9c770bcb62fe37e68b948da6dca" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/theseer/fDOMDocument/zipball/6e8203e40a32a9c770bcb62fe37e68b948da6dca", - "reference": "6e8203e40a32a9c770bcb62fe37e68b948da6dca", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "lib-libxml": "*", - "php": ">=5.3.3" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "role": "lead", - "email": "arne@blankerts.de" - } - ], - "description": "The classes contained within this repository extend the standard DOM to use exceptions at all occasions of errors instead of PHP warnings or notices. They also add various custom methods and shortcuts for convenience and to simplify the usage of DOM.", - "homepage": "https://github.com/theseer/fDOMDocument", - "time": "2017-06-30T11:53:12+00:00" + "time": "2020-11-30T17:05:38+00:00" }, { "name": "theseer/tokenizer", @@ -8502,6 +9173,10 @@ } ], "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/master" + }, "funding": [ { "url": "https://github.com/theseer", @@ -8557,71 +9232,11 @@ "check", "validate" ], + "support": { + "issues": "https://github.com/webmozart/assert/issues", + "source": "https://github.com/webmozart/assert/tree/master" + }, "time": "2020-07-08T17:02:28+00:00" - }, - { - "name": "wnx/laravel-stats", - "version": "v2.0.2", - "source": { - "type": "git", - "url": "https://github.com/stefanzweifel/laravel-stats.git", - "reference": "e86ebfdd149383b18a41fe3efa1601d82d447140" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/stefanzweifel/laravel-stats/zipball/e86ebfdd149383b18a41fe3efa1601d82d447140", - "reference": "e86ebfdd149383b18a41fe3efa1601d82d447140", - "shasum": "" - }, - "require": { - "illuminate/console": "~5.8.0|^6.0|^7.0", - "illuminate/support": "~5.8.0|^6.0|^7.0", - "php": ">=7.2.0", - "phploc/phploc": "~5.0|~6.0", - "symfony/finder": "~4.0" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "^2.15", - "laravel/browser-kit-testing": "~5.0", - "laravel/dusk": "~5.0", - "mockery/mockery": "^1.1", - "orchestra/testbench": "^3.8|^4.0|^5.0", - "phpunit/phpunit": "8.*|9.*" - }, - "type": "library", - "extra": { - "laravel": { - "providers": [ - "Wnx\\LaravelStats\\StatsServiceProvider" - ] - } - }, - "autoload": { - "psr-4": { - "Wnx\\LaravelStats\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Stefan Zweifel", - "email": "hello@stefanzweifel.io", - "homepage": "https://stefanzweifel.io", - "role": "Developer" - } - ], - "description": "Get insights about your Laravel Project", - "homepage": "https://github.com/stefanzweifel/laravel-stats", - "keywords": [ - "laravel", - "statistics", - "stats", - "wnx" - ], - "time": "2020-02-22T19:09:14+00:00" } ], "aliases": [], @@ -8630,7 +9245,7 @@ "prefer-stable": true, "prefer-lowest": false, "platform": { - "php": "^7.2", + "php": "^7.2.5", "ext-curl": "*", "ext-dom": "*", "ext-gd": "*", @@ -8640,7 +9255,7 @@ }, "platform-dev": [], "platform-overrides": { - "php": "7.2.0" + "php": "7.2.5" }, "plugin-api-version": "2.0.0" } From 4b4642c8ea58aa91cfe9b83095d2d420f608ad4d Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Fri, 18 Dec 2020 21:26:22 +0000 Subject: [PATCH 47/72] Aligned book and shelf grid item views Updated the titles so they are limited via CSS rather than by a estimated hardcoded limit. For #1469 --- resources/sass/_colors.scss | 2 +- resources/sass/_text.scss | 11 +++++++++- resources/views/books/grid-item.blade.php | 19 ----------------- resources/views/books/list.blade.php | 3 +-- resources/views/pages/show.blade.php | 2 +- .../views/partials/entity-grid-item.blade.php | 16 ++++++++++++++ resources/views/shelves/grid-item.blade.php | 21 ------------------- resources/views/shelves/list-item.blade.php | 2 +- resources/views/shelves/list.blade.php | 2 +- resources/views/shelves/show.blade.php | 2 +- 10 files changed, 32 insertions(+), 48 deletions(-) delete mode 100644 resources/views/books/grid-item.blade.php create mode 100644 resources/views/partials/entity-grid-item.blade.php delete mode 100644 resources/views/shelves/grid-item.blade.php diff --git a/resources/sass/_colors.scss b/resources/sass/_colors.scss index e01ecebc9..c51f01659 100644 --- a/resources/sass/_colors.scss +++ b/resources/sass/_colors.scss @@ -92,6 +92,6 @@ .bg-chapter { background-color: var(--color-chapter); } -.bg-shelf { +.bg-bookshelf { background-color: var(--color-bookshelf); } diff --git a/resources/sass/_text.scss b/resources/sass/_text.scss index 4ada34725..4322cb5a6 100644 --- a/resources/sass/_text.scss +++ b/resources/sass/_text.scss @@ -352,12 +352,21 @@ li > ol, li > ul { overflow-wrap: break-word; } -.limit-text { +.text-limit-lines-1 { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } +.text-limit-lines-2 { + // -webkit use here is actually standardised cross-browser: + // https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-line-clamp + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; + overflow: hidden; +} + /** * Grouping */ diff --git a/resources/views/books/grid-item.blade.php b/resources/views/books/grid-item.blade.php deleted file mode 100644 index e1d37753a..000000000 --- a/resources/views/books/grid-item.blade.php +++ /dev/null @@ -1,19 +0,0 @@ - - -
    -

    {{$book->getShortName(35)}}

    - @if(isset($book->searchSnippet)) -

    {!! $book->searchSnippet !!}

    - @else -

    {{ $book->getExcerpt(130) }}

    - @endif -
    - -
    \ No newline at end of file diff --git a/resources/views/books/list.blade.php b/resources/views/books/list.blade.php index 42a2757f9..52cd935d1 100644 --- a/resources/views/books/list.blade.php +++ b/resources/views/books/list.blade.php @@ -1,4 +1,3 @@ -

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

    @@ -22,7 +21,7 @@ @else
    @foreach($books as $key => $book) - @include('books.grid-item', ['book' => $book]) + @include('partials.entity-grid-item', ['entity' => $book]) @endforeach
    @endif diff --git a/resources/views/pages/show.blade.php b/resources/views/pages/show.blade.php index 48c88434e..13125464a 100644 --- a/resources/views/pages/show.blade.php +++ b/resources/views/pages/show.blade.php @@ -49,7 +49,7 @@