update kirby to v5 and add refresh cache panel view button

This commit is contained in:
isUnknown 2025-09-10 14:28:38 +02:00
commit 9a86d41254
466 changed files with 19960 additions and 10497 deletions

View file

@ -7,6 +7,7 @@ return function () {
'icon' => 'account',
'label' => I18n::translate('view.account'),
'search' => 'users',
'buttons' => require __DIR__ . '/account/buttons.php',
'dialogs' => require __DIR__ . '/account/dialogs.php',
'drawers' => require __DIR__ . '/account/drawers.php',
'dropdowns' => require __DIR__ . '/account/dropdowns.php',

View file

@ -0,0 +1,13 @@
<?php
use Kirby\Cms\App;
use Kirby\Cms\User;
use Kirby\Panel\Ui\Buttons\ViewButton;
return [
'user.theme' => function (App $kirby, User $user) {
if ($kirby->user()->is($user) === true) {
return new ViewButton(component: 'k-theme-view-button');
}
}
];

View file

@ -5,7 +5,6 @@ use Kirby\Panel\UserTotpEnableDialog;
$dialogs = require __DIR__ . '/../users/dialogs.php';
return [
// change email
'account.changeEmail' => [
'pattern' => '(account)/changeEmail',

View file

@ -7,8 +7,16 @@ return [
'pattern' => '(account)',
'options' => $dropdowns['user']['options']
],
'account.languages' => [
'pattern' => '(account)/languages',
'options' => $dropdowns['user.languages']['options']
],
'account.file' => [
'pattern' => '(account)/files/(:any)',
'options' => $dropdowns['user.file']['options']
],
'account.file.languages' => [
'pattern' => '(account)/files/(:any)/languages',
'options' => $files['language']
]
];

View file

@ -26,6 +26,9 @@ return [
[
'label' => I18n::translate('view.resetPassword')
]
],
'props' => [
'requirePassword' => App::instance()->session()->get('kirby.resetPassword') !== true
]
]
]

View file

@ -0,0 +1,14 @@
<?php
use Kirby\Cms\File;
use Kirby\Panel\Ui\Buttons\OpenButton;
use Kirby\Panel\Ui\Buttons\SettingsButton;
return [
'file.open' => function (File $file) {
return new OpenButton(link: $file->previewUrl());
},
'file.settings' => function (File $file) {
return new SettingsButton(model: $file);
}
];

View file

