Kirby 5 is here! Learn more
Skip to content

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) and Kirby\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 (currently changes and latest) #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, improved Kirby\Content\Lock class, which replaces Kirby\Cms\ContentLock

    // examples
    $page->lock()->isLocked()
    $page->lock()->modified()
    $page->lock()->modified('d.m.Y')
    $page->lock()->user()?->username()
  • New Kirby\Content\Changes class replaces Kirby\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 as Kirby\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 (replacing Kirby\Content\ContentTranslation)

  • New Kirby\Content\Translations class to provide a more type-safe collection for all translations (returned by Kirby\Cms\ModelWithContent::translations()).

  • New Kirby\Content\VersionId class to represent versions #6436

View buttons

Data

  • New third $fail argument for Data::read() and Data::decode(). By default, Data::read() and Data::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 for Json::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. #6483

    use 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
  • The files and pages sections introduce new delete 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

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 for this.$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 and model.update event after uploads have successfully completed.

Lab

  • Overview is filterable via a search input #7293
  • Internal components are hidden from docs; unstable components are marked as such #7295
🐛 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 call file.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
  • 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

  • Headers with null as value are no longer added to JS API requests. #6435
  • $helper.object.clone is no longer deprecated. Please use it instead of structuredClone as this might cause issues down the road with Vue 3. #6479
⚠️ 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 receives null 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 to api.methodOverride
  • The content.fileRedirects option is now set to false by default. This protects uploaded file originals from unauthorized downloads. If you rely on the https://example.com/some/page/file.pdf or https://example.com/some-site-file.pdf routes, you can set the option to true 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 method
  • Kirby\Cms\ModelWithContent::lock() will now always return a Kirby\Content\Lock object, even if the model is not currently locked. You can check for that case with ModelWithContent::lock()->isLocked()
  • Kirby\Cms\ModelWithContent::version() and Kirby\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 name version/versions.
  • Kirby\Cms\Page::modified(), Kirby\Cms\File::modifiedContent() and Kirby\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 return void instead of a bool #6660

Content & Locking

  • Removed Kirby\Cms\ContentLock and Kirby\Cms\ContentLocks as well as Kirby\Cms\App::locks()
  • $kirby->contentToken() only accepts objectornull for the $model parameter instead of mixed. #6822
  • Renamed token query param for preview URLs to _token #6823

Pages

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 the visitor role anymore #6656
  • Setting a name field in User::update() does no longer have any effect. Use User::changeName() instead.

Roles and Permissions

Media & Thumbnail generation

Plugins

Forms

  • Kirby\Form\Field::$formFields has been renamed to Kirby\Form\Field::$siblings
  • The $formField argument in Kirby\Form\Field::factory() has been renamed to $siblings
  • You can no longer pass a value to Kirby\Form\Field::isEmpty() Use Kirby\Form\Field::isEmptyValue($value) instead.
  • Kirby\Form\Form::fields() does no longer return null but an empty Kirby\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 and Kirby\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. Use Kirby\Form\Form::toProps() instead, to get the correct disabled state for each field. When using Kirby\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 #7166
  • Kirby\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 as http:// and https://. Please use the Remote class for this purpose. #7099
  • F::read() no longer silently returns false 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() and Str::widont() can no longer be called without a value argument (passing a null 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 blueprint accept 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 to 1. #6635
  • Select field: empty prop was removed. Use combination of requiredplaceholder and default 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 is false) #6109

Vue Components

  • <k-form> and <k-fieldset> as well as many fields and inputs don't emit an invalid event anymore. Use native HTML invalid state of elements instead. #6099
  • novalidate 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>: the move 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>: Removed data-only-option attributes
  • <k-dialog>: Removed data-has-footer attribute
  • <k-toggles-input>: Removed data-disabled attribute
  • <k-writer-input>: Removed data-toolbar-inline attribute
  • <k-bubble>: Removed data-has-text attribute
  • <k-header>: Removed data-has-buttons attribute
  • <k-tag>: Removed data-has-image and data-has-toggle attributes
  • <k-tree>: Removed data-has-subtree attribute

Panel JS API

  • panel.view.isLocked no longer exists. Use panel.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 and PATCH: users/$user/password API routes require an additional currentPassword 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 to copy.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

Plugins

Forms

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 for url option (use href instead) and for rel key (use rel 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 as value => text. #6913

Custom Panel CSS

  • --color-backdrop CSS property has been deprecated. Use --overlay-color-back instead #6299

Vue components

Panel JS API

  • TextareaInput.restoreSelectionCallback() has been deprecated. Use TextareaInput.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 to FileActions and UserActions and use them in their commit methods
  • Remove ::hardcopy() from ::commit() in model actions
  • New Kirby\Cms\HasModels trait
  • New Kirby\Cms\ModelCommit and Kirby\Cms\ModelState classes
  • App::setSite() is now public and can be used to overwrite the current site instance
  • New Page::normalizeProps(), File::normalizeProps() and User::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 and File::__construct call parent::__construct after setting the props #6499
  • Simplify ModelWithContent::writeContent by using the new Version::save() method. #6505
  • Simplify ModelWithContent::content by using Language::ensure() and Version::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

Languages

Forms

Kirby\Form\Form class improvements

Kirby\Form\Field class improvements

Kirby\Form\FieldClass class improvements

Kirby\Form\Fields class improvements

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

Plugins

  • New Kirby\Plugin namespace #6737

Exceptions

  • Exception classes support named arguments #6618

Hooks

API

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

Panel Models

Panel UI Backend

  • Drastically simplified Kirby\Panel\ChangesDialog class, which reads changed models directly on the backend with the new Kirby\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 for api, avatar, id and isLocked instead of going through the model object. The model prop has been removed.
  • The <k-user-profile> component has been refactored to use individual props for api, avatar, email, id, language and role instead of going through the model object. The model object prop has been removed as well as the already deprecated permissions 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 and TextareaInput.restoreSelection() are used to replace the old restoreSelectionCallback method in dialog events for better async control.
  • Various TextareaInput methods have been turned into async methods for more stable async/await control throughout all TextareaInput methods:
    • insert
    • insertFile
    • insertUpload
    • prepend
    • toggle
    • wrap