composer update

This commit is contained in:
isUnknown 2025-09-23 08:15:07 +02:00
parent 0b3c362c5e
commit a1f0701630
142 changed files with 4530 additions and 1195 deletions

View file

@ -1,7 +1,9 @@
<?php
use Kirby\Cms\File;
use Kirby\Cms\Files;
use Kirby\Panel\Collector\FilesCollector;
use Kirby\Panel\Ui\Item\FileItem;
use Kirby\Panel\Ui\Upload;
use Kirby\Toolkit\I18n;
return [
@ -56,86 +58,40 @@ return [
'parent' => function () {
return $this->parentModel();
},
'collector' => function () {
return $this->collector ??= new FilesCollector(
flip: $this->flip(),
limit: $this->limit(),
page: $this->page() ?? 1,
parent: $this->parent(),
query: $this->query(),
search: $this->searchterm(),
sortBy: $this->sortBy(),
template: $this->template(),
);
},
'models' => function () {
if ($this->query !== null) {
$files = $this->parent->query($this->query, Files::class) ?? new Files([]);
} else {
$files = $this->parent->files();
}
// filter files by template
$files = $files->template($this->template);
// filter out all protected and hidden files
$files = $files->filter('isListable', true);
// search
if ($this->search === true && empty($this->searchterm()) === false) {
$files = $files->search($this->searchterm());
// disable flip and sortBy while searching
// to show most relevant results
$this->flip = false;
$this->sortBy = null;
}
// sort
if ($this->sortBy) {
$files = $files->sort(...$files::sortArgs($this->sortBy));
} else {
$files = $files->sorted();
}
// flip
if ($this->flip === true) {
$files = $files->flip();
}
return $files;
return $this->collector()->models();
},
'modelsPaginated' => function () {
// apply the default pagination
return $this->models()->paginate([
'page' => $this->page,
'limit' => $this->limit,
'method' => 'none' // the page is manually provided
]);
return $this->collector()->models(paginated: true);
},
'files' => function () {
return $this->models;
},
'data' => function () {
$data = [];
$data = [];
$dragTextIsAbsolute = $this->model->is($this->parent) === false;
foreach ($this->modelsPaginated() as $file) {
$panel = $file->panel();
$permissions = $file->permissions();
$item = [
'dragText' => $panel->dragText(
// the drag text needs to be absolute
// when the files come from a different parent model
absolute: $this->model->is($this->parent) === false
),
'extension' => $file->extension(),
'filename' => $file->filename(),
'id' => $file->id(),
'image' => $panel->image(
$this->image,
$this->layout === 'table' ? 'list' : $this->layout
),
'info' => $file->toSafeString($this->info ?? false),
'link' => $panel->url(true),
'mime' => $file->mime(),
'parent' => $file->parent()->panel()->path(),
'permissions' => [
'delete' => $permissions->can('delete'),
'sort' => $permissions->can('sort'),
],
'template' => $file->template(),
'text' => $file->toSafeString($this->text),
'url' => $file->url(),
];
$item = (new FileItem(
file: $file,
dragTextIsAbsolute: $dragTextIsAbsolute,
image: $this->image,
layout: $this->layout,
info: $this->info,
text: $this->text,
))->props();
if ($this->layout === 'table') {
$item = $this->columnsValues($item, $file);
@ -185,26 +141,16 @@ return [
return false;
}
// count all uploaded files
$max = $this->max ? $this->max - $this->total : null;
$multiple = !$max || $max > 1;
$template = $this->template === 'default' ? null : $this->template;
$settings = new Upload(
api: $this->parent->apiUrl(true) . '/files',
accept: $this->accept,
max: $this->max ? $this->max - $this->total : null,
preview: $this->image,
sort: $this->sortable === true ? $this->total + 1 : null,
template: $this->template,
);
return [
'accept' => $this->accept,
'multiple' => $multiple,
'max' => $max,
'api' => $this->parent->apiUrl(true) . '/files',
'preview' => $this->image,
'attributes' => [
// TODO: an edge issue that needs to be solved:
// if multiple users load the same section
// at the same time and upload a file,
// uploaded files have the same sort number
'sort' => $this->sortable === true ? $this->total + 1 : null,
'template' => $template
]
];
return $settings->props();
}
],
// @codeCoverageIgnoreStart

View file

@ -13,7 +13,11 @@ return [
],
'methods' => [
'searchterm' => function (): string|null {
return App::instance()->request()->get('searchterm');
if ($this->search() === true) {
return App::instance()->request()->get('searchterm') ?? null;
}
return null;
}
]
];

View file

@ -5,6 +5,8 @@ use Kirby\Cms\Page;
use Kirby\Cms\Pages;
use Kirby\Cms\Site;
use Kirby\Exception\InvalidArgumentException;
use Kirby\Panel\Collector\PagesCollector;
use Kirby\Panel\Ui\Item\PageItem;
use Kirby\Toolkit\A;
use Kirby\Toolkit\I18n;
@ -85,83 +87,28 @@ return [
return $parent;
},
'collector' => function () {
return $this->collector ??= new PagesCollector(
limit: $this->limit(),
page: $this->page() ?? 1,
parent: $this->parent(),
query: $this->query(),
status: $this->status(),
templates: $this->templates(),
templatesIgnore: $this->templatesIgnore(),
search: $this->searchterm(),
sortBy: $this->sortBy(),
flip: $this->flip()
);
},
'models' => function () {
if ($this->query !== null) {
$pages = $this->parent->query($this->query, Pages::class) ?? new Pages([]);
} else {
$pages = match ($this->status) {
'draft' => $this->parent->drafts(),
'listed' => $this->parent->children()->listed(),
'published' => $this->parent->children(),
'unlisted' => $this->parent->children()->unlisted(),
default => $this->parent->childrenAndDrafts()
};
}
// filters pages that are protected and not in the templates list
// internal `filter()` method used instead of foreach loop that previously included `unset()`
// because `unset()` is updating the original data, `filter()` is just filtering
// also it has been tested that there is no performance difference
// even in 0.1 seconds on 100k virtual pages
$pages = $pages->filter(function ($page) {
// remove all protected and hidden pages
if ($page->isListable() === false) {
return false;
}
$intendedTemplate = $page->intendedTemplate()->name();
// filter by all set templates
if (
$this->templates &&
in_array($intendedTemplate, $this->templates, true) === false
) {
return false;
}
// exclude by all ignored templates
if (
$this->templatesIgnore &&
in_array($intendedTemplate, $this->templatesIgnore, true) === true
) {
return false;
}
return true;
});
// search
if ($this->search === true && empty($this->searchterm()) === false) {
$pages = $pages->search($this->searchterm());
// disable flip and sortBy while searching
// to show most relevant results
$this->flip = false;
$this->sortBy = null;
}
// sort
if ($this->sortBy) {
$pages = $pages->sort(...$pages::sortArgs($this->sortBy));
}
// flip
if ($this->flip === true) {
$pages = $pages->flip();
}
return $pages;
return $this->collector()->models();
},
'modelsPaginated' => function () {
// pagination
return $this->models()->paginate([
'page' => $this->page,
'limit' => $this->limit,
'method' => 'none' // the page is manually provided
]);
return $this->collector()->models(paginated: true);
},
'pages' => function () {
return $this->models;
return $this->models();
},
'total' => function () {
return $this->models()->count();
@ -170,30 +117,13 @@ return [
$data = [];
foreach ($this->modelsPaginated() as $page) {
$panel = $page->panel();
$permissions = $page->permissions();
$item = [
'dragText' => $panel->dragText(),
'id' => $page->id(),
'image' => $panel->image(
$this->image,
$this->layout === 'table' ? 'list' : $this->layout
),
'info' => $page->toSafeString($this->info ?? false),
'link' => $panel->url(true),
'parent' => $page->parentId(),
'permissions' => [
'delete' => $permissions->can('delete'),
'changeSlug' => $permissions->can('changeSlug'),
'changeStatus' => $permissions->can('changeStatus'),
'changeTitle' => $permissions->can('changeTitle'),
'sort' => $permissions->can('sort'),
],
'status' => $page->status(),
'template' => $page->intendedTemplate()->name(),
'text' => $page->toSafeString($this->text),
];
$item = (new PageItem(
page: $page,
image: $this->image,
layout: $this->layout,
info: $this->info,
text: $this->text,
))->props();
if ($this->layout === 'table') {
$item = $this->columnsValues($item, $page);

View file

@ -1,6 +1,6 @@
<?php
use Kirby\Toolkit\I18n;
use Kirby\Panel\Ui\Stats;
return [
'mixins' => [
@ -10,20 +10,8 @@ return [
/**
* Array or query string for reports. Each report needs a `label` and `value` and can have additional `info`, `link`, `icon` and `theme` settings.
*/
'reports' => function ($reports = null) {
if ($reports === null) {
return [];
}
if (is_string($reports) === true) {
$reports = $this->model()->query($reports);
}
if (is_array($reports) === false) {
return [];
}
return $reports;
'reports' => function (array|string|null $reports = null) {
return $reports ?? [];
},
/**
* The size of the report cards. Available sizes: `tiny`, `small`, `medium`, `large`
@ -33,36 +21,18 @@ return [
}
],
'computed' => [
'reports' => function () {
$reports = [];
$model = $this->model();
$toString = fn ($value) => $value === null ? null : $model->toString($value);
foreach ($this->reports as $report) {
if (is_string($report) === true) {
$report = $model->query($report);
}
if (is_array($report) === false) {
continue;
}
$info = $report['info'] ?? null;
$label = $report['label'] ?? null;
$link = $report['link'] ?? null;
$value = $report['value'] ?? null;
$reports[] = [
'icon' => $toString($report['icon'] ?? null),
'info' => $toString(I18n::translate($info, $info)),
'label' => $toString(I18n::translate($label, $label)),
'link' => $toString(I18n::translate($link, $link)),
'theme' => $toString($report['theme'] ?? null),
'value' => $toString(I18n::translate($value, $value))
];
}
return $reports;
'stats' => function (): Stats {
return $this->stats ??= Stats::from(
model: $this->model(),
reports: $this->reports(),
size: $this->size()
);
},
'reports' => function (): array {
return $this->stats->reports();
},
'size' => function (): string {
return $this->stats->size();
}
]
];