@ -45,13 +45,7 @@ return [
$oldUrl = $file->panel()->url(true);
$newUrl = $renamed->panel()->url(true);
$response = [
'event' => 'file.changeName',
'dispatch' => [
'content/move' => [
$oldUrl,
$newUrl
]
],
'event' => 'file.changeName'
];
// check for a necessary redirect after the filename has changed
@ -163,7 +157,6 @@ return [
return [
'event' => 'file.delete',
'dispatch' => ['content/remove' => [$url]],
'redirect' => $redirect
];
}

View file

@ -1,9 +1,14 @@
<?php
use Kirby\Cms\Find;
use Kirby\Panel\Ui\Buttons\LanguagesDropdown;
return [
'file' => function (string $parent, string $filename) {
return Find::file($parent, $filename)->panel()->dropdown();
},
'language' => function (string $parent, string $filename) {
$file = Find::file($parent, $filename);
return (new LanguagesDropdown($file))->options();
}
];

View file

@ -1,12 +1,13 @@
<?php
use Kirby\Panel\Lab\Doc;
use Kirby\Panel\Lab\Docs;
return [
'lab.docs' => [
'pattern' => 'lab/docs/(:any)',
'load' => function (string $component) {
if (Docs::installed() === false) {
if (Docs::isInstalled() === false) {
return [
'component' => 'k-text-drawer',
'props' => [
@ -15,14 +16,12 @@ return [
];
}
$docs = new Docs($component);
return [
'component' => 'k-lab-docs-drawer',
'props' => [
'icon' => 'book',
'title' => $component,
'docs' => $docs->toArray()
'docs' => Doc::factory($component)->toArray()
]
];
},

View file

@ -2,6 +2,7 @@
use Kirby\Cms\App;
use Kirby\Panel\Lab\Category;
use Kirby\Panel\Lab\Doc;
use Kirby\Panel\Lab\Docs;
return [
@ -12,7 +13,7 @@ return [
'component' => 'k-lab-index-view',
'props' => [
'categories' => Category::all(),
'info' => Category::installed() ? null : 'The default Lab examples are not installed.',
'info' => Category::isInstalled() ? null : 'The default Lab examples are not installed.',
'tab' => 'examples',
],
];
@ -21,18 +22,7 @@ return [
'lab.docs' => [
'pattern' => 'lab/docs',
'action' => function () {
$props = match (Docs::installed()) {
true => [
'categories' => [['examples' => Docs::all()]],
'tab' => 'docs',
],
false => [
'info' => 'The UI docs are not installed.',
'tab' => 'docs',
]
};
return [
$view = [
'component' => 'k-lab-index-view',
'title' => 'Docs',
'breadcrumb' => [
@ -40,8 +30,28 @@ return [
'label' => 'Docs',
'link' => 'lab/docs'
]
]
];
// if docs are not installed, show info message
if (Docs::isInstalled() === false) {
return [
...$view,
'props' => [
'info' => 'The UI docs are not installed.',
'tab' => 'docs',
],
];
}
return [
...$view,
'props' => [
'categories' => [
['examples' => Docs::all()]
],
'tab' => 'docs',
],
'props' => $props,
];
}
],
@ -59,7 +69,7 @@ return [
]
];
if (Docs::installed() === false) {
if (Docs::isInstalled() === false) {
return [
'component' => 'k-lab-index-view',
'title' => $component,
@ -71,16 +81,50 @@ return [
];
}
$docs = new Docs($component);
$doc = Doc::factory($component);
if ($doc === null) {
return [
'component' => 'k-lab-index-view',
'title' => $component,
'breadcrumb' => $crumbs,
'props' => [
'info' => 'No UI docs found for ' . $component . '.',
'tab' => 'docs',
],
];
}
// header buttons
$buttons = [];
if ($lab = $doc->lab()) {
$buttons[] = [
'props' => [
'text' => 'Lab examples',
'icon' => 'lab',
'link' => '/lab/' . $lab
]
];
}
$buttons[] = [
'props' => [
'icon' => 'github',
'link' => $doc->source(),
'target' => '_blank'
]
];
return [
'component' => 'k-lab-docs-view',
'title' => $component,
'breadcrumb' => $crumbs,
'props' => [
'buttons' => $buttons,
'component' => $component,
'docs' => $docs->toArray(),
'lab' => $docs->lab()
'docs' => $doc->toArray(),
'lab' => $lab
]
];
}
@ -111,16 +155,39 @@ return [
$vue = $example->vue();
$compiler = App::instance()->option('panel.vue.compiler', true);
if (Docs::installed() === true && $docs = $props['docs'] ?? null) {
$docs = new Docs($docs);
if ($doc = $props['docs'] ?? null) {
$doc = Doc::factory($doc);
}
$github = $docs?->github();
$github = $doc?->source();
if ($source = $props['source'] ?? null) {
$github ??= 'https://github.com/getkirby/kirby/tree/main/' . $source;
}
// header buttons
$buttons = [];
if ($doc) {
$buttons[] = [
'props' => [
'text' => $doc->name,
'icon' => 'book',
'drawer' => 'lab/docs/' . $doc->name
]
];
}
if ($github) {
$buttons[] = [
'props' => [
'icon' => 'github',
'link' => $github,
'target' => '_blank'
]
];
}
return [
'component' => 'k-lab-playground-view',
'breadcrumb' => [
@ -133,8 +200,9 @@ return [
]
],
'props' => [
'buttons' => $buttons,
'compiler' => $compiler,
'docs' => $docs?->name(),
'docs' => $doc?->name,
'examples' => $vue['examples'],
'file' => $example->module(),
'github' => $github,

View file

@ -7,6 +7,7 @@ return function ($kirby) {
'icon' => 'translate',
'label' => I18n::translate('view.languages'),
'menu' => true,
'buttons' => require __DIR__ . '/languages/buttons.php',
'dialogs' => require __DIR__ . '/languages/dialogs.php',
'views' => require __DIR__ . '/languages/views.php'
];

View file

@ -0,0 +1,21 @@
<?php
use Kirby\Cms\Language;
use Kirby\Panel\Ui\Buttons\LanguageCreateButton;
use Kirby\Panel\Ui\Buttons\LanguageDeleteButton;
use Kirby\Panel\Ui\Buttons\LanguageSettingsButton;
use Kirby\Panel\Ui\Buttons\OpenButton;
return [
'languages.create' => fn () =>
new LanguageCreateButton(),
'language.open' => fn (Language $language) =>
new OpenButton(link: $language->url()),
'language.settings' => fn (Language $language) =>
new LanguageSettingsButton($language),
'language.delete' => function (Language $language) {
if ($language->isDeletable() === true) {
return new LanguageDeleteButton($language);
}
}
];

View file

@ -2,6 +2,7 @@
use Kirby\Cms\App;
use Kirby\Cms\Find;
use Kirby\Cms\Language;
use Kirby\Cms\LanguageVariable;
use Kirby\Exception\NotFoundException;
use Kirby\Toolkit\A;
@ -49,16 +50,34 @@ $translationDialogFields = [
'label' => I18n::translate('language.variable.key'),
'type' => 'text'
],
'multiple' => [
'label' => I18n::translate('language.variable.multiple'),
'text' => I18n::translate('language.variable.multiple.text'),
'help' => I18n::translate('language.variable.multiple.help'),
'type' => 'toggle'
],
'value' => [
'buttons' => false,
'counter' => false,
'label' => I18n::translate('language.variable.value'),
'type' => 'textarea'
'type' => 'textarea',
'when' => [
'multiple' => false
]
],
'entries' => [
'field' => ['type' => 'text'],
'label' => I18n::translate('language.variable.entries'),
'help' => I18n::translate('language.variable.entries.help'),
'type' => 'entries',
'min' => 1,
'when' => [
'multiple' => true
],
]
];
return [
// create language
'language.create' => [
'pattern' => 'languages/create',
@ -184,6 +203,9 @@ return [
'props' => [
'fields' => $translationDialogFields,
'size' => 'large',
'value' => [
'multiple' => false,
]
],
];
},
@ -191,8 +213,13 @@ return [
$request = App::instance()->request();
$language = Find::language($languageCode);
$key = $request->get('key', '');
$value = $request->get('value', '');
$key = $request->get('key', '');
$multiple = $request->get('multiple', false);
$value = match ($multiple) {
true => $request->get('entries', []),
default => $request->get('value', '')
};
LanguageVariable::create($key, $value);
@ -209,9 +236,9 @@ return [
$variable = Find::language($languageCode)->variable($translationKey, true);
if ($variable->exists() === false) {
throw new NotFoundException([
'key' => 'language.variable.notFound'
]);
throw new NotFoundException(
key: 'language.variable.notFound'
);
}
return [
@ -230,48 +257,65 @@ return [
'language.translation.update' => [
'pattern' => 'languages/(:any)/translations/(:any)/update',
'load' => function (string $languageCode, string $translationKey) use ($translationDialogFields) {
$variable = Find::language($languageCode)->variable($translationKey, true);
$language = Find::language($languageCode);
$variable = $language->variable($translationKey, true);
if ($variable->exists() === false) {
throw new NotFoundException([
'key' => 'language.variable.notFound'
]);
throw new NotFoundException(
key: 'language.variable.notFound'
);
}
$fields = $translationDialogFields;
$fields['key']['disabled'] = true;
$fields['value']['autofocus'] = true;
// shows info text when variable is an array
// TODO: 5.0: use entries field instead showing info text
$isVariableArray = is_array($variable->value()) === true;
// the key field cannot be changed
// the multiple field is hidden
$fields['key']['disabled'] = true;
$fields['multiple']['type'] = 'hidden';
// check if the variable has multiple values;
// ensure to use the default language for this check because
// the variable might not exist in the current language but
// already be defined in the default language with multiple values
$isVariableArray = Language::ensure('default')->variable($translationKey, true)->hasMultipleValues();
// set the correct value field
// when value is string, set value for value field
// when value is array, set value for entries field
if ($isVariableArray === true) {
$fields['value'] = [
'label' => I18n::translate('info'),
'type' => 'info',
'text' => 'You are using an array variable for this key. Please modify it in the language file in /site/languages',
$fields['entries']['autofocus'] = true;
$value = [
'entries' => $variable->value(),
'key' => $variable->key(),
'multiple' => true
];
} else {
$fields['value']['autofocus'] = true;
$value = [
'key' => $variable->key(),
'multiple' => false,
'value' => $variable->value()
];
}
return [
'component' => 'k-form-dialog',
'props' => [
'cancelButton' => $isVariableArray === false,
'fields' => $fields,
'size' => 'large',
'submitButton' => $isVariableArray === false,
'value' => [
'key' => $variable->key(),
'value' => $variable->value()
]
],
'fields' => $fields,
'size' => 'large',
'value' => $value
]
];
},
'submit' => function (string $languageCode, string $translationKey) {
Find::language($languageCode)->variable($translationKey, true)->update(
App::instance()->request()->get('value', '')
);
$request = App::instance()->request();
$multiple = $request->get('multiple', false);
$value = match ($multiple) {
true => $request->get('entries', []),
default => $request->get('value', '')
};
Find::language($languageCode)->variable($translationKey, true)->update($value);
return true;
}

View file

@ -2,6 +2,7 @@
use Kirby\Cms\App;
use Kirby\Cms\Find;
use Kirby\Panel\Ui\Buttons\ViewButtons;
use Kirby\Toolkit\Escape;
use Kirby\Toolkit\I18n;
@ -19,9 +20,9 @@ return [
$foundation = $kirby->defaultLanguage()->translations();
$translations = $language->translations();
// TODO: update following line and adapt for update and delete options
// when new `languageVariables.*` permissions available
$canUpdate = $kirby->user()?->role()->permissions()->for('languages', 'update') === true;
// TODO: update following line and adapt for update and
// delete options when `languageVariables.*` permissions available
$canUpdate = $kirby->role()?->permissions()->for('languages', 'update') === true;
ksort($foundation);
@ -73,6 +74,10 @@ return [
]
],
'props' => [
'buttons' => fn () =>
ViewButtons::view('language', model: $language)
->defaults('open', 'settings', 'delete')
->render(),
'deletable' => $language->isDeletable(),
'code' => Escape::html($language->code()),
'default' => $language->isDefault(),
@ -113,6 +118,10 @@ return [
return [
'component' => 'k-languages-view',
'props' => [
'buttons' => fn () =>
ViewButtons::view('languages')
->defaults('create')
->render(),
'languages' => $kirby->languages()->values(fn ($language) => [
'deletable' => $language->isDeletable(),
'default' => $language->isDefault(),

View file

@ -36,7 +36,7 @@ return function ($kirby) {
* be used to redirect to that view again
*/
$kirby->session()->set('panel.path', $path);
Panel::go('login');
Panel::go(url: 'login', refresh: 0);
}
]
]

View file

@ -12,6 +12,7 @@ return function ($kirby) {
'icon' => $blueprint->icon() ?? 'home',
'label' => $blueprint->title() ?? I18n::translate('view.site'),
'menu' => true,
'buttons' => require __DIR__ . '/site/buttons.php',
'dialogs' => require __DIR__ . '/site/dialogs.php',
'drawers' => require __DIR__ . '/site/drawers.php',
'dropdowns' => require __DIR__ . '/site/dropdowns.php',

View file

@ -0,0 +1,72 @@
<?php
use Kirby\Cms\ModelWithContent;
use Kirby\Cms\Page;
use Kirby\Cms\Site;
use Kirby\Panel\Ui\Buttons\LanguagesDropdown;
use Kirby\Panel\Ui\Buttons\OpenButton;
use Kirby\Panel\Ui\Buttons\PageStatusButton;
use Kirby\Panel\Ui\Buttons\PreviewButton;
use Kirby\Panel\Ui\Buttons\SettingsButton;
use Kirby\Panel\Ui\Buttons\VersionsButton;
return [
'site.open' => function (Site $site, string $versionId = 'latest') {
$versionId = $versionId === 'compare' ? 'changes' : $versionId;
$link = $site->previewUrl($versionId);
if ($link !== null) {
return new OpenButton(
link: $link,
);
}
},
'site.preview' => function (Site $site) {
if ($site->previewUrl() !== null) {
return new PreviewButton(
link: $site->panel()->url(true) . '/preview/changes',
);
}
},
'site.versions' => function (Site $site, string $versionId = 'latest') {
return new VersionsButton(
model: $site,
versionId: $versionId
);
},
'page.open' => function (Page $page, string $versionId = 'latest') {
$versionId = $versionId === 'compare' ? 'changes' : $versionId;
$link = $page->previewUrl($versionId);
if ($link !== null) {
return new OpenButton(
link: $link,
);
}
},
'page.preview' => function (Page $page) {
if ($page->previewUrl() !== null) {
return new PreviewButton(
link: $page->panel()->url(true) . '/preview/changes',
);
}
},
'page.versions' => function (Page $page, string $versionId = 'latest') {
return new VersionsButton(
model: $page,
versionId: $versionId
);
},
'page.settings' => fn (Page $page) => new SettingsButton(model: $page),
'page.status' => fn (Page $page) => new PageStatusButton($page),
// `languages` button needs to be in site area,
// as the languages might be not loaded even in
// multilang mode when the `languages` option is deactivated
// (but content languages to switch between still can exist)
'languages' => fn (ModelWithContent $model) =>
new LanguagesDropdown($model),
// file buttons
...require __DIR__ . '/../files/buttons.php'
];

View file

@ -28,12 +28,10 @@ return [
$page = Find::page($id);
if ($page->blueprint()->num() !== 'default') {
throw new PermissionException([
'key' => 'page.sort.permission',
'data' => [
'slug' => $page->slug()
]
]);
throw new PermissionException(
key: 'page.sort.permission',
data: ['slug' => $page->slug()]
);
}
return [
@ -150,12 +148,10 @@ return [
$blueprints = $page->blueprints();
if (count($blueprints) <= 1) {
throw new Exception([
'key' => 'page.changeTemplate.invalid',
'data' => [
'slug' => $id
]
]);
throw new Exception(
key: 'page.changeTemplate.invalid',
data: ['slug' => $id]
);
}
return [
@ -264,20 +260,17 @@ return [
// the page title changed
if ($page->title()->value() !== $title) {
$page->changeTitle($title);
$page = $page->changeTitle($title);
$response['event'][] = 'page.changeTitle';
}
// the slug changed
if ($page->slug() !== $slug) {
$newPage = $page->changeSlug($slug);
$response['event'][] = 'page.changeSlug';
$response['dispatch'] = [
'content/move' => [
$oldUrl = $page->panel()->url(true),
$newUrl = $newPage->panel()->url(true)
]
];
$newPage = $page->changeSlug($slug);
$oldUrl = $page->panel()->url(true);
$newUrl = $newPage->panel()->url(true);
// check for a necessary redirect after the slug has changed
if (Panel::referrer() === $oldUrl && $oldUrl !== $newUrl) {
@ -372,7 +365,9 @@ return [
$page->childrenAndDrafts()->count() > 0 &&
$request->get('check') !== $page->title()->value()
) {
throw new InvalidArgumentException(['key' => 'page.delete.confirm']);
throw new InvalidArgumentException(
key: 'page.delete.confirm'
);
}
$page->delete(true);
@ -385,7 +380,6 @@ return [
return [
'event' => 'page.delete',
'dispatch' => ['content/remove' => [$url]],
'redirect' => $redirect
];
}
@ -416,19 +410,17 @@ return [
if ($hasFiles === true) {
$fields['files'] = [
'label' => I18n::translate('page.duplicate.files'),
'type' => 'toggle',
'required' => true,
'width' => $toggleWidth
'label' => I18n::translate('page.duplicate.files'),
'type' => 'toggle',
'width' => $toggleWidth
];
}
if ($hasChildren === true) {
$fields['children'] = [
'label' => I18n::translate('page.duplicate.pages'),
'type' => 'toggle',
'required' => true,
'width' => $toggleWidth
'label' => I18n::translate('page.duplicate.pages'),
'type' => 'toggle',
'width' => $toggleWidth
];
}
@ -440,11 +432,11 @@ return [
$duplicateSlug = $page->slug() . '-' . $slugAppendix;
$siblingKeys = $page->parentModel()->childrenAndDrafts()->pluck('uid');
if (in_array($duplicateSlug, $siblingKeys) === true) {
if (in_array($duplicateSlug, $siblingKeys, true) === true) {
$suffixCounter = 2;
$newSlug = $duplicateSlug . $suffixCounter;
while (in_array($newSlug, $siblingKeys) === true) {
while (in_array($newSlug, $siblingKeys, true) === true) {
$newSlug = $duplicateSlug . ++$suffixCounter;
}
@ -556,13 +548,7 @@ return [
return [
'event' => 'page.move',
'redirect' => $newPage->panel()->url(true),
'dispatch' => [
'content/move' => [
$oldPage->panel()->url(true),
$newPage->panel()->url(true)
]
],
'redirect' => $newPage->panel()->url(true)
];
}
],
@ -643,13 +629,7 @@ return [
'changes' => [
'pattern' => 'changes',
'load' => function () {
$dialog = new ChangesDialog();
return $dialog->load();
return (new ChangesDialog())->load();
},
'submit' => function () {
$dialog = new ChangesDialog();
$ids = App::instance()->request()->get('ids');
return $dialog->submit($ids);
}
],
];

View file

@ -1,5 +1,8 @@
<?php
use Kirby\Cms\App;
use Kirby\Cms\Find;
use Kirby\Panel\Ui\Buttons\LanguagesDropdown;
$files = require __DIR__ . '/../files/dropdowns.php';
@ -10,12 +13,34 @@ return [
return Find::page($path)->panel()->dropdown();
}
],
'page.languages' => [
'pattern' => 'pages/(:any)/languages',
'options' => function (string $path) {
$page = Find::page($path);
return (new LanguagesDropdown($page))->options();
}
],
'page.file' => [
'pattern' => '(pages/.*?)/files/(:any)',
'options' => $files['file']
],
'page.file.languages' => [
'pattern' => '(pages/.*?)/files/(:any)/languages',
'options' => $files['language']
],
'site.languages' => [
'pattern' => 'site/languages',
'options' => function () {
$site = App::instance()->site();
return (new LanguagesDropdown($site))->options();
}
],
'site.file' => [
'pattern' => '(site)/files/(:any)',
'options' => $files['file']
],
'site.file.languages' => [
'pattern' => '(site)/files/(:any)/languages',
'options' => $files['language']
]
];

View file

@ -1,90 +1,25 @@
<?php
use Kirby\Cms\App;
use Kirby\Cms\Find;
use Kirby\Toolkit\I18n;
use Kirby\Panel\Controller\PageTree;
return [
// @codeCoverageIgnoreStart
// TODO: move to controller class and add unit tests
'tree' => [
'pattern' => 'site/tree',
'action' => function () {
$kirby = App::instance();
$request = $kirby->request();
$move = $request->get('move');
$move = $move ? Find::parent($move) : null;
$parent = $request->get('parent');
if ($parent === null) {
$site = $kirby->site();
$panel = $site->panel();
$uuid = $site->uuid()?->toString();
$url = $site->url();
$value = $uuid ?? '/';
return [
[
'children' => $panel->url(true),
'disabled' => $move?->isMovableTo($site) === false,
'hasChildren' => true,
'icon' => 'home',
'id' => '/',
'label' => I18n::translate('view.site'),
'open' => false,
'url' => $url,
'uuid' => $uuid,
'value' => $value
]
];
}
$parent = Find::parent($parent);
$pages = [];
foreach ($parent->childrenAndDrafts()->filterBy('isListable', true) as $child) {
$panel = $child->panel();
$uuid = $child->uuid()?->toString();
$url = $child->url();
$value = $uuid ?? $child->id();
$pages[] = [
'children' => $panel->url(true),
'disabled' => $move?->isMovableTo($child) === false,
'hasChildren' => $child->hasChildren() === true || $child->hasDrafts() === true,
'icon' => $panel->image()['icon'] ?? null,
'id' => $child->id(),
'open' => false,
'label' => $child->title()->value(),
'url' => $url,
'uuid' => $uuid,
'value' => $value
];
}
return $pages;
return (new PageTree())->children(
parent: App::instance()->request()->get('parent'),
moving: App::instance()->request()->get('move')
);
}
],
'tree.parents' => [
'pattern' => 'site/tree/parents',
'action' => function () {
$kirby = App::instance();
$request = $kirby->request();
$root = $request->get('root');
$page = $kirby->page($request->get('page'));
$parents = $page?->parents()->flip()->values(
fn ($parent) => $parent->uuid()?->toString() ?? $parent->id()
) ?? [];
// if root is included, add the site as top-level parent
if ($root === 'true') {
array_unshift($parents, $kirby->site()->uuid()?->toString() ?? '/');
}
return [
'data' => $parents
];
return (new PageTree())->parents(
page: App::instance()->request()->get('page'),
includeSite: App::instance()->request()->get('root') === 'true',
);
}
]
// @codeCoverageIgnoreEnd
];

View file

@ -1,56 +1,17 @@
<?php
use Kirby\Cms\App;
use Kirby\Toolkit\Escape;
use Kirby\Panel\Controller\Search;
use Kirby\Toolkit\I18n;
return [
'pages' => [
'label' => I18n::translate('pages'),
'icon' => 'page',
'query' => function (string|null $query, int $limit, int $page) {
$kirby = App::instance();
$pages = $kirby->site()
->index(true)
->search($query)
->filter('isListable', true)
->paginate($limit, $page);
return [
'results' => $pages->values(fn ($page) => [
'image' => $page->panel()->image(),
'text' => Escape::html($page->title()->value()),
'link' => $page->panel()->url(true),
'info' => Escape::html($page->id()),
'uuid' => $page->uuid()?->toString(),
]),
'pagination' => $pages->pagination()->toArray()
];
}
'query' => fn (string|null $query, int $limit, int $page) => Search::pages($query, $limit, $page)
],
'files' => [
'label' => I18n::translate('files'),
'icon' => 'image',
'query' => function (string|null $query, int $limit, int $page) {
$kirby = App::instance();
$files = $kirby->site()
->index(true)
->filter('isListable', true)
->files()
->filter('isListable', true)
->search($query)
->paginate($limit, $page);
return [
'results' => $files->values(fn ($file) => [
'image' => $file->panel()->image(),
'text' => Escape::html($file->filename()),
'link' => $file->panel()->url(true),
'info' => Escape::html($file->id()),
'uuid' => $file->uuid()->toString(),
]),
'pagination' => $files->pagination()->toArray()
];
}
'query' => fn (string|null $query, int $limit, int $page) => Search::files($query, $limit, $page)
]
];

View file

@ -2,6 +2,9 @@
use Kirby\Cms\App;
use Kirby\Cms\Find;
use Kirby\Exception\PermissionException;
use Kirby\Panel\Ui\Buttons\ViewButtons;
use Kirby\Toolkit\I18n;
return [
'page' => [
@ -14,6 +17,40 @@ return [
return Find::file('pages/' . $id, $filename)->panel()->view();
}
],
'page.preview' => [
'pattern' => 'pages/(:any)/preview/(changes|latest|compare)',
'action' => function (string $path, string $versionId) {
$page = Find::page($path);
$view = $page->panel()->view();
$src = [
'latest' => $page->previewUrl('latest'),
'changes' => $page->previewUrl('changes'),
];
if ($src['latest'] === null) {
throw new PermissionException('The preview is not available');
}
return [
'component' => 'k-preview-view',
'props' => [
...$view['props'],
'back' => $view['props']['link'],
'buttons' => fn () =>
ViewButtons::view('page.preview', model: $page)
->defaults(
'page.versions',
'languages',
)
->bind(['versionId' => $versionId])
->render(),
'src' => $src,
'versionId' => $versionId,
],
'title' => $view['props']['title'] . ' | ' . I18n::translate('preview'),
];
}
],
'site' => [
'pattern' => 'site',
'action' => fn () => App::instance()->site()->panel()->view()
@ -24,4 +61,38 @@ return [
return Find::file('site', $filename)->panel()->view();
}
],
'site.preview' => [
'pattern' => 'site/preview/(changes|latest|compare)',
'action' => function (string $versionId) {
$site = App::instance()->site();
$view = $site->panel()->view();
$src = [
'latest' => $site->previewUrl('latest'),
'changes' => $site->previewUrl('changes'),
];
if ($src['latest'] === null) {
throw new PermissionException('The preview is not available');
}
return [
'component' => 'k-preview-view',
'props' => [
...$view['props'],
'back' => $view['props']['link'],
'buttons' => fn () =>
ViewButtons::view('site.preview', model: $site)
->defaults(
'site.versions',
'languages'
)
->bind(['versionId' => $versionId])
->render(),
'src' => $src,
'versionId' => $versionId
],
'title' => I18n::translate('view.site') . ' | ' . I18n::translate('preview'),
];
}
],
];

View file

@ -53,7 +53,7 @@ return [
];
}
throw new LogicException('The upgrade failed');
throw new LogicException(message: 'The upgrade failed');
// @codeCoverageIgnoreEnd
}
],

View file

@ -1,6 +1,7 @@
<?php
use Kirby\Cms\App;
use Kirby\Panel\Ui\Buttons\ViewButtons;
use Kirby\Toolkit\I18n;
return [
@ -59,11 +60,12 @@ return [
return [
'author' => empty($authors) ? '' : $authors,
'license' => $plugin->license() ?? '',
'license' => $plugin->license()->toArray(),
'name' => [
'text' => $plugin->name() ?? '',
'href' => $plugin->link(),
],
'status' => $plugin->license()->status()->toArray(),
'version' => $version,
];
});
@ -122,12 +124,14 @@ return [
return [
'component' => 'k-system-view',
'props' => [
'buttons' => fn () =>
ViewButtons::view('system')->render(),
'environment' => $environment,
'exceptions' => $debugMode ? $exceptions : [],
'info' => $system->info(),
'plugins' => $plugins,
'security' => $security,
'urls' => $sensitive ?? null
'urls' => $sensitive ?? []
]
];
}

View file

@ -8,6 +8,7 @@ return function ($kirby) {
'label' => I18n::translate('view.users'),
'search' => 'users',
'menu' => true,
'buttons' => require __DIR__ . '/users/buttons.php',
'dialogs' => require __DIR__ . '/users/dialogs.php',
'drawers' => require __DIR__ . '/users/drawers.php',
'dropdowns' => require __DIR__ . '/users/dropdowns.php',

View file

@ -0,0 +1,20 @@
<?php
use Kirby\Cms\User;
use Kirby\Panel\Ui\Buttons\SettingsButton;
use Kirby\Panel\Ui\Buttons\ViewButton;
use Kirby\Toolkit\I18n;
return [
'users.create' => function (User $user, string|null $role = null) {
return new ViewButton(
dialog: 'users/create?role=' . $role,
disabled: $user->kirby()->roles()->canBeCreated()->count() < 1,
icon: 'add',
text: I18n::translate('user.create'),
);
},
'user.settings' => function (User $user) {
return new SettingsButton(model: $user);
}
];

View file

@ -57,7 +57,7 @@ return [
'email' => '',
'password' => '',
'translation' => $kirby->panelLanguage(),
'role' => $role ?? $roles['options'][0]['value'] ?? null
'role' => $role ?: $roles['options'][0]['value'] ?? null
]
]
];
@ -231,9 +231,9 @@ return [
// compare passwords
if ($password !== $passwordConfirmation) {
throw new InvalidArgumentException([
'key' => 'user.password.notSame'
]);
throw new InvalidArgumentException(
key: 'user.password.notSame'
);
}
// change password if everything's fine
@ -319,7 +319,6 @@ return [
return [
'event' => 'user.delete',
'dispatch' => ['content/remove' => [$url]],
'redirect' => $redirect
];
}

View file

@ -1,18 +1,29 @@
<?php
use Kirby\Cms\Find;
use Kirby\Panel\Ui\Buttons\LanguagesDropdown;
$files = require __DIR__ . '/../files/dropdowns.php';
return [
'user' => [
'pattern' => 'users/(:any)',
'options' => fn (string $id) =>
Find::user($id)->panel()->dropdown()
],
'user.languages' => [
'pattern' => 'users/(:any)/languages',
'options' => function (string $id) {
return Find::user($id)->panel()->dropdown();
$user = Find::user($id);
return (new LanguagesDropdown($user))->options();
}
],
'user.file' => [
'pattern' => '(users/.*?)/files/(:any)',
'options' => $files['file']
],
'user.file.languages' => [
'pattern' => '(users/.*?)/files/(:any)/languages',
'options' => $files['language']
]
];

View file

@ -1,29 +1,12 @@
<?php
use Kirby\Cms\App;
use Kirby\Toolkit\Escape;
use Kirby\Panel\Controller\Search;
use Kirby\Toolkit\I18n;
return [
'users' => [
'label' => I18n::translate('users'),
'icon' => 'users',
'query' => function (string|null $query, int $limit, int $page) {
$kirby = App::instance();
$users = $kirby->users()
->search($query)
->paginate($limit, $page);
return [
'results' => $users->values(fn ($user) => [
'image' => $user->panel()->image(),
'text' => Escape::html($user->username()),
'link' => $user->panel()->url(true),
'info' => Escape::html($user->role()->title()),
'uuid' => $user->uuid()->toString(),
]),
'pagination' => $users->pagination()->toArray()
];
}
'query' => fn (string|null $query, int $limit, int $page) => Search::users($query, $limit, $page)
]
];

View file

@ -2,6 +2,7 @@
use Kirby\Cms\App;
use Kirby\Cms\Find;
use Kirby\Panel\Ui\Buttons\ViewButtons;
use Kirby\Toolkit\Escape;
return [
@ -18,7 +19,11 @@ return [
return [
'component' => 'k-users-view',
'props' => [
'canCreate' => $kirby->roles()->canBeCreated()->count() > 0,
'buttons' => fn () =>
ViewButtons::view('users')
->defaults('create')
->bind(['role' => $role])
->render(),
'role' => function () use ($roles, $role) {
if ($role) {
return $roles[$role] ?? null;