Changelog
In addition to all the features listed separately on the Kirby 5 release page, there are a lot more enhancements, deprecations and breaking changes in the fineprint:
✨ Enhancements
Core
- Thumbnails will no longer be regenerated when the page's sorting number changes #6432
- New
files.sort
permission #1969 - New
$kirby->role()
method that works like$kirby->user()
to return a specific role or the role of the current user #6874 - Support for content representation specific site controllers, e.g.
site.rss.php
#6950 - New
Kirby\Cms\Pages::delete(array $ids)
andKirby\Cms\Files::delete(array $ids)
methods to handle batch delete for multiple files in a collection. - Add root for plugin licenses (
$kirby->root('licenses')
) - New protected
Kirby\Filesystem\IsFile::assetFactory()
method to create a new asset instance based on the file type, but without adding it to the property cache. This enhancement is related to the bug fix for #7289 - Harden preview token verification to mitigate guessing the preview token with a timing attack
- Preview authentication tokens of drafts and (new in Kirby 5) versions have been shortened to 10 characters to make the preview URLs more manageable.
Versions
-
New
storage
core component which returns the default storage handler for a model #6867 -
New
Kirby\Cms\ModelWithContent::version()
method to directly access different content versions #6455// Accessing different versions $page->version('latest'); $page->version('changes'); // Version method examples $page->version('changes')->content(); $page->version('changes')->save([...]); $page->version('changes')->publish(); $page->version('changes')->delete();
-
New
Kirby\Cms\ModelWithContent::versions()
method to get a collection of all versions (currentlychanges
andlatest
) #7059 -
$page->previewUrl()
and$site->previewUrl()
now accept a version ID to specify which version you want to preview.$page->previewUrl('latest') // default $page->previewUrl('changes')
-
It is now possible to override the version ID in
$page->render()
with the new$versionId
parameter. -
New
Kirby\Content\VersionId::render()
method to atomically set the render version during a render operation -
The
Kirby\Cms\ModelWithContent::lock()
method returns the new, improvedKirby\Content\Lock
class, which replacesKirby\Cms\ContentLock
// examples $page->lock()->isLocked() $page->lock()->modified() $page->lock()->modified('d.m.Y') $page->lock()->user()?->username()
-
New
Kirby\Content\Changes
class replacesKirby\Cms\ContentLocks
to track all unsaved changes across all users and models. This class is mostly internal, but you can use it to get access to changed pages, files and users on the backend.use Kirby\Content\Changes; $changes = new Changes(); // collection of changed pages $changes->pages(); // collection of changed files $changes->files(); // collection of changed users $changes->users();
-
New default
changes
cache, which is active by default. This cache is internally used to keep track of all models with changes that have not been published yet. You can change the cache settings in your config:// /site/config/config.php return [ 'cache' => [ 'changes' => [ 'type' => 'redis' ] ] ];
-
New
Kirby\Content\MemoryStorage
#6457 as well asKirby\Content\ImmutableMemoryStorage
to keep outdated model information in memory but avoid any mutations. #6570 -
The
Kirby\Cms\ModelWithContent::changeStorage()
method to move (or copy) the model's storage to a different storage type -
New
Kirby\Content\Translation
class (replacingKirby\Content\ContentTranslation
) -
New
Kirby\Content\Translations
class to provide a more type-safe collection for all translations (returned byKirby\Cms\ModelWithContent::translations()
). -
New
Kirby\Content\VersionId
class to represent versions #6436
View buttons
- New
Kirby\Panel\Panel::buttons()
method that returns all defined buttons from all Panel areas #6541 - New
Kirby\Panel\Ui
namespace with basicKirby\Panel\Ui\Component
andKirby\Panel\Ui\Button
classes #6539. Each component renders as an array with acomponent
, uniquekey
andprops
entries - New
Kirby\Panel\Ui\Buttons\ViewButtons
andKirby\Panel\Ui\Buttons\ViewButton
classes #6542, responsible for gathering and transforming view buttons configured in blueprints, config files and/or Panel areas - New classes for core view buttons #6545:
Kirby\Panel\Ui\Buttons\LanguagesDropdown
andKirby\Panel\Ui\Buttons\PreviewButton
.
Data
-
New third
$fail
argument forData::read()
andData::decode()
. By default,Data::read()
andData::decode()
will throw an exception if the file does not exist or the data cannot be decoded. By setting$fail
to false, you can circumvent the exception and return an empty array instead. We’ve refactored our parts of the code where we used a try/catch block to achieve the same.use Kirby\Data\Data; $data = Data::read(__DIR__ . '/missing-file.yml', fail: false); $data = Data::decode($brokenData, type: 'json', fail: false);
-
New
$pretty
argument forJson::encode()
:use Kirby\Data\Json; $prettyJson = Json::encode($data, pretty: true);
-
New UUIDs are fully lowercased now to avoid issues between filesystems handling casing differently #6566
Languages
-
New
$language->ensure()
and$languages->ensure()
methods to get language(s) objects even in single-language mode. Note that these methods are marked as internal and may be changed in a future version. #6483use Kirby\Cms\Language; use Kirby\Cms\Languages; // for a single language echo Language::ensure('default')->code(); // for all languages foreach (Languages::ensure() as $language) { echo $language->code(); }
-
New
$language->is()
method to compare language objects
Translations
- New Taiwanese translation (thanks to Ralph)
- New i18n strings
copy.success
copy.url
lock.unsaved.files
lock.unsaved.pages
lock.unsaved.users
version.changes
version.compare
view
API
- New API Routes for saving, publishing and discarding of changes:
- POST:
/api/(:id)/changes/discard
- POST:
/api/(:id)/changes/publish
- POST:
/api/(:id)/changes/save
- POST:
- The
files
andpages
sections introduce newdelete
API endpoints. Those endpoints can take a set of page or file IDs and will delete each one. Errors will be caught and sent back in the details array of the final thrown exception.
Panel
- Radio and select fields:
default
option now supports Kirby queries #6459 - Sections: improved title and info wrapping #6447
- The fields section now passes all values on input of any field instead of updating just the one field (similar to on submit) #6517
- Improved contrast for some theme colors (e.g.
aqua-icon
theme) - Writer nodes with
inline: true
in their button definition are displayed as inline buttons in toolbar (instead inside the dropdown) #6902 - Page status button uses custom status labels for
title
#6911 - Resetting the password without knowledge of the current password is now only possible after logging in in password reset mode #7186
Icons
We’ve added the following new icons:
accessibility
ai
asterisk
cloud
collapse-horizontal
expand-horizontal
info-card
kirby
layout-columns
layout-right
layout-left
rocket
rss
shield
shut-down
terminal
wallet
window
Vue Components
- New
badge
prop for<k-button>
(value:{ text, theme }
) #6755 <k-link>
(and subsequently<k-button>
and<k-dropdown-item>
) has a newdownload
attribute to force direct download of a file<k-tag>
: newelement
andtheme
props #6569<k-tags>
: newelement
,element-tag
andtheme
props #6569- New
<k-tags-field-preview>
component #6569 - New
<k-view-button>
component #6540 - New
<k-form-controls>
component #6512 with a new dropdown to give information about the author and last modification of the page, site, user or file. - New
<k-languages-dropdown>
component <k-dropdown-content>
exposesitems
in scoped default slot and has newitem
scoped slot
Events
beforeunload
is now available as a global event, which you can listen to:this.$panel.events.on("beforeunload", () => { // do something before the window/tab closes. });
- The upload module now sends a
file.upload.error
event for every file that could not be uploaded.
Helpers
- New
this.$helper.throttle
JS helper #6708 - New
options
argument forthis.$helper.debounce
JS helper to control leading/trailing behavior #6708 - New
clipboard.write
event, which can be triggered globally to write something to the clipboard. This is especially useful if you want to fire a copy event from the backend (e.g. from a dropdown option):this.$panel.events.emit("clipboard.write", "Add me to the clipboard");
- New
uploadAsChunks
JS helper function #6421 - New
this.$helper.object.filter(object, predicate)
#6902 - New async
TextareaInput.restoreSelection()
method - New
panel.upload.announce()
method, which sends the success notification andmodel.update
event after uploads have successfully completed.
Lab
🐛 Bugfixes
Core
- Fixed thumb issues resulting from EXIF orientation data #2695
- Model hooks for actions: multiple hooks don't overwrite each others' changes to the model #6460 #2828
- Fix PHP error when
null
is passed as model to$kirby->contentToken()
#6822 - Fixed
Str::ucfirst()
behavior, now behaves like PHP default #6834 - Permissions are now always correctly determined if the active user changes during the request #6880
User::delete()
will now properly callfile.delete
hooks for deleted user files- Fixed invalid parent query in
Kirby\Cms\FileBlueprint
tests #7167 - URLs like
https://example.com/some-invalid-page/some-site-file.pdf
are no longer resolved to an existing site file #7217 - The
Kirby\Http\Uri
class now properly serializes URIs of the form/subfolder/
. #7255 F::type()
does no longer interpret.tmp
as valid file extension, but uses mime detection to get the correct type.
Panel
- Dialogs:
Cmd+S
doesn't re-submit the dialog when its already submitting #7258
Fields
- All fields: Fixed query support for default values in fields #2814 #2815
- Select, radio and toggles fields: Values that include a comma will not be split into two tags in the structure field preview anymore #5800
- Writer field: Inline toolbar is hidden when no nodes and marks are available #6804
- Range/Number field: Fix
isEmpty()
usage #6898 - Blocks field: Fix Drag & Drop between block fields #5290
- Blocks field: fix empty display #6951
Sections
- Page section: Fixed flag column for page sections with table layout #6866
Uploads
- Kirby is better at removing failed file uploads from the server tmp directory #2476
- Cancelling the file upload dialog now also cancels ongoing uploads #6421
Search
- Panel search now also considers site files #6710
Vue components
- Drawers + Fields block: collapse tabs in header correctly into dropdown for narrow columns #6914
<k-header>
: fixed wrapping with many buttons in narrow screens #6544- The lock state is properly passed to
<k-file-preview>
components to make sure that file previews can lock their state (e.g. for the focus point for image previews) - Fixed badge position in
<k-model-tabs>
and improved CSS for button badges in general - Page dropdown: fix disabling preview item #6891
- File preview: fix aspect ratio for medium viewports #6891
- Fixed background CSS for the
<k-progress>
component - Fixed footer margin in dialogs if the
cancelButton
property is a string or object instead of a boolean. #6833 - Custom writer nodes: fixed active state detection for nodes that include paragraph child nodes #6902
JS Panel API
⚠️ Breaking changes
Requirements
- Kirby 5 requires at least PHP 8.2
- Kirby 5 raises browser version requirements for the Panel:
- Safari 16+
- Mobile Safari 16+
- Android Browser 126+
- Chrome for Android 126+
- (other browsers remain unchanged)
Core
Config options
- Closures defined for the
content.salt
option will no longer receive a model when generating a salt for preview authentication tokens of drafts and versions as those tokens are now only based on the URI. The salt callback instead receivesnull
and is expected to return a fixed model-independent salt in this case. When generating a salt for a file media token, the file object is still passed as model. #6836 - The
api.methodOverwrite
option has been renamed toapi.methodOverride
- The
content.fileRedirects
option is now set tofalse
by default. This protects uploaded file originals from unauthorized downloads. If you rely on thehttps://example.com/some/page/file.pdf
orhttps://example.com/some-site-file.pdf
routes, you can set the option totrue
or to a closure to control access dynamically per file.
Controllers
- Data/variables from your
site
controller will now be passed to all templates #6412
Hooks
- Model action
before
hooks: rules get applied before and after the hook runs
Collections
- PHP type hints have been added to many collection methods. If you are extending Core classes, you might need to add the same to your own classes and methods.
Models
Kirby\Cms\HasMethods::callMethod()
is now a protected methodKirby\Cms\ModelWithContent::lock()
will now always return aKirby\Content\Lock
object, even if the model is not currently locked. You can check for that case withModelWithContent::lock()->isLocked()
Kirby\Cms\ModelWithContent::version()
andKirby\Cms\ModelWithContent::versions()
are no longer available as direct field accessor. You need to use$model->content()->version()
/$model->content()->versions()
instead if you are using a field with the nameversion
/versions
.Kirby\Cms\Page::modified()
,Kirby\Cms\File::modifiedContent()
andKirby\Cms\User::modified()
now use the current language instead of the default language.- Old model instances (objects that already were e.g. updated and returned a new model instance) can no longer modify their content. Calling actions on these old model instances will throw an exception. Use the new model instances instead.
- All methods in
*Rules
classes are now marked to returnvoid
instead of abool
#6660
Content & Locking
- Removed
Kirby\Cms\ContentLock
andKirby\Cms\ContentLocks
as well asKirby\Cms\App::locks()
$kirby->contentToken()
only acceptsobject
ornull
for the$model
parameter instead ofmixed
. #6822- Renamed
token
query param for preview URLs to_token
#6823
Pages
$page::translation()
returns a single translation in single language mode. It now always returns aKirby\Content\Translation
object. This is also included in the$page::toArray()
method.- Cache IDs in the pages cache now include a part for the version ID. Currently this is always
.latest
, e.g.home.latest.html
. #6827 - Removed internal
$page->isVerified()
method in favor of internal$page->renderVersionFromRequest()
#6829
Users
User::create()
does no longer accept null as argument.- Users without a role in their credentials file will now receive the
default
role (if exists), not thevisitor
role anymore #6656 - Setting a
name
field inUser::update()
does no longer have any effect. UseUser::changeName()
instead.
Roles and Permissions
- If file sorting was previously disabled via the
files.update
permission, the newfile.sort
permission has to be configured accordingly. #6589 Kirby\Cms\Role::admin()
has been renamed toKirby\Cms\Role::defaultAdmin()
#7187Kirby\Cms\Role::nobody()
has been renamed toKirby\Cms\Role::defaultNobody()
#7187- Classes extending
Kirby\Cms\ModelPermissions
need to set their category with theconst CATEGORY
orstatic function category()
instead ofprotected string $category
and use the staticuser()
method instead of$user
and$permissions
properties #6880
Media & Thumbnail generation
Kirby\Image\Dimensions::forImage()
now receives anKirby\Image\Image
object #6591Kirby\Image\Exif::read()
is now a static method that receives an absolute path to a file #6591- Thumb driver
autoOrient
option has been removed and now is always applied #6591
Plugins
Kirby\Plugin\Plugin::license()
now returns theLicense
object instead of a simple stringKirby\Plugin\Plugin::toArray()
includes the full license info as child array instead of a string
Forms
Kirby\Form\Field::$formFields
has been renamed toKirby\Form\Field::$siblings
- The
$formField
argument inKirby\Form\Field::factory()
has been renamed to$siblings
- You can no longer pass a value to
Kirby\Form\Field::isEmpty()
UseKirby\Form\Field::isEmptyValue($value)
instead. Kirby\Form\Form::fields()
does no longer return null but an emptyKirby\Form\Fields
collection if there are no fields.Kirby\Form\Field::validate()
returns an array of errors instead of void.- Removed protected
Kirby\Form\Fields::$errors
,Kirby\Form\Field::$errors
andKirby\Form\FieldClass::$errors
properties #7131 - The language argument in the protected internal
Kirby\Form\Form::prepareForLanguage()
method is no longer optional and must be a Language object. #7132 - The
Kirby\Form\Form
class does no longer swallow errors in field classes on construction. This could be considered a breaking change or an debugging enhancement. #7167 - When using the
Kirby\Form\Form
class, the disabled state of fields will no longer be overwritten on construction for secondary languages. UseKirby\Form\Form::toProps()
instead, to get the correct disabled state for each field. When usingKirby\Form\Form::toProps()
, permissions will also be honored when the model cannot be updated by the user role. #7166 Kirby\Form\Form::$values
has been removed #7166Kirby\Form\Form::prepareFieldsForLanguage()
has been removed #7166- The structure field
::form
method does no longer have a$values
parameter. Use$field->form()->fill()
or$field->form()->submit()
instead if you want to add values to the form. #7170
Filesystem
F::read()
no longer supports requesting URLs with protocols such ashttp://
andhttps://
. Please use theRemote
class for this purpose. #7099F::read()
no longer silently returnsfalse
when the file exists but is not readable. Instead it triggers a PHP "Permission denied" warning. #7099
Toolkit
- The
Str::ucfirst()
method no longer lowercases all but the first letter of the text, it only capitalizes the first letter. #6860 Str::camel()
,Str::camelToKebab()
,Str::float()
,Str::kebab()
,Str::kebabToCamel()
,Str::length()
,Str::lower()
,Str::safeTemplate()
,Str::short()
,Str::slug()
,Str::snake()
,Str::studly()
,Str::substr()
,Str::template()
,Str::ucfirst()
,Str::ucwords()
,Str::unhtml()
,Str::upper()
andStr::widont()
can no longer be called without a value argument (passing anull
value still works) #6401- Passing a single space as value to
Xml::attr()
won't render an empty value anymore but a single space. To render an empty value, please pass an empty string. #6803
Panel
Uploads
- Panel uploads can exceed PHP’s
upload_max_filesize
limit #6421. If you want to restrict the upload size, please use the file blueprintaccept
maxsize
option
Fields
- All fields:
signature
is no longer available as field property when loading fields from the Panel backend #6712 - Textarea field: File drag texts in the Panel always use the file UUID, if UUIDs are not disabled #6948
- Date field: Calendar dropdown input will show Sunday now as first day of the week (depending on the user's language). If you want to enforce Monday as first day of the week, you can set the
date.weekday
option to1
. #6635 - Select field:
empty
prop was removed. Use combination ofrequired
,placeholder
anddefault
to replicate functionality #6459 - Checkbox and Toggle fields:
required: true
now enforces that these fields need to be checked/toggled (active state)
Custom Panel CSS
- CSS attribute selectors must be written fully qualified (e.g.
[data-hidden="true"]
as only[data-hidden]
can start matching also elements where that attribute isfalse
) #6109
Vue Components
<k-form>
and<k-fieldset>
as well as many fields and inputs don't emit aninvalid
event anymore. Use native HTML invalid state of elements instead. #6099novalidate
prop has been removed from all elements but<k-form>
#6099- Removed
hasErrors
methods of<k-fieldset>
#6173 <k-file-preview>
got fully refactored. If you were replacing or extending it, your code likely will break. Check out the new custom file preview feature if you want to provide previews for specific files. #6578<k-draggable>
: themove
callback function is receiving an event with an altered data structure- While
<k-writer>
is still included as alias for <k-writer-input
>, some use cases where you accessed the<k-writer>
component via the$refs
of<k-writer-input>
have to be adapted #6172 <k-item>
: Removeddata-only-option
attributes<k-dialog>
: Removeddata-has-footer
attribute<k-toggles-input>
: Removeddata-disabled
attribute<k-writer-input>
: Removeddata-toolbar-inline
attribute<k-bubble>
: Removeddata-has-text
attribute<k-header>
: Removeddata-has-buttons
attribute<k-tag>
: Removeddata-has-image
anddata-has-toggle
attributes<k-tree>
: Removeddata-has-subtree
attribute
Panel JS API
panel.view.isLocked
no longer exists. Usepanel.content.isLocked()
instead #6515- Vuex and the Vuex content module have been removed.
- The following dialogs no longer send dispatch events via the backend. Dispatch events relied on Vuex.
page.changeTitle
page.delete
page.move
user.delete
- The
panel.api.users.changePassword()
method now receives three arguments for the user ID, the new password to set and the current password of the acting user (new) #7186
API
- The
PATCH
:account/password
andPATCH
:users/$user/password
API routes require an additionalcurrentPassword
parameter with the password of the acting user unless in password reset mode of the current user #7186 - Removed API routes:
GET
:/api/(:all)/lock
PATCH
:/api/(:all)/lock
DELETE
:/api/(:all)/lock
PATCH
:/api/(:all)/unlock
DELETE
:/api/(:all)/unlock
Translations
copy.success
has been renamed tocopy.success.multiple
Removed deprecated code
Removed | Use instead |
---|---|
<k-aspect-ratio> |
<k-frame> |
<k-autocomplete> |
- |
<k-bar> : left , right and center slots |
default slot |
<k-breadcrumb> : view prop |
Add as first entry to crumbs prop |
<k-button> : tooltip prop |
title prop |
<k-button-disabled> |
<k-button :disabled="true"> |
<k-button-link> |
<k-button link="..."> |
<k-button-native> |
<k-button> |
<k-dialog> : disabled , icon and theme props. |
submit-button prop |
<k-dropdown> |
<k-dropdown-content> as standalone |
<k-grid> : gutter prop |
style="gap: " or variant prop |
<k-header> : left and right slots |
buttons slot |
<k-header> : tabs prop |
standalone <k-tabs> |
<k-headline> : size prop |
tag prop |
<k-headline> : theme prop |
- |
<k-icon> : removed support for other viewBox than 0 0 24 24 |
Wrap icon in an <svg> element with corresponding viewBox attribute |
<k-inside> |
<k-panel-inside> |
<k-loader> |
<k-icon type="loader" /> |
<k-outside> |
<k-panel-outside> |
<k-plugin-view> |
- |
<k-progress> : set method |
value prop |
<k-text> : theme prop |
- |
<k-upload> |
$panel.upload module |
<k-view> |
- |
$store.drawer |
$panel.drawer |
$store.notification |
$panel.notification |
$store.dialog() |
$panel.dialog.open() |
$store.drag() |
$panel.drag.start(type, data) |
$store.fatal() |
$panel.notification.fatal() |
$store.isLoading() |
$panel.isLoading |
$store.navigate() |
- |
JS $events.$on , $events.$off , $events.$emit |
$events.on , $events.off , $events.emit |
window.panel.$api |
window.panel.api |
window.panel.$config |
window.panel.config |
window.panel.$direction |
window.panel.direction |
window.panel.$events |
window.panel.events |
window.panel.$language |
window.panel.language |
window.panel.$languages |
window.panel.languages |
window.panel.$license |
window.panel.license |
window.panel.$multilang |
window.panel.multilang |
window.panel.$search |
window.panel.search |
window.panel.$searches |
window.panel.searches |
window.panel.$translation |
window.panel.translation |
window.panel.$url |
window.panel.url |
window.panel.$urls |
window.panel.urls |
window.panel.$user |
window.panel.user |
window.panel.$view |
window.panel.view |
window.panel.$vue |
window.panel.app |
this.$config |
this.$panel.config |
this.$direction |
this.$panel.direction |
this.$language |
this.$panel.language |
this.$languages |
this.$panel.languages |
this.$license |
this.$panel.license |
this.$menu |
this.$panel.menu |
this.$multilang |
this.$panel.multilang |
this.$search |
this.$panel.search |
this.$searches |
this.$panel.searches |
this.$system |
this.$panel.system |
this.$translation |
this.$panel.translation |
this.$urls |
this.$panel.urls |
this.$user |
this.$panel.user |
this.$view |
this.$panel.view |
Array.wrap() |
this.$helper.array.wrap() |
Array.fromObject() |
this.$helper.array.fromObject() |
myArray.split() |
this.$helper.array.split(myArray, delimiter) |
myArray.sortBy() |
this.$helper.array.sortBy(myArray, sortBy) |
Kirby\Content\ContentTranslation |
Kirby\Content\Translation |
Kirby\Cms\Model |
- |
Kirby\Cms\ModelWithContent::readContent() |
$model->version()->read() |
Kirby\Cms\ModelWithContent::writeContent() |
$model->version()->write() |
Kirby\Cms\Properties trait |
PHP native named properties |
Kirby\Cms\File::contentFileDirectory() |
- |
Kirby\Cms\File::contentFileName() |
- |
Kirby\Cms\ModelWithContent::contentFile() |
$model->storage()->contentFile() |
Kirby\Cms\ModelWithContent::contentFiles() |
$model->storage()->contentFiles() |
Kirby\Cms\ModelWithContent::contentFileDirectory() |
- |
Kirby\Cms\ModelWithContent::contentFileName() |
- |
Kirby\Cms\ModelWithContent::contentFileExtension() |
- |
Kirby\Cms\Page::contentFileName() |
- |
Kirby\Cms\Site::contentFileName() |
- |
Kirby\Cms\User::contentFileName() |
- |
Kirby\Form\FieldClass::valueFromJson() |
Kirby\Data\Json::decode() |
Kirby\Form\FieldClass::valueFromYaml() |
Kirby\Data\Yaml::decode() |
Kirby\Form\FieldClass::valueToJson() |
Kirby\Data\Json::encode() |
Kirby\Form\FieldClass::valueToYaml() |
Kirby\Data\Yaml::encode() |
☠️ Deprecated
Core
Models
Kirby\Panel\Model::content()
is deprecated. UseKirby\Panel\Model::versions()['changes']
instead. #7153
Plugins
Kirby\Cms\Plugin
is deprecated. UseKirby\Plugin\Plugin
instead.Kirby\Cms\PluginAsset
is deprecated. UseKirby\Plugin\Asset
instead.Kirby\Cms\PluginAssets
is deprecated. UseKirby\Plugin\Assets
instead.
Forms
Kirby\Form\Field::formFields()
is deprecated. Use::siblings()
instead.Kirby\Form\Field::data()
is deprecated. Use::toStoredValue()
instead.Kirby\Form\Field::save()
is deprecated. Use::isSaveable()
instead.Kirby\Form\Field::value()
is deprecated. Use::toFormValue()
instead.Kirby\Form\FieldClass::data()
is deprecated. Use::toStoredValue()
instead.Kirby\Form\FieldClass::save()
is deprecated. Use::isSaveable()
instead.Kirby\Form\FieldClass::value()
is deprecated. Use::toFormValue()
instead.Kirby\Form\Form::content()
is deprecated. Use::toStoredValues()
instead. #7166Kirby\Form\Form::data()
is deprecated. Use::toStoredValues()
instead. #7166Kirby\Form\Form::strings()
is deprecated. Use::toStoredValues()
instead. #7166Kirby\Form\Form::values()
is deprecated. Use::toFormValues()
instead. #7166
Exceptions
- Exception classes: passing
$arg
array will be removed in a future version. Use named arguments. #6618
Panel
Config options
panel.favicon
option throws deprecation warnings forurl
option (usehref
instead) and forrel
key (userel
option instead)
Fields
- Color field: the
text => value
notation for options has been deprecated and will be removed in Kirby 6. Please rewrite your options asvalue => text
. #6913
Custom Panel CSS
--color-backdrop
CSS property has been deprecated. Use--overlay-color-back
instead #6299
Vue components
<k-writer>
will be removed in a future version. Use<k-writer-input>
instead #6172<k-bubble>
,<k-bubbles>
and<k-bubbles-field-preview>
. Use<k-tag>
,<k-tags>
and<k-tag-field-preview>
instead. #6569
Panel JS API
TextareaInput.restoreSelectionCallback()
has been deprecated. UseTextareaInput.restoreSelection()
instead.
♻️ Refactored
Core
General
- Use more modern PHP syntax and PHPUnit assertions where applicable #6401
- Improved class typing by adding
Stringable
interface to relevant classes #6433 - Use "new" functions from PHP 8.0 #6476
str_contains()
str_starts_with()
str_ends_with()
- Normalize timezone during unit tests #7248
- Move trait template annotations to class doc #7272
Model improvements
All models
- Use the new improved Form code in
Kirby\Cms\ModelWithContent::update()
#7169 - Call
::setBlueprint()
in constructors before setting content - Add
::updateParentCollection()
methods toFileActions
andUserActions
and use them in their commit methods - Remove
::hardcopy()
from::commit()
in model actions - New
Kirby\Cms\HasModels
trait - New
Kirby\Cms\ModelCommit
andKirby\Cms\ModelState
classes App::setSite()
is now public and can be used to overwrite the current site instance- New
Page::normalizeProps()
,File::normalizeProps()
andUser::normalizeProps()
- Unit tests for Models have been reorganized and cleaned up
- Use
ModelWithContent::version()
in the core where it makes sense #6455 Page::__construct
,Site::__construct
,User::__construct
andFile::__construct
callparent::__construct
after setting the props #6499- Simplify
ModelWithContent::writeContent
by using the newVersion::save()
method. #6505 - Simplify
ModelWithContent::content
by usingLanguage::ensure()
andVersion::content()
#6505 - Consolidate duplicated logic from
$page->previewUrl()
and$site->previewUrl()
in$version->url()
(with aliases to the existing methods)
Pages
- Template name is always lowercase in the
Page::setTemplate()
method - Model name in
Page::model()
is always lowercase - Template in
Page::factory()
method is always lowercase - Use
Page::updateParentCollections()
in the::commit()
method and remove redundant calls.
Files
- Simplify
Kirby\Cms\FileActions::create
when the same file is uploaded #7149
Roles & Permissions
Kirby\Cms\ModelPermissions
now also supportsKirby\Cms\Language
objects as quasi models #6876- New
Kirby\Cms\LanguagePermissions
class that inherits the existing logic fromKirby\Cms\LanguageRules
for consistency with other models #6876 - Globally cache
access
andlist
permissions per permission category, model type and user role to reduce code duplication #6881 - Remove dead code from role shortcut methods for the default
admin
andnobody
roles #7187
Languages
- Refactored
Kirby\Cms\LanguageRules
#6659 - New
Language::single()
method to create aLanguage
placeholder object in single language installations #6448
Forms
Kirby\Form\Form
class improvements
- New
Kirby\Form\Form::toFormValues()
to return all values for all fields in the collection that can be passed to a frontend form. - New
Kirby\Form\Form::toStoredValues()
to return all values for all fields in a format that can be stored in our text files. - The Form class now always passes the injected model to the Fields collection
- The Form class now uses
Kirby\Form\Field::isSaveable
instead ofKirby\Form\Field::save
consistently. Kirby\Form\Form::errors()
is now an alias for$form->fields()->errors()
Kirby\Form\Form::field($name)
is now an alias for$form->fields()->find($name)
- Removed an unnecessary check for a blueprint method in the
Form::for
method.Kirby\Cms\ModelWithContent
has a blueprint method by default and we
already check forKirby\Cms\ModelWithContent
child classes with the argument type. - Refactored language handling in the
Kirby\Form\Form
class with the newKirby\Cms\Language::ensure()
method. #7132 - Use named parameters for Form construction throughout our entire code base #7174
Kirby\Form\Field
class improvements
- New
Kirby\Form\Field::fill($value)
method - New
Kirby\Form\Field::toFormValue()
method - New
Kirby\Form\Field::toStoredValue()
method
Kirby\Form\FieldClass
class improvements
- New
Kirby\Form\FieldClass::toFormValue()
method - New
Kirby\Form\FieldClass::toStoredValue()
method
Kirby\Form\Fields
class improvements
-
You can now pass the parent model as second argument to the Fields collection to inject it into any of the given fields.
use Kirby\Form\Fields; $fields = new Fields( fields: [ 'text' => [ 'label' => 'Text', 'type' => 'text' ] ], model: page('blog/hello-world') );
-
New
Kirby\Form\Fields::defaults()
method to return all default values for all fields. -
New
Kirby\Form\Fields::errors()
method to run validation on all fields and return an array with all errors -
New
Kirby\Form\Fields::fill($values)
method to set the value for each field in the array -
New
Kirby\Form\Fields::findByKey()
andKirby\Form\Fields::findByKeyRecursive()
to find fields within fields withKirby\Form\Fields::find('parent-field+child-field')
(e.g. a field in a structure field) This has been handled by theKirby\Form\Form::field()
method before, but it's the wrong place to do that. With the new collection methods, this is handled in a very similar fashion as we do for pages. -
New
Kirby\Form\Fields::toFormValues()
to return all values for all fields in the collection that can be passed to a frontend form. -
New
Kirby\Form\Fields::toStoredValues()
to return all values for all fields in a format that can be stored in our text files. -
Improved
Kirby\Form\Fields::toArray()
method. You can now provide a proper map function to return custom values for each field in the collection.
New Form Field Trait classes
The new trait classes help reduce code redundancy between Kirby\Form\Field
and Kirby\Form\FieldClass
Kirby\Form\Mixin\Api
Kirby\Form\Mixin\Model
Kirby\Form\Mixin\Translatable
Kirby\Form\Mixin\Validation
Kirby\Form\Mixin\Value
Kirby\Form\Mixin\When
Collections
- New
Kirby\Cms\Collection::update($object)
method - Improve code style
Kirby\Toolkit\Collection::sort()
#6626
Plugins
- New
Kirby\Plugin
namespace #6737
Exceptions
- Exception classes support named arguments #6618
Hooks
- New
Kirby\Cms\Events
class that handles low-level hook execution
API
- New
Kirby\Api\Upload
class to handle file uploads via the REST API #6421
Toolkit
- New
Kirby\Toolkit\Component::applyProp()
method to allow resetting single props and also improves prop unsetting in custom components.
Unit tests
- Switched to PHPUnit Attributes in various test classes. This is work in progress and will happen in more test classes in the future.
Panel
Preparations for a move to Vue 3 in v6
<k-draggable>
is directly built on top of SortableJS now #6387- Replace Vue
$listeners
#6107 - Use strict CSS selectors for boolean (data) attributes #6109
- Explicitly added
$attrs.class
to components that disable inheriting attributes #6332
Streamlined input validation
- Use
<k-string-input>
for all text inputs #6103 <k-slug-input>
is now built on top of<k-string-input>
#6320- Stricter native URL validation for
<k-url-input>
#6320 - Removed
vuelidate
library #6099
Panel Models
- Removed
Kirby\Panel\Model::lock()
method - New
Kirby\Panel\Model::versions()
method - New top-level props in
Kirby\Panel\Model::props()
api
id
link
uuid
versions
- New top-level props in
Kirby\Panel\File::props()
extension
filename
mime
preview
type
url
- New top-level props in
Kirby\Panel\Page::props()
title
- New top-level props in
Kirby\Panel\Site::props()
title
- New top-level props in
Kirby\Panel\User::props()
avatar
email
language
name
role
username
Panel UI Backend
- Drastically simplified
Kirby\Panel\ChangesDialog
class, which reads changed models directly on the backend with the newKirby\Content\Changes
class and sends the required data for each model directly to the frontend. We no longer need an additional async request. - Simplified the fields section backend code with the refactored
Kirby\Cms\Form
class #7168 - New
Kirby\Panel\Controller\Search
class #6710 - Removed unnecessary generic signature key for each form field. #6712
Vue Components
<k-writer>
has been merged into<k-writer-input>
#6172<k-languages-dropdown>
now receives Fiber dropdown endpoint instead of array of options #6762<k-user-avatar>
component has been refactored to use individual props forapi
,avatar
,id
andisLocked
instead of going through themodel
object. Themodel
prop has been removed.- The
<k-user-profile>
component has been refactored to use individual props forapi
,avatar
,email
,id
,language
androle
instead of going through themodel
object. Themodel
object prop has been removed as well as the already deprecatedpermissions
prop.
Panel JS API
- New
this.$panel.content
module to access and alter the current model content (unsaved changes) #6513 - Clean up
panel/plugins.js
- Moves some refactoring/clean up changes from #7104 up to v5
- Renames some helper functions to
resolve*
- Exposes these for kirbyup and other tools
- Removed unnecessary complete handler in
FilesSection
. The upload module already takes care of the notifications and events. TextareaInput.selectionRange
andTextareaInput.restoreSelection()
are used to replace the oldrestoreSelectionCallback
method in dialog events for better async control.- Various
TextareaInput
methods have been turned into async methods for more stable async/await control throughout allTextareaInput
methods:- insert
- insertFile
- insertUpload
- prepend
- toggle
- wrap