Changelog
This is the full changelog for Kirby 6.0.0-beta.1. In addition to all the features on the Kirby 6 release page, there are many more enhancements, breaking changes and deprecations in the fine print.
Kirby 6 is still in beta. This changelog will be updated with every pre-release until the final 6.0.0 release. If you are upgrading an existing project, start with our migration guides.
๐ Features
- Preview view: work on your content right next to a live preview of your page, synced across browser windows and viewport sizes
- Passkeys & two-factor for everyone: log in with passkeys, let every user set up their own second factor and define a password policy
- Simpler blueprints: define fields once at the root of a blueprint and reference them in your layout. Sections become fields: new
pagelistandfilelistfields replace thepagesandfilessections. - Buttons field: a new field to open links, dialogs or drawers from a blueprint
- Guards: one place that answers whether an action is possible, allowed and valid
- Content negotiation: content representations can be requested via the
Acceptheader - Template stacks: push output from any snippet and render it anywhere else in your templates
- Better error handling: new error dialogs, stack traces in debug mode and blocked actions that explain themselves
- A modern foundation: a modern PHP baseline, a restructured core and a Panel built on Vue 3, TypeScript and trusted HTML
โจ Enhancements
For editors
- Field labels get highlighted when field has unsaved changes #7794
- Values of disabled Panel fields can be selected #7581
- Better drag sorting in list layouts, e.g. in page and file lists #7349
- Blocks field:
imageandgalleryblock previews now load properly sized thumbs that also respect thecoverandratiosettings #7756 - Page picker: the picker dialog shows a badge for selected children #7687
- File picker: upload files by drag'n'drop onto the dialog https://feedback.getkirby.com/729 #7888
- New Panel login UI/UX: the login view has been refactored to be more driven by the backend. It now features a method picker, a challenge switcher and centralized loading/error handling. #7848
- TOTP management in one drawer: enable/disable TOTP in a single drawer with QR code and a clickable
otpauth://setup-key link. Only users themselves can set up TOTP for their account and confirm the removal with a current code. Admins can remove TOTP for other users after confirming with their own password. #7848 #8268 - A field that fails to be created or to resolve its props shows an error in its place instead of breaking the whole view #8443
- Date and time fields show an example of their
displayformat as placeholder, so the expected notation is visible before typing #8322 - Date field: month names and their abbreviations are recognized in English and in the current Panel language #8327 #8328
- The loading spinner in the topbar only shows up after a short delay, so it no longer flashes for quick requests #8331
- The "browser not supported" page names the browser versions the Panel needs #8450
For site developers
-
Improved IDE autocompletion for field methods #7082
-
Panel only shows missing blueprint info when debug mode is active https://feedback.getkirby.com/392
-
On installation, all required PHP extensions are checked and installation is blocked if one is missing. The Panel system view shows an alert if a required PHP extension is missing. #7812
-
$model->update()andKirby\Form\Form::submit()accept Kirby objects and collections as field values, e.g. a$fileor$filesfor a picker field #8536$page->update([ 'cover' => $file, 'related' => $page->siblings()->listed(), 'authors' => $kirby->users()->role('editor'), 'items' => $page->items()->toStructure(), 'text' => $page->text()->toBlocks(), 'gallery' => $other->gallery(), 'date' => new DateTime(), ]); -
Kirby queries support logical not and unary minus, e.g.
!user.isAdmin ? "guest" : "admin",-page.priceor-(1 + 2)#8309 #8578 -
The
displayformat of date and time fields supports escaped literals #8322fields: meeting: type: date display: D. MMMM [in the year] YYYY time: display: HH[h]mm -
New MIME type mappings.
icoandpsdalso map to their registered types now. #8284Extension MIME type 7zapplication/x-7z-compressedaacaudio/aacapngimage/apngatomapplication/atom+xmlepubapplication/epub+zipodsapplication/vnd.oasis.opendocument.spreadsheetogaaudio/oggrarapplication/vnd.rar,application/x-rar-compressedsvgzimage/svg+xmlvtttext/vttwasmapplication/wasmwebaaudio/webmwebmanifestapplication/manifest+json -
Kirby\Toolkit\Date::optional()acceptsDateTimeInterfaceobjects and UNIX timestamps -
A field option with the wrong type in a blueprint shows a clear error message, e.g.
Field "title": The option "required" must be of type bool#8616 -
New
Kirby\Cms\Language::isLastLanguage()method to check if a language is the only remaining one (the previous meaning ofisLast()) #8582
For plugin developers
Core
-
Custom fields are implemented as PHP classes based on
Kirby\Form\Fieldor any of theKirby\Form\Field\*classes and registered by their class name. You can learn more about this in the "Refactored" section. -
Custom fields declare their options as properties with the new
#[Kirby\Reflection\Attributes\Prop]attribute. All marked options can be set in the blueprint and are sent to the Panel automatically.export: falsekeeps an option in the backend,export: 'name'sends it under a different name, andgetterandsettername the methods that read or normalize the value. #8615 #8616 #8618use Kirby\Form\Field\InputField; use Kirby\Reflection\Attributes\Prop; class RatingField extends InputField { /** * The highest possible rating */ #[Prop] protected int $max = 5; /** * Only used in the backend */ #[Prop(export: false)] protected string|null $query = null; protected mixed $value = null; } -
Custom fields can read additional options from Kirby's config by overriding the new
Kirby\Form\Field::config()method. Options from the blueprint take precedence. #8616 -
The type of a field is always the name it was registered with. A field class that is registered under a different name no longer reports a type derived from its class name. #8622
-
New
Kirby\Cms\Modelbase class, extended byKirby\Cms\ModelWithContentandKirby\Cms\Language, for unified type checks across all models #8369 -
New
Kirby\Cms\User::ensure()method that always returns a user and falls back to an anonymousnobodyuser if nobody is logged in #8369 -
New
Kirby\Exception\AbilityException#8369 -
New
$model->toSafeHtmlString()method, similar to$model->toSafeString(), but the result is marked as trusted HTML for the Panel #8344$page->toSafeHtmlString('<strong>{{ page.title }}</strong>'); -
New
$defaultsargument forKirby\Form\Form::fill()#8400 -
New
Kirby\Form\Field::error()factory to create an error field in place of a field that failed #8443 -
Kirby\Cms\Files::delete()andKirby\Cms\Pages::delete()accept UUIDs and still only delete items in the collection #8315 -
New
Kirby\Blueprint\TabandKirby\Blueprint\Tabsclasses to work with tabs and their props in blueprints #8449 -
New
Kirby\Auth\Service\Webauthnclass #8245 -
Updated
Kirby\Toolkit\Html::$inlineListandKirby\Toolkit\Html::$voidList#8286
Frontend
-
Migrated from Vue 2 to Vue 3 #7104
-
Panel plugins load their scripts as separate modules and their stylesheets as separate files #8603
-
Panel plugins without a build step can use top-level
import, e.g.import { h } from "vue"#8603 -
Panel plugins run after the core components are registered, right before the Panel starts #8603
-
Dialogs and drawers: Added dropzone that becomes active when a
@droplistener is added on the component #7520 -
New
<k-video-frame>component #7755 -
The
<k-table>component has a newresponsiveprop, which is set totrueby default. Switching the responsive mode off will no longer hide columns that are not marked withdata-mobile="true". This gives more control over custom responsive behaviors for tables and also helps to improve the usability in narrow widths. #7770 -
<k-item>has a newselectedprop to control its selection state and aselectmodeprop to select single or multiple items #7516 -
<k-collection>/<k-items>can receive a list ofselecteditems to control selection status from parent #7516 -
<k-collection>supports theskeletontheme also with thetablelayout #8482 -
New
<k-model-picker-dialog>and<k-page-picker-dialog>components #7529 -
New
<k-collapsible>component that can wrap a list of elements with a default and fallback slot and provide the necessary data how many elements fit in the current container width to render the element as a responsive list of visible and hidden elements (the latter represented by the fallback slot content). #7901 -
New
<k-model-form>component #8449 -
New
RequestError.dialog()method to create all props for the request error dialog according to the details from the error object. #7782 -
All errors are now converted to Error objects in
panel.notification.error()#7782 -
New
this.$panel.observersJS module -
The Panel URL is available inside the Panel as
this.$panel.urls.panel#7800 -
New Vue components for login forms:
<k-login-password-method-form>,<k-login-code-method-form>,<k-login-password-reset-method-form>,<k-login-email-challenge-form>,<k-login-totp-challenge-form> -
New helper Vue components for the login view:
<k-login-back>,<k-login-code>,<k-login-footer>,<k-login-challenges>,<k-login-methods>,<k-login-remember>,<k-login-submit>#7840 -
Trusted HTML #8175 #8176 #8344 #8346 #8347 #8348
-
New
Kirby\Toolkit\HtmlStringclass andHtmlStringJS class that wrap and mark strings as safe HTML.HtmlStringvalues (also in arrays) reach the frontend from every Panel JSON response (views, dialogs, drawers, dropdowns, requests) and from API responses to Panel requests. -
New
v-safe-htmlVue directive that only renders passedHtmlStringobjects as HTML and escapes any other passed string -
New
this.$html()Vue helper (shorthandthis.$h()) to mark a string as safe HTML (wraps it in aHtmlStringobject) -
New
this.$th()helper for translations that contain markup: it marks the translation's own HTML as trusted, but escapes everything interpolated into it.v-safe-html="$th('some.key', { name })"is safe even whennamecontains HTML. -
<k-text>has a newtextprop: plain strings are escaped, trusted HTML is rendered as-is<!-- escaped --> <k-text :text="value" /> <!-- rendered as HTML --> <k-text :text="$h(value)" /> <!-- translation rendered as HTML, interpolated data is escaped --> <k-text :text="$th('my.plugin.hint', { name })" />
-
-
New
this.$helper.items()to request preview data for one or more models by ID. Calls made in the same tick are batched into a single request, so components can ask for what they need without coordinating. #8341// a single item const file = await this.$helper.items("items/files", "file://abc"); // a list of items, resolved in the order you asked for them const pages = await this.$helper.items("items/pages", [ "page://a", "page://b", ]); // with a query as third argument const file = await this.$helper.items("items/files", "file://abc", { layout: "auto", image: JSON.stringify({ ratio: "16/9", cover: true }), }); -
<k-image-frame>loads images lazily and decodes them asynchronously. Lazy-loaded images usesizes="auto"if nosizesare specified. Set:lazy="false"for images that are visible right away, e.g. an avatar in the header. #8341 #8438 -
New
$library.dayjs.parse(input, { pattern, strict, type })to parse user input against a display pattern #8328 -
$library.dayjs()follows the locale of the current Panel language #8327
Backend
-
New
items/files,items/pagesanditems/usersPanel request endpoints to turn IDs into item data, backed by the newKirby\Panel\Controller\Request\FileItemsRequestController,Kirby\Panel\Controller\Request\PageItemsRequestControllerandKirby\Panel\Controller\Request\UserItemsRequestControllerclasses #7723 -
New
$kirby->panel()method to accessKirby\Panel\Panelobject #7409 -
New
Kirby\Panel\Controller\Controllerclasses that can be passed by their name asactionargument of a Panel route (dialog, drawer, dropdown, request, search and view) and then handle the route action. This helps to move away from the anonymous closures inconfig/areas/and instead build handler classes that can be properly tested etc. #7422 -
New Panel UI classes:
Kirby\Panel\Ui\Dialog,Kirby\Panel\Ui\Dialog\ErrorDialog,Kirby\Panel\Ui\Dialog\FormDialog,Kirby\Panel\Ui\Dialog\RemoveDialog,Kirby\Panel\Ui\Dialog\TextDialog,Kirby\Panel\Ui\Drawer,Kirby\Panel\Ui\Drawer\FormDrawer,Kirby\Panel\Ui\Drawer\TextDrawer,Kirby\Panel\Ui\View,Kirby\Panel\Ui\View\ErrorView,Kirby\Panel\Ui\Item(foundation forKirby\Panel\Ui\Item\ModelItemetc.) andKirby\Panel\Ui\Item\LanguageItem#7441 #7443 #7468 #7471 -
Kirby\Panel\Response\JsonResponse::from()resolves Panel UI component objects by calling theirKirby\Panel\Ui\Component::render()method, soKirby\Panel\Controller\Controller::load()can return UI component instances #7442 -
New
Kirby\Toolkit\HasI18ntrait that adds aKirby\Toolkit\HasI18n::i18n()helper method to the class which can be used to translate and/or template i18n strings. NewKirby\Panel\Ui\Component::i18n()helper method #7406 #7465 -
Exceptions are no longer intercepted by our Response classes but handled by our regular error handler. This will improve the JSON error responses drastically and expose more details in debug mode. One exception (pun intended) are NotFoundExceptions for views, which will still create a full error view with error message, to make sure that navigation to non-existing routes still works. #7744
-
New
Kirby\Exception\FormValidationException#7769 -
Error responses from the backend now include the
editorURL if the editor is set up in the config.php and debug mode is on. #7782 -
New protected
Kirby\Cms\AppErrors::trace()method to return a stack trace for PHP errors in JSON responses when debug mode is enabled. #7782 -
Auth methods can authenticate without an email, enabling token/SSO-style plugin methods that don't key on email. #7848
-
New
Kirby\Auth\Auth::guard()helper to wrap an auth attempt with rate-limiting and error handling #8260 -
Plugins can remove any core definition from a Panel area by setting it to
false, as was already possible for menu items and view buttons #8357Kirby::plugin('my/plugin', [ 'areas' => [ 'site' => [ 'searches' => [ 'pages' => false ] ] ] ]); -
New
Kirby\Panel\User::info()method that returns the data for<k-user-info>#8245 -
New
Kirby\Panel\Controller\View\ModelViewController::fields()method that returns all form fields of the current tabs and versions #8449
More
- New icons:
hashtag,email-unread,fingerprint this.$panel.t()/window.panel.t()now returns the string key as a fallback if no matching i18n string exists and no actual fallback has been provided
๐ Security
- Cookies are now signed with HMAC-SHA256 instead of HMAC-SHA1 #8561
Kirby\Http\Cookie::set()adds theSecureflag by default when the site is served over HTTPS #8560- Panel components escape plain strings and only render HTML that has been marked as trusted (
Kirby\Toolkit\HtmlString), e.g. in<k-item>,<k-text>,<k-box>and<k-tags>. The block pasteboard, block selector and installation view no longer usev-htmlat all. #8344 #8348 - Hardened security of
Kirby\Session\Session(thx @XananasX7)
๐๏ธ Performance
Core
- Normalized blueprints are cached #8449
- Block fieldsets no longer build their forms upfront. Saving a page with a
blocksfield is faster when the blueprint registers more block types than the content uses. #8391 - Constructor parameter names are resolved once per class instead of once per reflection #8390
Kirby\Exception\Exceptionand its subclasses resolve their code and message lazily #8459
Panel
- Panel routes resolve their controller classes lazily, so building the route table no longer autoloads every area controller #8366
- Typing inside a block, layout, entries or structure row no longer re-renders the surrounding field on every keystroke #8449
- The blocks field only renders the toolbar of the selected block instead of one hidden toolbar per block #8447
pagelistandfilelistfields withlayout: tableload faster. Their performance only depends on the number of displayed columns, no longer on the size of the blueprint. #8439- Requests for model item preview data are batched: components that ask for a file or page in the same tick share a single request instead of firing one each #8341
panel.content.diff()is computed once per change instead of on every call #8340- ProseMirror is no longer part of the initial Panel bundle but imported when needed #8342
- The icon sprite is no longer inlined into every Panel document #8445
- Browsers cache each plugin script and stylesheet until the file changes #8603
๐ Bugfixes
Core
- Fixed auto-closing open snippets at the end of a nested snippet (thx to @JojOatXGME) #7567
Kirby\Filesystem\Exifnow supports arrays forISOSpeedRatings#7569Kirby\Form\Field::stringTemplate()now usesKirby\Cms\ModelWithContent::toSafeString()by default and introduces a new$safeargument, which can switch to the unsafe method. #7687- Login-failed hook is no longer fired twice. #7848
Kirby\Text\KirbyTag::__set()now lowercases the properties, asKirby\Text\KirbyTag::__get()already didKirby\Toolkit\Str::date(null, null)returns the current timestamp- Fixed
Kirby\Toolkit\A::merge()with empty input Kirby\Image\Exif::parseTimestamp()returnsnullfor a missing timestamp nowKirby\Filesystem\File::realpath()returnsfalsewhen the file does not exist at the path- Actions run their checks against the model returned by a
beforehook, not the original one #8364 - Changing a user's role or secrets no longer fails with an unexpected error when nobody is logged in #8364
- Fields without a value no longer break saving #8449
new Exception(message: '…', previous: $previous)no longer discards$previous#8459- Discarded
Kirby\Cms\Appinstances are no longer kept in memory by Whoops handlers, KirbyTag closures and translation loaders. An app created withsetInstance: falseno longer takes over the global translation loader. #8339 - The number field stores an empty value instead of
0for non-numeric input #8534 - JSON responses with invalid UTF-8 fail with an error instead of going out as an empty
200. JSON error responses are no longer empty when the exception message or details contain invalid UTF-8. #8562 - Queries:
- Backslashes in strings are kept, e.g. in regex patterns like
'\d+'. Only\',\"and\\are escapes. #8580 - Subtraction works without spaces, e.g.
page.num-1#8578 ??,?:,? :,&&and||only evaluate the operand they need #8576- Each query is resolved with its own
intercept(), even if another query was created in between #8579 - Changes to
Kirby\Query\Query::$entries(e.g. from plugins) also reach queries that were resolved before #8579 {{ 0 }}resolves to0instead of the data array #8577Kirby\Toolkit\Str::template(): empty placeholders like{}or{{ }}stay as they are instead of failing with "Array to string conversion" #8577
- Backslashes in strings are kept, e.g. in regex patterns like
- Field class names that contain
Fieldin the middle, e.g.FieldWithDialogsField, no longer lose that part in their type #8622
Panel
- The toggle field uses
<k-toggle-input>instead of<k-input type="toggle">, like the radio and checkboxes fields #7489 <k-item>only hides the default options button in selecting mode, not a custom options slot #7516<k-item>is selectable by default unless explicitly defined otherwise #7516<k-item>:selectedalso works with UUIDs #7751- The languages button no longer shows a badge for current changes #7749
- Context data (path, referrer, query, code) is always added to the view response again, so error views get the correct URL instead of causing side effects like redirects to
/panel/null#7744 - Listeners of backend-defined dialogs and drawers are preserved when loading them #7888
- Writer field: pasting text that contains an email address now turns it into an email link even when the address is surrounded by other text #8110
- Writer field: Markdown shortcuts for headline levels that aren't enabled (e.g.
#withouth1) are no longer converted #8111 - Date and time fields read the input in the field's own
displayformat instead of guessing. Input that cannot be read is kept and the field is marked invalid, instead of silently clearing the field. #8322 - Time fields word their
min/maxvalidation messages as times instead of dates #8322 $library.dayjs.iso()parses strictly #8325$library.dayjs.validate()is as strict as the validation in the backend #8329$helper.url.buildQuery()supports nested objects as params #8349$helper.string.template()no longer HTML-escapes the placeholder key, which prevented lookups for keys containing characters like/orₜ- The "Split" option is no longer missing from the block options on first render #8447
- A table column with
value: "0"renders0instead of falling back to the field value #8439 - Sorting no longer breaks when a collection becomes sortable while the drag library is still loading #8482
โ ๏ธ Breaking changes
Core
General
- Removed support for PHP 8.2. Use PHP 8.3, 8.4 or 8.5 instead. #7372
- Changed the default YAML handler to Symfony YAML which sometimes enforces a stricter syntax than our previous Spyc handler. You can switch back to Spyc with the config option
'yaml.handler' => 'spyc'#7530 - New global helper functions
push(),endpush()andstack()can collide with functions of the same name in your code #7867 - Template data must not include variables named
$slotor$slots. #7599 videoKirbyTag: Removedstyleoption to protect against style injections. If you need to define a customstyleattribute, please extend as a custom KirbyTag. Thanks to Peter Levashov (@petersevera) for his responsible disclosure and suggestion.- Custom validators cannot overwrite default validators from the
Kirby\Toolkit\Vclass any longer. #7674 - Removed
Kirby\Cms\Apiclass. UseKirby\Api\Apiclass instead. #7532 - Removed
Kirby\Cms\System::php()#7816 Kirby\Cms\App::models()andKirby\Uuid\Uuid::index()generators are now keyed by idKirby\Cms\LazyCollection::getIterator()skips items that failed hydrationKirby\Cms\FieldsextendsKirby\Cms\CollectionandKirby\Cms\HasSiblingsrelies onKirby\Cms\Collection, notKirby\Toolkit\CollectionKirby\Cms\Fieldset::name()falls back to a labelized type- Added abstract
Kirby\Cms\ModelWithContent::apiUrl()method Kirby\Data\Txt::encodeValue()encodestrueandfalseas'true'and'false'instead of'1'and'0', and an empty array as empty string instead of[]Kirby\Http\VolatileHeaders::append()requires an array as third parameterKirby\Toolkit\Str::float()returnsnullinstead of'0'for non-numeric values (includingnulland''). UseKirby\Toolkit\Str::float($value) ?? '0'if you relied on the old behavior. #8534- Removed
command,keygenandparamfromKirby\Toolkit\Html::$voidList, as they are obsolete and no longer part of the WHATWG list of void elements.Kirby\Toolkit\Html::isVoid()returnsfalsefor them andKirby\Toolkit\Html::tag()no longer renders them self-closing. #8286 qr()helper only accepts a site, page or file object or a URL string as parameter.Kirby\Cms\Language::isLast()checks the language's position in the languages collection, likeisLast()for other models. Use the newKirby\Cms\Language::isLastLanguage()to check if it is the only remaining language. #8582
Cookies & HTTP
- Cookies are signed with HMAC-SHA256 instead of HMAC-SHA1. Cookies signed by earlier versions, including the session cookie, are no longer accepted: users need to log in again after the upgrade. #8561
Kirby\Http\Cookie::set()sets thesecureoption totrueon HTTPS requests by default. Pass'secure' => falseif a cookie set on an HTTPS page must also be readable on plain HTTP pages:Cookie::set('name', 'value', ['secure' => false])#8560- The
$prettyargument ofKirby\Http\Response::json()must be abool. Passfalseinstead ofnull. #8562
MIME types
Kirby\Filesystem\Mime::fromExtension() and Kirby\Filesystem\Mime::type() return the registered IANA type for these extensions now (e.g. RFC 6713 for gzip, RFC 9239 for JavaScript, RFC 7303 for XML). #8284
| Extension | Before | Now |
|---|---|---|
exe |
application/octet-stream |
application/vnd.microsoft.portable-executable |
gz, gzip |
application/x-gzip |
application/gzip |
js |
application/javascript |
text/javascript |
ppt |
application/powerpoint |
application/vnd.ms-powerpoint |
psd |
application/x-photoshop |
image/vnd.adobe.photoshop |
tgz |
application/x-tar |
application/gzip |
wbxml |
application/wbxml |
application/vnd.wap.wbxml |
xl, xls |
application/excel |
application/vnd.ms-excel |
xml |
text/xml |
application/xml |
xsl |
text/xml |
application/xslt+xml |
zip |
application/x-zip |
application/zip |
Kirby\Filesystem\Mime::toExtension() returns different results for MIME types whose secondary mapping was removed:
| MIME type | Before | Now |
|---|---|---|
application/x-gzip-compressed |
tgz |
false |
application/octet-stream |
csv |
exe |
Field methods
- Calling non-existing field methods throws a
Kirby\Exception\BadMethodCallException. #7082 - Removed
Kirby\Content\Field::$aliases,Kirby\Cms\Core::fieldMethods()andKirby\Cms\Core::fieldMethodsAliases(). #7082
UUIDs
Kirby\Uuid\Uuid::for()does not resolve any permalinks anymore. UseKirby\Uuid\Permalink::from()instead. #7545Kirby\Uuid\Uuid::for()cannot be called any longer with a string. UseKirby\Uuid\Uuid::from(string $uuid)orKirby\Uuid\Permalink::from(string $permalink)instead. #7544- Removed deprecated
Kirby\Uuid\Uuid::url(). UseKirby\Uuid\Uuid::toPermalink()instead.
Queries
- Removed the legacy query runner. If your config sets
query.runnertolegacy, remove that option. Queries always use the AST-basedKirby\Query\Runners\DefaultRunnernow. #7791 #8554 - Removed
Kirby\Query\Argument,Kirby\Query\Arguments,Kirby\Query\Expression,Kirby\Query\SegmentandKirby\Query\Segments. UseKirby\Query\Query::resolve()or a customKirby\Query\Runners\Runnerinstead. #8554 Kirby\Query\Visitors\Visitor: required methods are abstract now and get enforced when extending the class.Kirby\Query\Visitors\Visitor::coalescence(),Kirby\Query\Visitors\Visitor::logical()andKirby\Query\Visitors\Visitor::ternary()receive the right operand/branches asClosure. #8576
Sessions
- Merged
Kirby\Session\AutoSessionintoKirby\Session\Sessions#8248 Kirby\Session\Sessions::get()no longer accepts a$token. UseKirby\Session\Sessions::find()instead. #8248new Kirby\Session\Sessions()no longer accepts an$optionsargument. UseKirby\Session\Sessions::factory()instead. #8248Kirby\Session\Sessionno longer serializes objects
Exceptions
- Passing a single array argument to
Kirby\Exception\Exceptionis no longer supported. Use named arguments instead. The string shorthandnew Exception('Some message')is unchanged. #8459 - Removed
Kirby\Exception\Exception::isTranslated()#8459
Permissions
- Several i18n error keys and strings have changed #8364
Kirby\Cms\Permissions::for()allowsnullas default #8369- Removed
Kirby\Cms\ModelPermissions::canFromCache(). Use$model->guards()->isAvailable()instead. #8481
Forms
Custom fields
- Custom fields can no longer be defined as arrays. Create a class based on
Kirby\Form\Field(or one of theKirby\Form\Field\*classes) and register it by its class name. To extend a core field, extend its class (e.g.Kirby\Form\Field\TextField). #8395 #8396 - Removed
Kirby\Form\FieldClassand thelegacy-*fields.Kirby\Form\Fieldhas been fully rewritten as base class for all fields. It has a newKirby\Form\Field::id()method and implementsStringable. #8395 #8399 - Removed the
Kirby\Form\Mixin\Valuemixin in favor of the newKirby\Form\Field\ValueFieldbase class. Custom fields with a value must extendKirby\Form\Field\ValueField(orKirby\Form\Field\InputField), as the now finalKirby\Form\Field::hasValue()checks for it. The deprecatedKirby\Form\Mixin\Value::data()andKirby\Form\Mixin\Value::save()methods are replaced byKirby\Form\Field\ValueField::toStoredValue()andKirby\Form\Field::hasValue(). #8400 #8401 - Fields with subfields must implement the new
Kirby\Form\Interface\ProvidesNestedForminterface to be found by nested lookups likeKirby\Form\Fields::findByKeyRecursive('parent+child')#8401 - Field options are no longer constructor parameters. Declare each option as a property with the
#[Kirby\Reflection\Attributes\Prop]attribute instead. A custom constructor must accept all other options asmixed ...$argsand pass them on toparent::__construct(...$args), otherwiseKirby\Form\Field::resolve()throws an exception. #8492 #8616 #8620 Kirby\Form\Field::factory()has been removed. Create fields withnew, e.g. with the class fromKirby\Form\Field::resolve($type):new $class(...$props)#8620- Field props are stored as passed: all setters of field classes and mixins have been removed (set the properties directly), and defaults, translations (
after,before,empty,help,label,placeholder) and the lower-casing of the name are applied in the getters instead. This keeps the originally passed values accessible and reduces the work done on instantiation. - The model and siblings of a field are passed to the constructor as
modelandsiblingsarguments and can't be changed afterwards. There are nosetModel()andsetSiblings()methods. An initial value can be passed asvalueargument and is filled after all other props are set. #8620 #8621 files,pagesandusersare no longer registered field types. They still work in blueprints and are mapped tofilepicker,pagepickeranduserpicker. Code that looks up a field class inKirby\Form\Field::$typesmust use the new names. #8622- Fields define their API routes in
Kirby\Form\Field::api(), not in aroutes()method - Removed
Kirby\Cms\Picker,Kirby\Cms\PagePicker,Kirby\Cms\FilePickerandKirby\Cms\UserPicker. UseKirby\Panel\Controller\Dialog\ModelPickerDialogController,Kirby\Panel\Controller\Dialog\PagePickerDialogController,Kirby\Panel\Controller\Dialog\FilePickerDialogControllerandKirby\Panel\Controller\Dialog\UserPickerDialogControllerinstead. #8395
Form class
- Removed deprecated
Kirby\Form\Formmethods #8400 Kirby\Form\Form::for()andnew Kirby\Form\Form()require named arguments. A$propsarray is no longer accepted. #8400Kirby\Form\Fields::validate()andKirby\Form\Form::validate()throw the more specificKirby\Exception\FormValidationException. #7769
Field behavior
-
The
checkboxes,color,multiselect,radio,select,tagsandtogglesfields no longer remove invalid values on submit or fill, but use the option validator to warn about them. This is in line with other input fields and has massive performance benefits. It also means that you can deliberately store a non-existing option if you skip validation. -
The
apiandqueryoptions of these fields are no longer available. Queries and API calls to fetch options have to be declared directly in theoptionsproperty:fields: myRadio: type: radio options: type: query query: some.query myOtherRadio: type: radio options: type: api url: /some/options/api -
Kirby\Form\Field\NumberField::toNumber()andKirby\Form\Field\RangeField::toNumber()returnnullinstead of an empty string for empty values -
The text field no longer sets the
spellcheckattribute by default -
The
filepicker,pagepickeranduserpickerfields only exchange UUIDs/IDs with the backend and their picker dialog, instead of full item objects with display data
Blueprints
- Removed blueprint presets (
preset: page,preset: pages,preset: files). Define the layout directly with fields likepagelistandfilelistinstead. #8386 Kirby\Blueprint\Blueprint::factory()requires the$modelas first argument. Some blueprint props are translated lazily, so preferKirby\Blueprint\Blueprint::factory()overKirby\Blueprint\Blueprint::load().Kirby\Blueprint\Blueprint::tab()returns aKirby\Blueprint\Tabobject andKirby\Blueprint\Blueprint::tabs()returns aKirby\Blueprint\Tabscollection. The normalized tabs no longer contain their link, which is built by theKirby\Blueprint\Tabclass instead. #8449- The
$inSectionargument ofKirby\Blueprint\AcceptRules::fileTemplates(),Kirby\Blueprint\Blueprint::acceptedFileTemplates()andKirby\Cms\File::blueprints()has been renamed to$inField#8406 - Removed the
Kirby\Blueprint\Blueprint::$fileTemplatesproperty and the protected methodsKirby\Blueprint\Blueprint::acceptedFileTemplatesFromFields(),Kirby\Blueprint\Blueprint::acceptedFileTemplatesFromFieldsets()andKirby\Blueprint\Blueprint::acceptedFileTemplatesFromFieldUploads()#7829
Changed return types
| Before | Now | |
|---|---|---|
Kirby\Http\Request::domain() |
string | string|null |
Kirby\Image\Exif::parseTimestamp() |
string | string|null |
Kirby\Cms\Site::modified() |
int|string | int|string|false |
Kirby\Filesystem\Dir::modified() |
int|string | int|string|false |
Kirby\Filesystem\File::realpath() |
string | string|false |
Kirby\Toolkit\V::value() |
bool|array | true|array |
Kirby\Cms\LicenseStatus::info() |
string | HtmlString |
Kirby\Form\Mixin\Help::help() |
string|null | HtmlString|null |
Kirby\Form\Mixin\Text::text() |
string|null | HtmlString|null |
Kirby\Form\Field\ToggleField::text() |
array|string|null | array|HtmlString|null |
Kirby\Panel\Ui\Item::text() |
string | string|HtmlString |
Kirby\Panel\Ui\Item::info() |
string|null | string|HtmlString|null |
Kirby\Panel\Ui\Item\ModelItem::text() |
string | HtmlString |
Kirby\Panel\Ui\Item\ModelItem::info() |
string|null | HtmlString|null |
Kirby\Panel\Lab\Doc::kt() |
string | HtmlString |
Kirby\Toolkit\HasI18n::i18n() |
string|null | string|HtmlString|null |
HtmlString refers to Kirby\Toolkit\HtmlString #8344. Cast it with (string) if you need the raw string, and compare arrays that contain it with ==/assertEquals() instead of ===/assertSame(). The array returned by Kirby\Form\Field\ToggleField::text() contains Kirby\Toolkit\HtmlString entries, and Kirby\Toolkit\HasI18n::i18n() passes a Kirby\Toolkit\HtmlString $key through unchanged.
Changed exceptions
| Case | Before | Now |
|---|---|---|
| Actions that are impossible for everyone | Kirby\Exception\PermissionException |
Kirby\Exception\AbilityException (new) |
| Deleting an avatar that does not exist | Kirby\Exception\NotFoundException |
Kirby\Exception\AbilityException |
| Changing a file or page to an invalid template | Kirby\Exception\LogicException |
Kirby\Exception\InvalidArgumentException |
Kirby\Cms\App::resolve() when the home page is missing, which indicates a broken installation |
Kirby\Exception\NotFoundException |
Kirby\Exception\LogicException |
Methods that newly throw
| Before | Now | |
|---|---|---|
Kirby\Toolkit\Dom::query() |
returns false |
throws if query invalid |
Kirby\Cache\Value::toJson() |
throws for invalid JSON | |
Kirby\Data\Json::encode() |
throws for invalid JSON | |
Kirby\Filesystem\File::toJson() |
throws for invalid JSON | |
Kirby\Http\Uri::toJson() |
throws for invalid JSON | |
Kirby\Toolkit\Collection::toJson() |
throws for invalid JSON | |
Kirby\Toolkit\Obj::toJson() |
throws for invalid JSON | |
Kirby\Filesystem\File::sha1() |
returns false |
throws on missing file |
Kirby\Content\Version::contentFile() |
throws when called with a storage other than Kirby\Content\PlainTextStorage |
|
Kirby\Filesystem\Dir::realpath() |
throws when $dir itself is passed as $in |
Sections
Sections have been replaced by fields (see "Sections become fields" above). Blueprints with fields, files, info, pages and stats sections keep working, as they are converted to fields automatically. Everything else around sections has been removed. #8449
- Any other section type, including custom sections from plugins, is no longer supported in blueprints
- Removed the
sectionsplugin extension, along withKirby\Cms\App::extendSections(),Kirby\Cms\Core::sections(),Kirby\Cms\Core::sectionMixins(),Kirby\Cms\Loader::sections()andKirby\Cms\Loader::section() - Removed
Kirby\Blueprint\Section, theKirby\Cms\Sectionalias,Kirby\Blueprint\Blueprint::section(),Kirby\Blueprint\Blueprint::sections()andKirby\Api\Api::sectionApi() - Removed all
…/sections/(:any)and…/sections/(:any)/(:all?)API routes for the site, pages, users and their files - Removed all section dialog and drawer routes and their Panel controller classes
- The blueprints API endpoints (
/api/site/blueprints,/api/pages/(:any)/blueprintsand/api/users/(:any)/blueprints) accept afieldquery parameter instead ofsection. Thesectionargument ofpanel.api.pages.blueprints()andpanel.api.users.blueprints()has been renamed tofieldas well. - Removed components:
<k-sections>,<k-fields-section>,<k-files-section>,<k-info-section>,<k-models-section>,<k-pages-section>and<k-stats-section>, as well as thek-section-fieldadapter and thesectionplugin mixin. Use<k-model-form>instead of<k-sections>and<k-fields-section>. - The
endpointsobject of field components no longer contains asectionendpoint - The
section.loadedevent has been replaced byfield.loaded, emitted bypagelistandfilelistfields #8415 - Renamed i18n keys
error.section.files.*โerror.field.filelist.*error.section.pages.*โerror.field.pagelist.*error.page.move.noSectionsโerror.page.move.noBlueprints
- Removed i18n keys:
error.section.notLoaded,error.section.type.invalid
Panel
General
- The Panel needs Chrome 124, Edge 124, Firefox 125, Safari 17.5 or newer, i.e. browsers released from roughly mid-2024 onwards. Kirby follows Baseline "widely available": we only rely on web platform features that have been in every major browser for at least 30 months. #8450
panel.faviconoption: Usehrefinstead ofurlattribute. Userelattribute instead of passing string as key.- Color field options
text => valuenotation has been removed. Please rewrite your options asvalue => text. #7534 media/plugins/index.cssandmedia/plugins/index.jsno longer exist. Each plugin's files are served atmedia/plugins/{vendor}/{name}.{hash}.cssandmedia/plugins/{vendor}/{name}.{hash}.jsinstead. #8603
Frontend
- All plugins that have compiled their Vue Single File Components with Vue 2 have to recompile their SFC for Vue 3 to work with Kirby 6. Consider also the Vue 3 migration guide.
- All plugin JS files get loaded as module. Plugin scripts no longer share one scope, so a plugin can't read another plugin's top-level variables. Put shared values on
windowexplicitly. #8603 - The icon sprite is no longer part of the Panel document. Custom icons registered by plugins keep working, but markup that references the sprite by hand (
<use xlink:href="#icon-…">) needs the sprite's URL now:window.panel.urls.icons + "#icon-edit"#8445 - The Panel no longer sets a
data-overlayattribute. Use:has(.k-overlay[open])instead. #8343 - Renamed components
<k-dropdown-content>โ<k-dropdown>. Thealignprop has been removed. Usealign-xinstead. #7535<k-fiber-dialog>โ<k-state-dialog><k-fiber-drawer>โ<k-state-drawer>
- Removed deprecated components
<k-bubble>,<k-bubbles>and<k-bubbles-field-preview>. Use<k-tag>,<k-tags>and<k-tags-field-preview>instead. #7533<k-settings-view-button>and<k-status-view-button>
- Changes in components
- Radio input does not support the
resetoption anymore. Use the toggles input instead. #7385 <k-panel-menu>requires its props to be passed explicitly instead of using$panel.menuitself. #7381- Removed deprecated
modelprop from model views. Use the top-level props instead. #7463 <k-collection>and<k-items>:@selectevents pass an array of selected IDs, not a single item object #7516<k-structure-drawer>:prev/nextneed a boolean as value, not an object anymore #7790<k-item>:textandinfoare escaped unless they are trusted HTML. Plugins that pass pre-escaped or raw HTML strings will see the markup as visible characters. Wrap the value with$h()(frontend) or in aKirby\Toolkit\HtmlString/$model->toSafeHtmlString()(backend). #8344<k-tags>/<k-picklist-input>: an optiontextis only rendered as HTML if it is trusted HTML. Plain strings are escaped, and the search highlighting escapes untrusted text before adding its<b>marker. #8344<k-box>: thehtmlslot binding has been removed.<slot v-bind="{ text, html }">is now<slot v-bind="{ text }">, wheretextis the resolved (possibly trusted) content. #8344<k-models-field-preview>: thehtmlprop no longer defaults totrue. Model items already carry trusted HTML, so the raw rendering is preserved without the flag. #8344<k-installation-view>: the DOM has been fully restructured #7876<k-progress>: the<progress>element is now wrapped in a<label>#8330- The
filepicker,pagepickeranduserpickerfields use their full name in CSS classes:.k-filepicker-field,.k-pagepicker-field,.k-userpicker-field image,galleryandvideoblock previews receive the file UUID instead of full file item data
- Radio input does not support the
- View changes
- Request changes: the term โFiberโ is gone for backend requests
- The
window.fiberglobal has been replaced withwindow.panelState - The
X-Fibernamespace in request headers has been replaced withX-Panel - Keys aren't prefixed with
$anymore in request responses. Use without prefix. This also affects Panel plugins reloading the Panel by defining only specific keys to be reloaded. #7365
- The
- Helpers
- Removed
$helper.isVueComponent()#7518 - Removed
$helper.link.preview(). Use<k-pages-field-preview>or<k-files-field-preview>to render a model preview, or$helper.items("items/pages", id)/$helper.items("items/files", id)if you need the raw data. #7725 #8341 $helper.string.sanitizeHTML()is asynchronous now #8342- Removed
$library.dayjs.merge()
- Removed
- Removed deprecated
panel.dialog.openComponent()method #7518 panel.notification.error()no longer resolves nested errors in the state. Always throw Exceptions instead to create first-level error responses. #7782- Removed deprecated v3 CSS properties #7825
Backend
Moved and replaced classes and methods:
| Before | Now |
|---|---|
Kirby\Panel\ChangesDialog |
Kirby\Panel\Controller\Dialog\ChangesDialogController |
Kirby\Panel\PageCreateDialog |
Kirby\Panel\Controller\Dialog\PageCreateDialogController |
Kirby\Panel\View |
Kirby\Panel\Response\ViewResponse (most of its functionality) |
Kirby\Panel\Document |
Kirby\Panel\Response\ViewDocumentResponse (most of its functionality) |
Kirby\Panel\Dialog |
Kirby\Panel\Response\DialogResponse |
Kirby\Panel\Drawer |
Kirby\Panel\Response\DrawerResponse |
Kirby\Panel\Dropdown |
Kirby\Panel\Response\DropdownResponse |
Kirby\Panel\Json |
Kirby\Panel\Response\JsonResponse |
Kirby\Panel\Request |
Kirby\Panel\Response\RequestResponse |
Kirby\Panel\Search |
Kirby\Panel\Response\SearchResponse |
Kirby\Panel\View::apply(), Kirby\Panel\View::applyGlobals(), Kirby\Panel\View::applyOnly(), Kirby\Panel\View::data(), Kirby\Panel\View::globals(), Kirby\Panel\View::searches() |
Kirby\Panel\State |
Kirby\Panel\Controller\Search |
Kirby\Panel\Controller\Search\FilesSearchController, Kirby\Panel\Controller\Search\ModelsSearchController, Kirby\Panel\Controller\Search\PagesSearchController or Kirby\Panel\Controller\Search\UsersSearchController |
Kirby\Panel\Controller\PageTree |
Kirby\Panel\Controller\Request\PageTreeRequestController or Kirby\Panel\Controller\Request\PageTreeParentsRequestController |
Kirby\Panel\Field::dialog() |
Kirby\Panel\Controller\Dialog\FieldDialogController |
Kirby\Panel\Field::drawer() |
Kirby\Panel\Controller\Drawer\FieldDrawerController |
Kirby\Panel\Ui\Buttons\* |
Kirby\Panel\Ui\Button\* |
Kirby\Panel\Ui\FilePreviews\* |
Kirby\Panel\Ui\FilePreview\* |
Kirby\Panel\Ui\Buttons\LanguagesDropdown |
Kirby\Panel\Ui\Button\LanguagesButton |
Kirby\Panel\Ui\Buttons\LanguagesDropdown::option(), Kirby\Panel\Ui\Buttons\LanguagesDropdown::options() |
Kirby\Panel\Controller\Dropdown\LanguagesDropdownController |
Kirby\Panel\Home::isPanelUrl() |
Kirby\Panel\Panel::isPanelUrl() |
Kirby\Panel\Home::panelPath() |
Kirby\Panel\Panel::path() |
Kirby\Panel\Panel::area() |
Kirby\Panel\Areas::area() |
Kirby\Panel\Panel::buttons() |
Kirby\Panel\Areas::buttons() |
Kirby\Panel\Panel::firewall(), Kirby\Panel\Panel::hasAccess() |
Kirby\Panel\Panel::access()->area() |
Kirby\Panel\Panel::isFiberRequest() |
Kirby\Panel\Panel::isStateRequest() |
Kirby\Panel\Panel::routesForViews() |
Kirby\Panel\Routes\ViewRoutes |
Kirby\Panel\Panel::routesForSearches() |
Kirby\Panel\Routes\SearchRoutes |
Kirby\Panel\Panel::routesForDialogs() |
Kirby\Panel\Routes\DialogRoutes |
Kirby\Panel\Panel::routesForDrawers() |
Kirby\Panel\Routes\DrawerRoutes |
Kirby\Panel\Panel::routesForDropdowns() |
Kirby\Panel\Routes\DropdownRoutes |
Kirby\Panel\Panel::routesForRequests() |
Kirby\Panel\Routes\RequestRoutes |
- Removed methods
Kirby\Panel\Model::isDisabledDropdownOption()#7425Kirby\Panel\Model::toPrevNextLink()and the deprecatedKirby\Panel\Model::content()(also onKirby\Panel\Site,Kirby\Panel\Page,Kirby\Panel\FileandKirby\Panel\User) #7480fileResponse()/toFiles(),pageResponse()/toPages()anduserResponse()/toUsers()of the formerfiles,pagesandusersfield definitions. UseKirby\Form\Field\ModelPickerField::toItem()andKirby\Form\Field\ModelPickerField::toFormValue()instead. #7528Kirby\Panel\Plugins::url(). UseKirby\Panel\Plugins::css()for the plugin stylesheet URLs andKirby\Panel\Plugins::js()for the plugin script URLs. #8603Kirby\Panel\Plugins::files(),Kirby\Panel\Plugins::modified(),Kirby\Panel\Plugins::read()and theKirby\Panel\Plugins::$filesproperty. The newKirby\Panel\Plugins::resolve()serves each plugin's stylesheet and script on its own. #8603
- Changed methods
Kirby\Panel\Controller\Dialog\PageCreateDialogControlleris initiated with a parent model (page/site) and the available blueprints #7466 #8449Kirby\Panel\PanelandKirby\Panel\Homeand their methods are non-static. Instead ofKirby\Panel\Panel::router($path), use$panel->router()?->call($path). #7394 #7407 #7409Kirby\Panel\Panel::areas()returns aKirby\Panel\Areascollection ofKirby\Panel\Areaobjects instead of an array. TheKirby\Panel\Menuclass has been rewritten to use them. #7391 #7406- The argument of the
Kirby\Panel\Ui\Button\ViewButtonsconstructor has changed #7462 Kirby\Panel\Ui\Button\ViewButtons::view()accepts aKirby\Panel\Controller\View\ModelViewControlleras$viewargument, instead of aKirby\Panel\Model#7480Kirby\Panel\Ui\Button\VersionsButton::__construct(): the$versionIdparameter has been renamed to$mode#7548Kirby\Panel\Assets::icons()returns the URL of the icon sprite instead of its markup #8445
- Registering field dialogs or drawers without a closure throws an exception #7512
Auth
- Custom auth challenges must be rewritten based on the redesigned
Kirby\Auth\Challengeclass (instead ofKirby\Cms\Auth\Challenge) #8044 Kirby\Auth\StatusreplacesKirby\Cms\Auth\Statuseverywhere, e.g. as return value of$auth->status().Kirby\Cms\Auth\Status::is()andKirby\Cms\Auth\Status::clone()have no equivalent in the new class.Kirby\Auth\Auth::validatePassword()andKirby\Auth\Auth::verifyChallenge()returnKirby\Cms\UserornullKirby\Cms\Find::user()throwsKirby\Exception\UserNotFoundException- Removed
Kirby\Cms\Auth::ipHash(). Use$visitor->ip(hash: true)instead. - Auth session format changed:
kirby.challenge.codeโkirby.challenge.data. In-flight challenges across the Kirby upgrade won't verify. - Removed the translation strings
login.code.label.loginandlogin.code.label.password-reset - Removed the
loginextension type ofpanel.plugin()(panel.plugins.login). Register your custom login UI as a normalcomponentinstead and reference it in theKirby\Auth\Method::form()orKirby\Auth\Challenge::form()method of your custom auth method or challenge. #8045 - Removed
<k-login-form>,<k-login-code-form>and the deprecated aliases<k-login>and<k-login-code>#8045 - The Panel login routes are multi-step now:
login/method/...andlogin/challenge/... - The TOTP enable/disable dialogs (
Kirby\Panel\UserTotpEnableDialog,Kirby\Panel\UserTotpDisableDialogand<k-totp-dialog>) have been replaced byKirby\Panel\Controller\Drawer\UserTotpDrawerControllerand<k-user-totp-drawer>#7445
โ ๏ธ Deprecated
Deprecated classes, methods, components and options keep working for now, but will be removed in a future major version.
Core
General
| Deprecated | Use instead |
|---|---|
Spyc YAML handler ('yaml.handler' => 'spyc') |
Symfony YAML (default) |
Kirby\Cms\Blueprint |
Kirby\Blueprint\Blueprint |
Kirby\Cms\FileBlueprint |
Kirby\Blueprint\FileBlueprint |
Kirby\Cms\PageBlueprint |
Kirby\Blueprint\PageBlueprint |
Kirby\Cms\SiteBlueprint |
Kirby\Blueprint\SiteBlueprint |
Kirby\Cms\UserBlueprint |
Kirby\Blueprint\UserBlueprint |
files, pages and users field types |
filepicker, pagepicker and userpicker (aliases removed in the next major release) |
Kirby\Cms\PageRules, Kirby\Cms\FileRules, Kirby\Cms\UserRules, Kirby\Cms\SiteRules, Kirby\Cms\LanguageRules |
$model->guards() |
$model->permissions() and the permission classes behind it |
$model->guards() |
Kirby\Field\FieldOptions |
Kirby\Form\FieldOptions |
Auth
| Deprecated | Use instead |
|---|---|
Kirby\Cms\Auth |
Kirby\Auth\Auth |
Kirby\Cms\Auth\Status |
Kirby\Auth\Status |
Kirby\Auth\Auth::login2fa() |
Kirby\Auth\Auth::authenticate() |
Kirby\Auth\Auth::enabledChallenges() |
Kirby\Auth\Challenges::enabled() via $kirby->auth()->challenges()->enabled() |
Kirby\Auth\Auth::isBlocked() |
Kirby\Auth\Limits::isBlocked() via $kirby->auth()->limits()->isBlocked() |
Kirby\Auth\Auth::log() |
Kirby\Auth\Limits::log() via $kirby->auth()->limits()->log() |
Kirby\Auth\Auth::logfile() |
Kirby\Auth\Limits::file() via $kirby->auth()->limits()->file() |
Kirby\Auth\Auth::track() |
Kirby\Auth\Limits::track() via $kirby->auth()->limits()->track() |
Kirby\Cms\System::loginMethods() |
Kirby\Auth\Methods::enabled() via $kirby->auth()->methods()->enabled() |
Kirby\Cms\System::is2FA() |
Kirby\Auth\Methods::hasAnyRequiring2FA() via $kirby->auth()->methods()->hasAnyRequiring2FA() |
Kirby\Cms\System::is2FAWithTOTP() |
Kirby\Auth\Methods::hasAnyRequiring2FA() together with Kirby\Auth\Challenges::enabled() |
Kirby\Cms\User::changeTotp(), Kirby\Cms\UserRules::changeTotp() |
Kirby\Cms\User::changeSecret('totp', …) |
Sessions
| Deprecated | Use instead |
|---|---|
Kirby\Session\SessionData |
Kirby\Session\Data |
Kirby\Session\SessionStore |
Kirby\Session\Store |
Kirby\Session\FileSessionStore |
Kirby\Session\FileStore |
Kirby\Cms\App::sessionHandler() |
Kirby\Cms\App::sessions() |
Kirby\Session\Sessions::createManually() |
Kirby\Session\Sessions::create(['mode' => 'manual']) |
Kirby\Session\Sessions::getManually() |
Kirby\Session\Sessions::find() |
Kirby\Session\Sessions::currentDetected() |
Kirby\Session\Sessions::detect() |
Kirby\Session\Sessions::updateCache() |
Kirby\Session\Sessions::track() |
Kirby\Session\Sessions::cookieDomain() |
Kirby\Session\Sessions::cookie()->domain() |
Kirby\Session\Sessions::cookieName() |
Kirby\Session\Sessions::cookie()->name() |
Panel
Frontend
| Deprecated | Use instead |
|---|---|
<k-models-dialog>, <k-files-dialog>, <k-users-dialog> |
<k-model-picker-dialog> |
<k-pages-dialog> |
<k-page-picker-dialog> |
<k-text :html="foo" /> |
<k-text :text="$h(foo)" /> or <k-text :text="foo" /> to escape the value |
<k-box :html="true" :text="foo" /> |
<k-box :text="$h(foo)" /> |
<k-tag :html="true" :text="foo" /> |
<k-tag :text="$h(foo)" /> |
html prop of <k-tag-field-preview>, <k-tags-field-preview> and <k-models-field-preview> |
not needed: values and option texts already carry trusted HTML where appropriate |
$library.dayjs.interpret() |
$library.dayjs.parse() |
Backend
| Deprecated | Use instead |
|---|---|
Kirby\Panel\File::dropdown() |
Kirby\Panel\Controller\Dropdown\FileSettingsDropdownController |
Kirby\Panel\Page::dropdown() |
Kirby\Panel\Controller\Dropdown\PageSettingsDropdownController |
Kirby\Panel\User::dropdown() |
Kirby\Panel\Controller\Dropdown\UserSettingsDropdownController |
Kirby\Panel\Model::breadcrumb() |
Kirby\Panel\Controller\View\ModelViewController::breadcrumb() |
Kirby\Panel\Model::buttons() |
Kirby\Panel\Controller\View\ModelViewController::buttons() |
Kirby\Panel\Model::prevNext() |
Kirby\Panel\Controller\View\ModelViewController::prev() and Kirby\Panel\Controller\View\ModelViewController::next() |
Kirby\Panel\Model::props() |
Kirby\Panel\Controller\View\ModelViewController::props() |
Kirby\Panel\Model::versions() |
Kirby\Panel\Controller\View\ModelViewController::versions() |
Kirby\Panel\Model::view() |
Kirby\Panel\Controller\View\ModelViewController::load() |
Global pages/create dialog endpoint |
create dialog endpoint of a pagelist field |
โป๏ธ Refactored
Core
- Moved default field methods into new
Kirby\Content\FieldMethodstrait used byKirby\Content\Field#7082 - Implemented default validators as regular class methods of
Kirby\Toolkit\V#7608 - Use
json_validateforKirby\Toolkit\V::json()#7538 - Moved permalink logic to new
Kirby\Uuid\Permalinkclass #7545 - New
Kirby\Uuid\Uuid::from(string $uuid)method for creating an Uuid object from a UUID string.Kirby\Uuid\Uuid::for()remains to create a Uuid object for a model object. #7544 - New
Kirby\Blueprint\AcceptRulesclass andKirby\Blueprint\Blueprint::acceptRules()method for the code that checks for accepted files. This could later be extended to also check for accepted subpages. #7829 - Moved all blueprint normalization logic into a new
Kirby\Blueprint\Normalizerclass #8387 - The default site blueprint uses a
pagelistfield instead of apagessection #8405 #8449 - New
Kirby\Cms\App\Resolverclass, which handles all the logic ofKirby\Cms\App::resolve()#8277 Kirby\Cms\ModelWithContent::errors()only collects errors from fields #8449Kirby\Exception\Exception::$prefixis a class constant now #8459- Query package: switched from
privatetoprotectedmethods; fixed the types of theKirby\Query\Query::filterQuery()param and return value #8464 - New
Kirby\Reflection\Propsclass and#[Kirby\Reflection\Attributes\Prop]attribute to describe, set and export the props of a class #8457 #8615 - PHP type hints have been added to all class constants #7536
Forms
Form fields have been fully refactored as PHP classes instead of the previous array definitions #8399:
- All fields declare their props as properties with the
#[Prop]attribute instead of$propsarrays. Fields are created with named arguments, e.g.new Kirby\Form\Field\TextField(model: $page, name: 'title'). #8616 #8618 #8620 - Removed
defaultfrom field props passed to Panel #7789 - Moved
Kirby\Field\FieldOptionsclass toKirby\Form\FieldOptions - The slug field gets the 'slug' translation string as default label #7846
Field foundation classes
All fields extend Kirby\Form\Field or one of these abstract classes:
Kirby\Form\Field\DisplayFieldfor all fields without a value (e.g.headline,info,stats)Kirby\Form\Field\ValueFieldfor all fields with a valueKirby\Form\Field\InputFieldfor all fields with user inputKirby\Form\Field\DateTimeFieldfor all date and time fieldsKirby\Form\Field\OptionFieldfor fields with a single option valueKirby\Form\Field\OptionsFieldfor fields with multiple options valueKirby\Form\Field\StringFieldfor text, textarea and potentially more string value fieldsKirby\Form\Field\ProseMirrorFieldfor thelistandwriterfields #8493Kirby\Form\Field\ModelPickerFieldfor all picker fieldsKirby\Form\Field\ModelListFieldfor thefilelistandpagelistfields #8449
Field classes
Every core field type has its own class:
Kirby\Form\Field\BlocksField, Kirby\Form\Field\ButtonsField, Kirby\Form\Field\CheckboxesField, Kirby\Form\Field\ColorField, Kirby\Form\Field\DateField, Kirby\Form\Field\EmailField, Kirby\Form\Field\EntriesField, Kirby\Form\Field\FileListField, Kirby\Form\Field\FilePickerField, Kirby\Form\Field\GapField, Kirby\Form\Field\HeadlineField, Kirby\Form\Field\HiddenField, Kirby\Form\Field\InfoField, Kirby\Form\Field\LayoutField, Kirby\Form\Field\LineField, Kirby\Form\Field\LinkField, Kirby\Form\Field\ListField, Kirby\Form\Field\MultiselectField, Kirby\Form\Field\NumberField, Kirby\Form\Field\ObjectField, Kirby\Form\Field\PageListField, Kirby\Form\Field\PagePickerField, Kirby\Form\Field\PasswordField, Kirby\Form\Field\RadioField, Kirby\Form\Field\RangeField, Kirby\Form\Field\SelectField, Kirby\Form\Field\SlugField, Kirby\Form\Field\StatsField, Kirby\Form\Field\StructureField, Kirby\Form\Field\TagsField, Kirby\Form\Field\TelField, Kirby\Form\Field\TextField, Kirby\Form\Field\TextareaField, Kirby\Form\Field\TimeField, Kirby\Form\Field\ToggleField, Kirby\Form\Field\TogglesField, Kirby\Form\Field\UrlField, Kirby\Form\Field\UserPickerField and Kirby\Form\Field\WriterField
Field mixins
Shared behavior has been extracted into reusable mixins, such as:
Kirby\Form\Mixin\Autocomplete, Kirby\Form\Mixin\Batch, Kirby\Form\Mixin\Columns, Kirby\Form\Mixin\Converter, Kirby\Form\Mixin\Counter, Kirby\Form\Mixin\DefaultValue, Kirby\Form\Mixin\Disabled, Kirby\Form\Mixin\Duplicate, Kirby\Form\Mixin\Fields, Kirby\Form\Mixin\Font, Kirby\Form\Mixin\ItemLayout, Kirby\Form\Mixin\ItemSize, Kirby\Form\Mixin\Limit, Kirby\Form\Mixin\Maxlength, Kirby\Form\Mixin\Minlength, Kirby\Form\Mixin\Name, Kirby\Form\Mixin\Options, Kirby\Form\Mixin\Pattern, Kirby\Form\Mixin\Prepend, Kirby\Form\Mixin\Pretty, Kirby\Form\Mixin\Required, Kirby\Form\Mixin\Separator, Kirby\Form\Mixin\Siblings, Kirby\Form\Mixin\Sortable, Kirby\Form\Mixin\SortBy, Kirby\Form\Mixin\Spellcheck, Kirby\Form\Mixin\TableColumns, Kirby\Form\Mixin\Text, Kirby\Form\Mixin\Theme, Kirby\Form\Mixin\Type and Kirby\Form\Mixin\Upload #8457
Panel
Frontend
- Files, pages and users field previews now support IDs alongside item objects as value and will fetch the item data for these IDs automatically. #7723
- Picker fields use the new picker dialogs and fetch their item data dynamically from the new
itemsfield API endpoint <k-image-frame>can receive a file ID/UUID via newfileprop #7756- Removed the
panel.vue.compileroption. It isn't needed with Vue 3 anymore. #7788 - New
<k-panel-notifications>#7797 <k-button>applies allaria-*attributes #7801- The DOM structure of
<k-item>has changed: an additional.k-item-boxwrapper div was added #7361 - Removed
light-dark()polyfill #7902 <k-breadcrumb>has a new responsive behavior (backed by<k-collapsible>) #7901- The
filelistandpagelistfield components share a base component #8449
Backend
- Refactored the Panel namespace as non-static classes, with the new
Kirby\Panel\Areas,Kirby\Panel\Area,Kirby\Panel\AccessandKirby\Panel\Routerclasses #7383 #7386 #7391 #7394 #7406 #7407 - Refactored all Panel dialogs, drawers, dropdowns, requests and views (from
kirby/config/areas) as controller classes (Kirby\Panel\Controller) #7425 #7427 #7437 #7439 #7440 #7448 #7451 #7452 #7453 #7455 #7469 #7471 #7474 #7475 #7479 #7480 #7482- Field dialogs and drawers are dialog and drawer controllers (using a shared
Kirby\Panel\Controller\FieldControllertrait) #7454
- Field dialogs and drawers are dialog and drawer controllers (using a shared
- Aligned the namespace names within
Kirby\Panel\Ui#7459Kirby\Panel\Ui\Button\ViewButtonssupports passing an array ofKirby\Panel\Ui\Button\ViewButtonobjects #7462Kirby\Panel\Ui\Stathas an optional$modelproperty #7420
- Use
Kirby\Panel\Ui\Item\ModelItemclasses for picker dialogs #7753 - In
layout: table,Kirby\Panel\Ui\Item\ModelItemreturns the item'stextandinfoas plain, unescaped strings, because table cells render them as text rather than HTML #8439 - New
createdialog endpoint forpagelistfields #7466 #8449 - The
Kirby\Panel\Fieldclass uses the new classes and improvements above to replace its logic. #7846 - New
Kirby\Panel\Panel::assets()method #8445 - New special Panel field classes:
Kirby\Panel\Form\Field\FilePositionField,Kirby\Panel\Form\Field\PagePositionField,Kirby\Panel\Form\Field\RoleField,Kirby\Panel\Form\Field\TemplateField,Kirby\Panel\Form\Field\TitleField,Kirby\Panel\Form\Field\TranslationFieldandKirby\Panel\Form\Field\UsernameField#7846
Tests
TypeScript migration
- Migrated
this.$paneland all its modules to TypeScript #8056 #8076 #8079 #8115 - Refactored the Panel
apiJavaScript as a class in TypeScript #8075 #8121 - Migrated
preserveDataAttrsandpreserveListenersto TypeScript #8118 - Migrated the Editor to TypeScript #8101 #8102 #8105 #8106 #8107 #8108 #8110 #8111 #8112 #8114
- Migrated
$helper.writerto TypeScript #8321 panel.system.csrfandpanel.csrf.titleare always strings now (empty strings when not set) #8119
Auth
Kirby\Cms\Authclasses move into newKirby\Authnamespace:- New classes:
Kirby\Auth\Auth,Kirby\Auth\Csrf,Kirby\Auth\Limits,Kirby\Auth\Pending,Kirby\Auth\Status,Kirby\Auth\Userand theKirby\Auth\Stateenum - New auth methods:
Kirby\Auth\Methods,Kirby\Auth\Method,Kirby\Auth\Method\BasicAuthMethod,Kirby\Auth\Method\CodeMethod,Kirby\Auth\Method\PasswordMethod,Kirby\Auth\Method\PasswordResetMethodandKirby\Auth\Method\WebauthnMethod - New auth challenges:
Kirby\Auth\Challenges,Kirby\Auth\Challenge,Kirby\Auth\Challenge\EmailChallenge,Kirby\Auth\Challenge\TotpChallengeandKirby\Auth\Challenge\WebauthnChallenge - New exceptions:
Kirby\Auth\Exception\ChallengeTimeoutException,Kirby\Auth\Exception\LoginNotPermittedException,Kirby\Auth\Exception\RateLimitExceptionandKirby\Exception\UserNotFoundException
- New classes:
- Auth challenges have been changed from static classes to instance-based objects
- Panel login decomposed from two fixed forms into small composable components and a thin
LoginView.vueshell driven by the backend. - New
Kirby\Cms\User::changeSecret()/Kirby\Cms\UserRules::changeSecret()generalise the old TOTP-specific secret writing. - New Panel routes:
/login/(type)/(name), e.g./login/method/password#8045
Session
- New
Kirby\Session\Tokenclass #8228 - Removed
Kirby\Session\Session::__call()and replaced it with non-magic methods #8229 - New
Kirby\Session\CookieandKirby\Session\Headerclasses #8230 Kirby\Sessionpackage tweaks #8177- DRY-ed exceptions thrown in the
Kirby\Sessionpackage
More
- Use trait constant for
Kirby\Filesystem\IsFiledetection #8135
๐งน Housekeeping
- Upgraded CI setup #7738
- Improved testing setup
- Upgraded to Vite 8 #8037
- The Panel code is formatted with Oxfmt instead of Prettier #8592
- Panel templates can be type-checked against all core components #8593
- Panel browser support is defined in one place:
panel/.browserslistrc#8450 - Simplified PHP class docblocks #7944 and added docblocks to frontend files #8220