Upgrade to 4.4.0

This commit is contained in:
Bastian Allgeier
2024-09-12 14:43:02 +02:00
parent a955c7822e
commit 8bc7250b68
87 changed files with 637 additions and 352 deletions

View File

@@ -3,7 +3,7 @@
"description": "The Kirby core",
"license": "proprietary",
"type": "kirby-cms",
"version": "4.3.1",
"version": "4.4.0",
"keywords": [
"kirby",
"cms",
@@ -38,15 +38,15 @@
"ext-openssl": "*",
"christian-riesen/base32": "1.6.0",
"claviska/simpleimage": "4.2.0",
"composer/semver": "3.4.0",
"composer/semver": "3.4.2",
"filp/whoops": "2.15.4",
"getkirby/composer-installer": "^1.2.1",
"laminas/laminas-escaper": "2.13.0",
"michelf/php-smartypants": "1.8.1",
"phpmailer/phpmailer": "6.9.1",
"symfony/polyfill-intl-idn": "1.29.0",
"symfony/polyfill-mbstring": "1.29.0",
"symfony/yaml": "6.4.8"
"symfony/polyfill-intl-idn": "1.30.0",
"symfony/polyfill-mbstring": "1.30.0",
"symfony/yaml": "6.4.11"
},
"replace": {
"symfony/polyfill-php72": "*"

90
kirby/composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "5c5a02ed090776d3c703adfc737f316b",
"content-hash": "a49870b845c1d596a44c5af23c4dd685",
"packages": [
{
"name": "christian-riesen/base32",
@@ -120,16 +120,16 @@
},
{
"name": "composer/semver",
"version": "3.4.0",
"version": "3.4.2",
"source": {
"type": "git",
"url": "https://github.com/composer/semver.git",
"reference": "35e8d0af4486141bc745f23a29cc2091eb624a32"
"reference": "c51258e759afdb17f1fd1fe83bc12baaef6309d6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/semver/zipball/35e8d0af4486141bc745f23a29cc2091eb624a32",
"reference": "35e8d0af4486141bc745f23a29cc2091eb624a32",
"url": "https://api.github.com/repos/composer/semver/zipball/c51258e759afdb17f1fd1fe83bc12baaef6309d6",
"reference": "c51258e759afdb17f1fd1fe83bc12baaef6309d6",
"shasum": ""
},
"require": {
@@ -181,7 +181,7 @@
"support": {
"irc": "ircs://irc.libera.chat:6697/composer",
"issues": "https://github.com/composer/semver/issues",
"source": "https://github.com/composer/semver/tree/3.4.0"
"source": "https://github.com/composer/semver/tree/3.4.2"
},
"funding": [
{
@@ -197,7 +197,7 @@
"type": "tidelift"
}
],
"time": "2023-08-31T09:50:34+00:00"
"time": "2024-07-12T11:35:52+00:00"
},
{
"name": "filp/whoops",
@@ -577,16 +577,16 @@
},
{
"name": "psr/log",
"version": "3.0.0",
"version": "3.0.2",
"source": {
"type": "git",
"url": "https://github.com/php-fig/log.git",
"reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001"
"reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001",
"reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001",
"url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3",
"reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3",
"shasum": ""
},
"require": {
@@ -621,9 +621,9 @@
"psr-3"
],
"support": {
"source": "https://github.com/php-fig/log/tree/3.0.0"
"source": "https://github.com/php-fig/log/tree/3.0.2"
},
"time": "2021-07-14T16:46:02+00:00"
"time": "2024-09-11T13:17:53+00:00"
},
{
"name": "symfony/deprecation-contracts",
@@ -694,20 +694,20 @@
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.29.0",
"version": "v1.31.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4"
"reference": "a3cc8b044a6ea513310cbd48ef7333b384945638"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ef4d7e442ca910c4764bce785146269b30cb5fc4",
"reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638",
"reference": "a3cc8b044a6ea513310cbd48ef7333b384945638",
"shasum": ""
},
"require": {
"php": ">=7.1"
"php": ">=7.2"
},
"provide": {
"ext-ctype": "*"
@@ -753,7 +753,7 @@
"portable"
],
"support": {
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.29.0"
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0"
},
"funding": [
{
@@ -769,20 +769,20 @@
"type": "tidelift"
}
],
"time": "2024-01-29T20:11:03+00:00"
"time": "2024-09-09T11:45:10+00:00"
},
{
"name": "symfony/polyfill-intl-idn",
"version": "v1.29.0",
"version": "v1.30.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-idn.git",
"reference": "a287ed7475f85bf6f61890146edbc932c0fff919"
"reference": "a6e83bdeb3c84391d1dfe16f42e40727ce524a5c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/a287ed7475f85bf6f61890146edbc932c0fff919",
"reference": "a287ed7475f85bf6f61890146edbc932c0fff919",
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/a6e83bdeb3c84391d1dfe16f42e40727ce524a5c",
"reference": "a6e83bdeb3c84391d1dfe16f42e40727ce524a5c",
"shasum": ""
},
"require": {
@@ -837,7 +837,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.29.0"
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.30.0"
},
"funding": [
{
@@ -853,24 +853,24 @@
"type": "tidelift"
}
],
"time": "2024-01-29T20:11:03+00:00"
"time": "2024-05-31T15:07:36+00:00"
},
{
"name": "symfony/polyfill-intl-normalizer",
"version": "v1.29.0",
"version": "v1.31.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
"reference": "bc45c394692b948b4d383a08d7753968bed9a83d"
"reference": "3833d7255cc303546435cb650316bff708a1c75c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/bc45c394692b948b4d383a08d7753968bed9a83d",
"reference": "bc45c394692b948b4d383a08d7753968bed9a83d",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c",
"reference": "3833d7255cc303546435cb650316bff708a1c75c",
"shasum": ""
},
"require": {
"php": ">=7.1"
"php": ">=7.2"
},
"suggest": {
"ext-intl": "For best performance"
@@ -918,7 +918,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.29.0"
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0"
},
"funding": [
{
@@ -934,20 +934,20 @@
"type": "tidelift"
}
],
"time": "2024-01-29T20:11:03+00:00"
"time": "2024-09-09T11:45:10+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.29.0",
"version": "v1.30.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec"
"reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9773676c8a1bb1f8d4340a62efe641cf76eda7ec",
"reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fd22ab50000ef01661e2a31d850ebaa297f8e03c",
"reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c",
"shasum": ""
},
"require": {
@@ -998,7 +998,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.29.0"
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.30.0"
},
"funding": [
{
@@ -1014,20 +1014,20 @@
"type": "tidelift"
}
],
"time": "2024-01-29T20:11:03+00:00"
"time": "2024-06-19T12:30:46+00:00"
},
{
"name": "symfony/yaml",
"version": "v6.4.8",
"version": "v6.4.11",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
"reference": "52903de178d542850f6f341ba92995d3d63e60c9"
"reference": "be37e7f13195e05ab84ca5269365591edd240335"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/yaml/zipball/52903de178d542850f6f341ba92995d3d63e60c9",
"reference": "52903de178d542850f6f341ba92995d3d63e60c9",
"url": "https://api.github.com/repos/symfony/yaml/zipball/be37e7f13195e05ab84ca5269365591edd240335",
"reference": "be37e7f13195e05ab84ca5269365591edd240335",
"shasum": ""
},
"require": {
@@ -1070,7 +1070,7 @@
"description": "Loads and dumps YAML files",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/yaml/tree/v6.4.8"
"source": "https://github.com/symfony/yaml/tree/v6.4.11"
},
"funding": [
{
@@ -1086,7 +1086,7 @@
"type": "tidelift"
}
],
"time": "2024-05-31T14:49:08+00:00"
"time": "2024-08-12T09:55:28+00:00"
}
],
"packages-dev": [],

View File

@@ -1,7 +1,7 @@
<?php
// routing pattern to match all models with files
$filePattern = '(account/|pages/[^/]+/|site/|users/[^/]+/|)files/(:any)';
$filePattern = '(account/|pages/[^/]+/|site/|users/[^/]+/|)files/(:any)';
$parentPattern = '(account|pages/[^/]+|site|users/[^/]+)/files';
/**
@@ -47,17 +47,15 @@ return [
// move_uploaded_file() not working with unit test
// @codeCoverageIgnoreStart
return $this->upload(function ($source, $filename) use ($path) {
$props = [
// move the source file from the temp dir
return $this->parent($path)->createFile([
'content' => [
'sort' => $this->requestBody('sort')
],
'source' => $source,
'template' => $this->requestBody('template'),
'filename' => $filename
];
// move the source file from the temp dir
return $this->parent($path)->createFile($props, true);
], true);
});
// @codeCoverageIgnoreEnd
}

View File

@@ -3,12 +3,14 @@
use Kirby\Toolkit\I18n;
return function ($kirby) {
$blueprint = $kirby->site()->blueprint();
return [
'breadcrumbLabel' => function () use ($kirby) {
return $kirby->site()->title()->or(I18n::translate('view.site'))->toString();
},
'icon' => 'home',
'label' => $kirby->site()->blueprint()->title() ?? I18n::translate('view.site'),
'icon' => $blueprint->icon() ?? 'home',
'label' => $blueprint->title() ?? I18n::translate('view.site'),
'menu' => true,
'dialogs' => require __DIR__ . '/site/dialogs.php',
'drawers' => require __DIR__ . '/site/drawers.php',

View File

@@ -194,12 +194,23 @@ return [
'page.changeTitle' => [
'pattern' => 'pages/(:any)/changeTitle',
'load' => function (string $id) {
$request = App::instance()->request();
$kirby = App::instance();
$request = $kirby->request();
$page = Find::page($id);
$permissions = $page->permissions();
$select = $request->get('select', 'title');
// build the path prefix
$path = match ($kirby->multilang()) {
true => Str::after($kirby->site()->url(), $kirby->url()) . '/',
false => '/'
};
if ($parent = $page->parent()) {
$path .= $parent->uri() . '/';
}
return [
'component' => 'k-form-dialog',
'props' => [
@@ -212,7 +223,7 @@ return [
'slug' => Field::slug([
'required' => true,
'preselect' => $select === 'slug',
'path' => $page->parent() ? '/' . $page->parent()->uri() . '/' : '/',
'path' => $path,
'disabled' => $permissions->can('changeSlug') === false,
'wizard' => [
'text' => I18n::translate('page.changeSlug.fromTitle'),

View File

@@ -5,6 +5,8 @@ use Kirby\Cms\Find;
use Kirby\Toolkit\I18n;
return [
// @codeCoverageIgnoreStart
// TODO: move to controller class and add unit tests
'tree' => [
'pattern' => 'site/tree',
'action' => function () {
@@ -62,5 +64,20 @@ return [
return $pages;
}
],
'tree.parents' => [
'pattern' => 'site/tree/parents',
'action' => function () {
$kirby = App::instance();
$request = $kirby->request();
$page = $kirby->page($request->get('page'));
return [
'data' => $page->parents()->flip()->values(
fn ($parent) => $parent->uuid()?->toString() ?? $parent->id()
)
];
}
]
// @codeCoverageIgnoreEnd
];

View File

@@ -2,6 +2,7 @@
use Kirby\Toolkit\I18n;
use Kirby\Toolkit\Str;
use Kirby\Uuid\Uuids;
return [
'props' => [
@@ -75,7 +76,11 @@ return [
* @param string $store 'uuid'|'id'
*/
'store' => function (string $store = 'uuid') {
return Str::lower($store);
// fall back to ID, if UUIDs globally disabled
return match (Uuids::enabled()) {
false => 'id',
default => Str::lower($store)
};
},
/**

View File

@@ -23,7 +23,11 @@ return [
$uploads = [];
}
$uploads['accept'] = '*';
$uploads['accept'] = '*';
if ($preview = $this->image) {
$uploads['preview'] = $preview;
}
if ($template = $uploads['template'] ?? null) {
// get parent object for upload target

View File

@@ -63,7 +63,14 @@ return [
'computed' => [
'value' => function () {
$value = trim($this->value ?? '');
return Sane::sanitize($value, 'html');
$value = Sane::sanitize($value, 'html');
// convert non-breaking spaces to HTML entity
// as that's how ProseMirror handles it internally;
// will allow comparing saved and current content
$value = str_replace(' ', '&nbsp;', $value);
return $value;
}
],
'validations' => [

View File

@@ -194,6 +194,7 @@ return [
'multiple' => $multiple,
'max' => $max,
'api' => $this->parent->apiUrl(true) . '/files',
'preview' => $this->image,
'attributes' => [
// TODO: an edge issue that needs to be solved:
// if multiple users load the same section

View File

@@ -21,6 +21,14 @@ return [
$layouts = ['list', 'cardlets', 'cards', 'table'];
return in_array($layout, $layouts) ? $layout : 'list';
},
/**
* Whether the raw content file values should be used for the table column previews. Should not be used unless it eases performance issues in your setup introduced with Kirby 4.2
*
* @todo remove when Form classes have been refactored
*/
'rawvalues' => function (bool $rawvalues = false) {
return $rawvalues;
},
/**
* The size option controls the size of cards. By default cards are auto-sized and the cards grid will always fill the full width. With a size you can disable auto-sizing. Available sizes: `tiny`, `small`, `medium`, `large`, `huge`, `full`
*/
@@ -133,6 +141,24 @@ return [
$item['info'] = $model->toString($this->info);
}
// if forcing raw values, get those directly from content file
// TODO: remove once Form classes have been refactored
// @codeCoverageIgnoreStart
if ($this->rawvalues === true) {
foreach ($this->columns as $columnName => $column) {
$item[$columnName] = match (empty($column['value'])) {
// if column value defined, resolve the query
false => $model->toString($column['value']),
// otherwise use the form value,
// but don't overwrite columns
default => $item[$columnName] ?? $model->content()->get($column['id'] ?? $columnName)->value()
};
}
return $item;
}
// @codeCoverageIgnoreEnd
// Use form to get the proper values for the columns
$form = Form::for($model)->values();
@@ -142,10 +168,7 @@ return [
false => $model->toString($column['value']),
// otherwise use the form value,
// but don't overwrite columns
default =>
$item[$columnName] ??
$form[$column['id'] ?? $columnName] ??
null,
default => $item[$columnName] ?? $form[$column['id'] ?? $columnName] ?? null
};
}

View File

@@ -112,6 +112,11 @@ return [
'width'
],
'html' => function (KirbyTag $tag): string {
$kirby = $tag->kirby();
$tag->width ??= $kirby->option('kirbytext.image.width');
$tag->height ??= $kirby->option('kirbytext.image.height');
if ($tag->file = $tag->file($tag->value)) {
$tag->src = $tag->file->url();
$tag->alt ??= $tag->file->alt()->or('')->value();
@@ -129,6 +134,13 @@ return [
$tag->srcset = $tag->file->srcset($srcset);
}
if ($tag->width === 'auto') {
$tag->width = $tag->file->width();
}
if ($tag->height === 'auto') {
$tag->height = $tag->file->height();
}
} else {
$tag->src = Url::to($tag->value);
}
@@ -157,14 +169,14 @@ return [
'alt' => $tag->alt ?? ''
]);
if ($tag->kirby()->option('kirbytext.image.figure', true) === false) {
if ($kirby->option('kirbytext.image.figure', true) === false) {
return $link($image);
}
// render KirbyText in caption
if ($tag->caption) {
$options = ['markdown' => ['inline' => true]];
$caption = $tag->kirby()->kirbytext($tag->caption, $options);
$caption = $kirby->kirbytext($tag->caption, $options);
$tag->caption = [$caption];
}

View File

@@ -126,9 +126,12 @@
"error.form.notSaved": "Формата не може да бъде запазена",
"error.language.code": "Please enter a valid code for the language",
"error.language.create.permission": "You are not allowed to create a language",
"error.language.delete.permission": "You are not allowed to delete the language",
"error.language.duplicate": "The language already exists",
"error.language.name": "Please enter a valid name for the language",
"error.language.notFound": "The language could not be found",
"error.language.update.permission": "You are not allowed to update the language",
"error.layout.validation.block": "There's an error on the \"{field}\" field in block {blockIndex} using the \"{fieldset}\" block type in layout {layoutIndex}",
"error.layout.validation.settings": "There's an error in layout {index} settings",

View File

@@ -126,9 +126,12 @@
"error.form.notSaved": "No s'ha pogut desar el formulari",
"error.language.code": "Introdueix un codi vàlid per a lidioma",
"error.language.create.permission": "You are not allowed to create a language",
"error.language.delete.permission": "You are not allowed to delete the language",
"error.language.duplicate": "L'idioma ja existeix",
"error.language.name": "Introdueix un nom vàlid per a l'idioma",
"error.language.notFound": "The language could not be found",
"error.language.update.permission": "You are not allowed to update the language",
"error.layout.validation.block": "There's an error on the \"{field}\" field in block {blockIndex} using the \"{fieldset}\" block type in layout {layoutIndex}",
"error.layout.validation.settings": "There's an error in layout {index} settings",

View File

@@ -126,9 +126,12 @@
"error.form.notSaved": "Formulář nemohl být uložen",
"error.language.code": "Zadejte prosím platný kód jazyka",
"error.language.create.permission": "You are not allowed to create a language",
"error.language.delete.permission": "You are not allowed to delete the language",
"error.language.duplicate": "Jazyk již existuje",
"error.language.name": "Zadejte prosím platné jméno jazyka",
"error.language.notFound": "Jazyk nebyl nalezen",
"error.language.update.permission": "You are not allowed to update the language",
"error.layout.validation.block": "V rozvržení {layoutIndex} je v poli \"{field}\" v bloku {blockIndex} při použití \"{fieldset}\" typu chyba",
"error.layout.validation.settings": "Chyba v nastavení rozvržení {index}",

View File

@@ -126,9 +126,12 @@
"error.form.notSaved": "Formularen kunne ikke gemmes",
"error.language.code": "Indtast venligst en gyldig kode for sproget",
"error.language.create.permission": "You are not allowed to create a language",
"error.language.delete.permission": "You are not allowed to delete the language",
"error.language.duplicate": "Sproget eksisterer allerede",
"error.language.name": "Indtast venligst et gyldigt navn for sproget",
"error.language.notFound": "Sproget fandtes ikke",
"error.language.update.permission": "You are not allowed to update the language",
"error.layout.validation.block": "There's an error on the \"{field}\" field in block {blockIndex} using the \"{fieldset}\" block type in layout {layoutIndex}",
"error.layout.validation.settings": "Der er fejl i layout {index} indstillinger",

View File

@@ -126,9 +126,12 @@
"error.form.notSaved": "Das Formular konnte nicht gespeichert werden",
"error.language.code": "Bitte gib einen gültigen Code für die Sprache an",
"error.language.create.permission": "Du darfst keine Sprache anlegen",
"error.language.delete.permission": "Du darfst diese Sprache nicht löschen",
"error.language.duplicate": "Die Sprache besteht bereits",
"error.language.name": "Bitte gib einen gültigen Namen für die Sprache an",
"error.language.notFound": "Die Sprache konnte nicht gefunden werden",
"error.language.update.permission": "Du darfst diese Sprache nicht bearbeiten",
"error.layout.validation.block": "Fehler im \"{field}\" Feld in Block {blockIndex} mit dem Blocktyp \"{fieldset}\" in Layout {layoutIndex}",
"error.layout.validation.settings": "Fehler in den Einstellungen von Layout {index}",

View File

@@ -126,9 +126,12 @@
"error.form.notSaved": "Δεν ήταν δυνατή η αποθήκευση της φόρμας",
"error.language.code": "Please enter a valid code for the language",
"error.language.create.permission": "You are not allowed to create a language",
"error.language.delete.permission": "You are not allowed to delete the language",
"error.language.duplicate": "The language already exists",
"error.language.name": "Please enter a valid name for the language",
"error.language.notFound": "The language could not be found",
"error.language.update.permission": "You are not allowed to update the language",
"error.layout.validation.block": "There's an error on the \"{field}\" field in block {blockIndex} using the \"{fieldset}\" block type in layout {layoutIndex}",
"error.layout.validation.settings": "There's an error in layout {index} settings",

View File

@@ -297,6 +297,9 @@
"field.blocks.heading.name": "Heading",
"field.blocks.heading.text": "Text",
"field.blocks.heading.placeholder": "Heading …",
"field.blocks.figure.back.plain": "Plain",
"field.blocks.figure.back.pattern.light": "Pattern (light)",
"field.blocks.figure.back.pattern.dark": "Pattern (dark)",
"field.blocks.image.alt": "Alternative text",
"field.blocks.image.caption": "Caption",
"field.blocks.image.crop": "Crop",
@@ -334,6 +337,7 @@
"field.blocks.video.url.placeholder": "https://youtube.com/?v=",
"field.files.empty": "No files selected yet",
"field.files.empty.single": "No file selected yet",
"field.layout.change": "Change layout",
"field.layout.delete": "Delete layout",
@@ -345,12 +349,14 @@
"field.object.empty": "No information yet",
"field.pages.empty": "No pages selected yet",
"field.pages.empty.single": "No page selected yet",
"field.structure.delete.confirm": "Do you really want to delete this row?",
"field.structure.delete.confirm.all": "Do you really want to delete all entries?",
"field.structure.empty": "No entries yet",
"field.users.empty": "No users selected yet",
"field.users.empty.single": "No user selected yet",
"fields.empty": "No fields yet",
@@ -598,6 +604,7 @@
"save": "Save",
"search": "Search",
"searching": "Searching",
"search.min": "Enter {min} characters to search",
"search.all": "Show all {count} results",
"search.results.none": "No results",

View File

@@ -126,9 +126,12 @@
"error.form.notSaved": "Ne eblis konservi la formularon",
"error.language.code": "Bonvolu entajpi validan kodon por la lingvo",
"error.language.create.permission": "You are not allowed to create a language",
"error.language.delete.permission": "You are not allowed to delete the language",
"error.language.duplicate": "La lingvo jam ekzistas",
"error.language.name": "Bonvolu entajpi validan nomon por la lingvo",
"error.language.notFound": "La lingvo ne troveblas",
"error.language.update.permission": "You are not allowed to update the language",
"error.layout.validation.block": "There's an error on the \"{field}\" field in block {blockIndex} using the \"{fieldset}\" block type in layout {layoutIndex}",
"error.layout.validation.settings": "Estas eraro en la agordoj de blokaranĝo {index}",

View File

@@ -126,9 +126,12 @@
"error.form.notSaved": "No se pudo guardar el formulario",
"error.language.code": "Por favor introduce un código válido para el idioma",
"error.language.create.permission": "You are not allowed to create a language",
"error.language.delete.permission": "You are not allowed to delete the language",
"error.language.duplicate": "El idioma ya existe",
"error.language.name": "Por favor introduce un nombre válido para el idioma",
"error.language.notFound": "No se pudo encontrar el idioma",
"error.language.update.permission": "You are not allowed to update the language",
"error.layout.validation.block": "Hay un error en el campo \"{field}\" del bloque {blockIndex} que utiliza el tipo de bloque \"{fieldset}\" en el layout {layoutIndex}",
"error.layout.validation.settings": "Hay un error en los ajustes del layout {index}",

View File

@@ -126,9 +126,12 @@
"error.form.notSaved": "El formulario no pudo ser guardado",
"error.language.code": "Por favor, introduce un código válido para el idioma",
"error.language.create.permission": "You are not allowed to create a language",
"error.language.delete.permission": "You are not allowed to delete the language",
"error.language.duplicate": "El idioma ya existe",
"error.language.name": "Por favor, introduce un nombre válido para el idioma",
"error.language.notFound": "No se pudo encontrar el idioma",
"error.language.update.permission": "You are not allowed to update the language",
"error.layout.validation.block": "Hay un error en el campo \"{field}\" del bloque {blockIndex} que utiliza el tipo de bloque \"{fieldset}\" en el layout {layoutIndex}",
"error.layout.validation.settings": "Hay un error en los ajustes del layout {index}",

View File

@@ -126,9 +126,12 @@
"error.form.notSaved": "امکان دخیره فرم وجود ندارد",
"error.language.code": "Please enter a valid code for the language",
"error.language.create.permission": "You are not allowed to create a language",
"error.language.delete.permission": "You are not allowed to delete the language",
"error.language.duplicate": "The language already exists",
"error.language.name": "Please enter a valid name for the language",
"error.language.notFound": "The language could not be found",
"error.language.update.permission": "You are not allowed to update the language",
"error.layout.validation.block": "There's an error on the \"{field}\" field in block {blockIndex} using the \"{fieldset}\" block type in layout {layoutIndex}",
"error.layout.validation.settings": "There's an error in layout {index} settings",

View File

@@ -126,9 +126,12 @@
"error.form.notSaved": "Lomaketta ei voitu tallentaa",
"error.language.code": "Anna kielen lyhenne",
"error.language.create.permission": "You are not allowed to create a language",
"error.language.delete.permission": "You are not allowed to delete the language",
"error.language.duplicate": "Kieli on jo olemassa",
"error.language.name": "Anna kielen nimi",
"error.language.notFound": "Kieltä ei löytynyt",
"error.language.update.permission": "You are not allowed to update the language",
"error.layout.validation.block": "There's an error on the \"{field}\" field in block {blockIndex} using the \"{fieldset}\" block type in layout {layoutIndex}",
"error.layout.validation.settings": "Virhe asetelman {index} asetuksissa",

View File

@@ -125,10 +125,13 @@
"error.form.incomplete": "Veuillez corriger toutes les erreurs du formulaire…",
"error.form.notSaved": "Le formulaire na pu être enregistré",
"error.language.code": "Veuillez saisir un code correct pour cette langue",
"error.language.code": "Veuillez saisir un code correct pour la langue",
"error.language.create.permission": "Vous nêtes pas autorisé à créer une langue",
"error.language.delete.permission": "Vous nêtes pas autorisé à supprimer la langue",
"error.language.duplicate": "Cette langue existe déjà",
"error.language.name": "Veuillez saisir un nom correct pour cette langue",
"error.language.name": "Veuillez saisir un nom correct pour la langue",
"error.language.notFound": "La langue na pu être trouvée",
"error.language.update.permission": "Vous nêtes pas autorisé à modifier la langue",
"error.layout.validation.block": "Il y a une erreur sur le champ « {field} » du bloc {blockIndex} utilisant le type de bloc « {fieldset} » dans le layout {layoutIndex}.",
"error.layout.validation.settings": "Il y a une erreur dans les paramètres de la disposition {index}",
@@ -470,7 +473,7 @@
"login.email.password-reset.body": "Bonjour {user.nameOrEmail},\n\nVous avez récemment demandé un code de réinitialisation de mot de passe pour le Panel de {site}.\nLe code de réinitialisation de mot de passe suivant sera valable pendant {timeout} minutes :\n\n{code}\n\nSi vous navez pas demandé de code de réinitialisation de mot de passe, veuillez ignorer cet email ou contacter votre administrateur si vous avez des questions.\nPar sécurité, merci de ne PAS faire suivre ce courriel.",
"login.email.password-reset.subject": "Votre code de réinitialisation du mot de passe",
"login.remember": "Rester connecté",
"login.reset": "Réinitialiser le mot de passe",
"login.reset": "Réinitialiser",
"login.toggleText.code.email": "Se connecter par courriel",
"login.toggleText.code.email-password": "Se connecter avec un mot de passe",
"login.toggleText.password-reset.email": "Mot de passe oublié ?",
@@ -617,8 +620,8 @@
"stats.empty": "Aucun rapport",
"status": "Statut",
"system.info.copy": "Copy info",
"system.info.copied": "System info copied",
"system.info.copy": "Copier les informations",
"system.info.copied": "Informations système copiées",
"system.issues.content": "Le dossier content semble exposé",
"system.issues.eol.kirby": "La version de Kirby installée a atteint la fin de son cycle de vie et ne recevra plus de mises à jour de sécurité",
"system.issues.eol.plugin": "La version du plugin { plugin } installée a atteint la fin de son cycle de vie et ne recevra plus de mises à jour de sécurité",

View File

@@ -126,9 +126,12 @@
"error.form.notSaved": "Az űrlap nem menthető",
"error.language.code": "Kérlek, add meg a nyelv érvényes kódját",
"error.language.create.permission": "You are not allowed to create a language",
"error.language.delete.permission": "You are not allowed to delete the language",
"error.language.duplicate": "A nyelv már létezik",
"error.language.name": "Kérlek, add meg a nyelv érvényes nevét",
"error.language.notFound": "A nyelv nem található",
"error.language.update.permission": "You are not allowed to update the language",
"error.layout.validation.block": "There's an error on the \"{field}\" field in block {blockIndex} using the \"{fieldset}\" block type in layout {layoutIndex}",
"error.layout.validation.settings": "Hibát találtunk a(z) {index} elrendezés beállításaiban",

View File

@@ -126,9 +126,12 @@
"error.form.notSaved": "Formulir tidak dapat disimpan",
"error.language.code": "Masukkan kode bahasa yang valid",
"error.language.create.permission": "You are not allowed to create a language",
"error.language.delete.permission": "You are not allowed to delete the language",
"error.language.duplicate": "Bahasa sudah ada",
"error.language.name": "Masukkan nama bahasa yang valid",
"error.language.notFound": "Bahasa tidak ditemukan",
"error.language.update.permission": "You are not allowed to update the language",
"error.layout.validation.block": "Ada kesalahan pada bidang \"{field}\" di blok {blockIndex} menggunakan tipe blok \"{fieldset}\" di tata letak {layoutIndex}",
"error.layout.validation.settings": "Ada kesalahan di pengaturan tata letak {index}",

View File

@@ -126,9 +126,12 @@
"error.form.notSaved": "Ekki tókst að vista upplýsingar úr forminu",
"error.language.code": "Gófúslega settu inn gildan kóða fyrir tungumál",
"error.language.create.permission": "You are not allowed to create a language",
"error.language.delete.permission": "You are not allowed to delete the language",
"error.language.duplicate": "Þetta tungumál er nú þegar skráð",
"error.language.name": "Gott og gyllt nafn fyrir tungumálið",
"error.language.notFound": "Tungumálið fannst ekkert",
"error.language.update.permission": "You are not allowed to update the language",
"error.layout.validation.block": "Það er villa í {field} sviðinu í bálkinum {blockIndex} sem notar {fieldset} bálkgerðina í rammanum {layoutIndex}",
"error.layout.validation.settings": "Hér er villa í sitllingum fyrir ramman {index}",

View File

@@ -126,9 +126,12 @@
"error.form.notSaved": "Non è stato possibile salvare il form",
"error.language.code": "Inserisci un codice valido per la lingua",
"error.language.create.permission": "You are not allowed to create a language",
"error.language.delete.permission": "You are not allowed to delete the language",
"error.language.duplicate": "La lingua esiste già",
"error.language.name": "Inserisci un nome valido per la lingua",
"error.language.notFound": "La lingua non è stata trovata",
"error.language.update.permission": "You are not allowed to update the language",
"error.layout.validation.block": "C'è un errore sul campo \"{field}\" nel blocco {blockIndex} che utilizza il tipo di blocco \"{fieldset}\" nel layout {layoutIndex}",
"error.layout.validation.settings": "C'è un errore nelle impostazioni del layout {index}",

View File

@@ -126,9 +126,12 @@
"error.form.notSaved": "항목을 저장할 수 없습니다.",
"error.language.code": "올바른 언어 코드를 입력하세요.",
"error.language.create.permission": "You are not allowed to create a language",
"error.language.delete.permission": "You are not allowed to delete the language",
"error.language.duplicate": "이미 등록한 언어입니다.",
"error.language.name": "올바른 언어명을 입력하세요.",
"error.language.notFound": "언어를 찾을 수 없습니다.",
"error.language.update.permission": "You are not allowed to update the language",
"error.layout.validation.block": "레이아웃({layoutIndex})의 특정 블록 유형({fieldset})을 사용하는 블록({blockIndex})의 특정 필드({field})에 오류가 있습니다.",
"error.layout.validation.settings": "레이아웃({index}) 옵션을 확인하세요.",

View File

@@ -126,9 +126,12 @@
"error.form.notSaved": "Formos nepavyko išsaugoti",
"error.language.code": "Prašome įrašyti teisingą kalbos kodą",
"error.language.create.permission": "You are not allowed to create a language",
"error.language.delete.permission": "You are not allowed to delete the language",
"error.language.duplicate": "Tokia kalba jau yra",
"error.language.name": "Prašome įrašyti teisingą kalbos pavadinimą",
"error.language.notFound": "Nepavyko rasti šios kalbos",
"error.language.update.permission": "You are not allowed to update the language",
"error.layout.validation.block": "There's an error on the \"{field}\" field in block {blockIndex} using the \"{fieldset}\" block type in layout {layoutIndex}",
"error.layout.validation.settings": "Yra klaida išdėstymo {index} nustatymuose",

View File

@@ -126,9 +126,12 @@
"error.form.notSaved": "Skjemaet kunne ikke lagres",
"error.language.code": "Vennligst skriv inn gyldig språkkode",
"error.language.create.permission": "You are not allowed to create a language",
"error.language.delete.permission": "You are not allowed to delete the language",
"error.language.duplicate": "Språket eksisterer allerede",
"error.language.name": "Vennligst skriv inn et gyldig navn for språket",
"error.language.notFound": "Finner ikke språket",
"error.language.update.permission": "You are not allowed to update the language",
"error.layout.validation.block": "Det er en feilmelding på \"{field}\" feltet i blokk {blockIndex} med bruk av \"{fieldset}\" blokktypen i layout {layoutIndex}",
"error.layout.validation.settings": "Det er en feil i layout {index} innstillinger",

View File

@@ -126,9 +126,12 @@
"error.form.notSaved": "Het formulier kon niet worden opgeslagen",
"error.language.code": "Vul een geldige code voor deze taal in",
"error.language.create.permission": "You are not allowed to create a language",
"error.language.delete.permission": "You are not allowed to delete the language",
"error.language.duplicate": "De taal bestaat al",
"error.language.name": "Vul een geldige naam voor deze taal in",
"error.language.notFound": "De taal kan niet worden gevonden",
"error.language.update.permission": "You are not allowed to update the language",
"error.layout.validation.block": "Er is een fout opgetreden bij het \"{field}\" veld in blok {blockIndex} in het \"{fieldset}\" bloktype in layout {layoutIndex}",
"error.layout.validation.settings": "Er is een fout gevonden in de instellingen van ontwerp {index} ",
@@ -617,8 +620,8 @@
"stats.empty": "Geen rapporten",
"status": "Status",
"system.info.copy": "Copy info",
"system.info.copied": "System info copied",
"system.info.copy": "Kopieer informatie",
"system.info.copied": "Systeem informatie gekopieerd",
"system.issues.content": "De content map lijkt zichtbaar te zijn",
"system.issues.eol.kirby": "De geïnstalleerde Kirby versie is niet meer actueel en zal geen verdere beveiligingsupdates meer ontvangen.",
"system.issues.eol.plugin": "De geïnstalleerde versie van plugin { plugin } is niet meer actueel en zal geen verdere beveiligingsupdates meer ontvangen.",

View File

@@ -126,9 +126,12 @@
"error.form.notSaved": "Nie udało się zapisać formularza",
"error.language.code": "Wprowadź poprawny kod języka.",
"error.language.create.permission": "You are not allowed to create a language",
"error.language.delete.permission": "You are not allowed to delete the language",
"error.language.duplicate": "Język już istnieje.",
"error.language.name": "Wprowadź poprawną nazwę języka.",
"error.language.notFound": "Język nie został odnaleziony",
"error.language.update.permission": "You are not allowed to update the language",
"error.layout.validation.block": "Wystąpił błąd w polu „{field}” w bloku {blockIndex} o typie bloku „{fieldset}” w układzie {layoutIndex}",
"error.layout.validation.settings": "W ustawieniach układu {index} jest błąd",

View File

@@ -126,9 +126,12 @@
"error.form.notSaved": "O formulário não pôde ser salvo",
"error.language.code": "Por favor entre um código válido para o idioma",
"error.language.create.permission": "Não tem permissões para criar um idioma",
"error.language.delete.permission": "Não tem permissões para eliminar o idioma",
"error.language.duplicate": "O idioma já existe",
"error.language.name": "Por favor entre um nome válido para o idioma",
"error.language.notFound": "O idioma não foi encontrado",
"error.language.update.permission": "Não tem permissões para atualizar o idioma",
"error.layout.validation.block": "Há um erro no campo \"{field}\" no bloco {blockIndex} a usar o tipo de bloco \"{fieldset}\" no layout {layoutIndex}",
"error.layout.validation.settings": "Há um erro na configuração do layout {index}",
@@ -617,8 +620,8 @@
"stats.empty": "Nenhum relatório",
"status": "Estado",
"system.info.copy": "Copy info",
"system.info.copied": "System info copied",
"system.info.copy": "Copiar informação",
"system.info.copied": "Informação de sistema copiada",
"system.issues.content": "A pasta \"content\" parece não estar protegida",
"system.issues.eol.kirby": "A versão instalada do Kirby chegou ao fim da sua vida útil e não irá receber mais atualizações de segurança",
"system.issues.eol.plugin": "A versão instalada do plugin {plugin} chegou ao fim da sua vida útil e não irá receber mais atualizações de segurança",

View File

@@ -126,9 +126,12 @@
"error.form.notSaved": "Não foi possível guardar o formulário",
"error.language.code": "Por favor, insira um código válido para o idioma",
"error.language.create.permission": "Não tem permissões para criar um idioma",
"error.language.delete.permission": "Não tem permissões para eliminar o idioma",
"error.language.duplicate": "O idioma já existe",
"error.language.name": "Por favor, insira um nome válido para o idioma",
"error.language.notFound": "Não foi possível encontrar o idioma",
"error.language.update.permission": "Não tem permissões para atualizar o idioma",
"error.layout.validation.block": "Há um erro no campo \"{field}\" no bloco {blockIndex} a usar o tipo de bloco \"{fieldset}\" no layout {layoutIndex}",
"error.layout.validation.settings": "Há um erro na configuração do layout {index}",
@@ -617,8 +620,8 @@
"stats.empty": "Sem relatórios",
"status": "Estado",
"system.info.copy": "Copy info",
"system.info.copied": "System info copied",
"system.info.copy": "Copiar informação",
"system.info.copied": "Informação de sistema copiada",
"system.issues.content": "A pasta content parece não estar protegida",
"system.issues.eol.kirby": "A versão instalada do Kirby chegou ao fim da sua vida útil e não irá receber mais atualizações de segurança",
"system.issues.eol.plugin": "A versão instalada do plugin { plugin } chegou ao fim da sua vida útil e não irá receber mais atualizações de segurança",

View File

@@ -126,9 +126,12 @@
"error.form.notSaved": "Formularul nu a putut fi salvat",
"error.language.code": "Te rog introdu un cod valid pentru limbă",
"error.language.create.permission": "You are not allowed to create a language",
"error.language.delete.permission": "You are not allowed to delete the language",
"error.language.duplicate": "Limba există deja",
"error.language.name": "Te rog introdu un nume valid pentru limbă",
"error.language.notFound": "Limba nu a fost găsită",
"error.language.update.permission": "You are not allowed to update the language",
"error.layout.validation.block": "Există o eroare la câmpul \"{field}\" în blocul {blockIndex} care utilizează tipul de bloc \"{fieldset}\" în aranjamentul {layoutIndex}",
"error.layout.validation.settings": "Există o eroare la setările aranjamentului {index}",

View File

@@ -126,9 +126,12 @@
"error.form.notSaved": "Форма не может быть сохранена",
"error.language.code": "Пожалуйста, впишите правильный код языка",
"error.language.create.permission": "You are not allowed to create a language",
"error.language.delete.permission": "You are not allowed to delete the language",
"error.language.duplicate": "Язык уже есть",
"error.language.name": "Пожалуйста, впишите правильное название языка",
"error.language.notFound": "Не получилось найти этот язык",
"error.language.update.permission": "You are not allowed to update the language",
"error.layout.validation.block": "Ошибка в поле \"{field}\" в блоке {blockIndex} типа \"{fieldset}\" внутри разметки {layoutIndex}",
"error.layout.validation.settings": "Ошибка в настройках макета {index}",

View File

@@ -126,9 +126,12 @@
"error.form.notSaved": "Formulár sa nepodarilo uložiť",
"error.language.code": "Please enter a valid code for the language",
"error.language.create.permission": "You are not allowed to create a language",
"error.language.delete.permission": "You are not allowed to delete the language",
"error.language.duplicate": "The language already exists",
"error.language.name": "Please enter a valid name for the language",
"error.language.notFound": "The language could not be found",
"error.language.update.permission": "You are not allowed to update the language",
"error.layout.validation.block": "There's an error on the \"{field}\" field in block {blockIndex} using the \"{fieldset}\" block type in layout {layoutIndex}",
"error.layout.validation.settings": "There's an error in layout {index} settings",

View File

@@ -126,9 +126,12 @@
"error.form.notSaved": "Formuläret kunde inte sparas",
"error.language.code": "Ange en giltig kod för språket",
"error.language.create.permission": "You are not allowed to create a language",
"error.language.delete.permission": "You are not allowed to delete the language",
"error.language.duplicate": "Språket finns redan",
"error.language.name": "Ange ett giltigt namn för språket",
"error.language.notFound": "Språket hittades inte",
"error.language.update.permission": "You are not allowed to update the language",
"error.layout.validation.block": "Det finns ett fel i fältet \"{field}\" i blocket {blockIndex} med blocktypen \"{fieldset}\" i layouten {layoutIndex}",
"error.layout.validation.settings": "Det finns ett fel i inställningarna för layout {index}",

View File

@@ -126,9 +126,12 @@
"error.form.notSaved": "Form kaydedilemedi",
"error.language.code": "Lütfen dil için geçerli bir kod girin",
"error.language.create.permission": "Bir dil oluşturmanıza izin verilmiyor",
"error.language.delete.permission": "Dili silmenize izin verilmiyor",
"error.language.duplicate": "Bu dil zaten var",
"error.language.name": "Lütfen dil için geçerli bir isim girin",
"error.language.notFound": "Dil bulunamadı",
"error.language.update.permission": "Dili güncellemenize izin verilmiyor",
"error.layout.validation.block": "{layoutIndex}. sıradaki düzende \"{fieldset}\" blok türünü kullanan {blockIndex}. bloktaki \"{field}\" alanında bir hata var",
"error.layout.validation.settings": "{index}. düzen ayarlarında bir hata var",
@@ -617,8 +620,8 @@
"stats.empty": "Rapor yok",
"status": "Durum",
"system.info.copy": "Copy info",
"system.info.copied": "System info copied",
"system.info.copy": "Bilgileri kopyala",
"system.info.copied": "Sistem bilgisi kopyalandı",
"system.issues.content": "İçerik klasörü açığa çıkmış görünüyor",
"system.issues.eol.kirby": "Yüklü Kirby sürümünüz kullanım ömrünün sonuna ulaştı ve daha fazla güvenlik güncellemesi almayacak",
"system.issues.eol.plugin": "{ plugin } eklentisinin yüklü sürümü kullanım ömrünün sonuna ulaştı ve daha fazla güvenlik güncellemesi almayacak",

File diff suppressed because one or more lines are too long

View File

@@ -234,6 +234,9 @@
<symbol id="icon-globe" viewBox="0 0 24 24">
<path d="M13.0003 20.9998H18.0003V22.9998H6.00032V20.9998H11.0003V19.9505C7.70689 19.6235 4.88351 17.6986 3.31641 14.9621L5.05319 13.9696C6.43208 16.3775 9.02674 17.9998 12.0003 17.9998C16.4186 17.9998 20.0003 14.4181 20.0003 9.99983C20.0003 7.02625 18.378 4.43159 15.9701 3.0527L16.9626 1.31592C19.9724 3.03953 22.0003 6.28285 22.0003 9.99983C22.0003 15.1852 18.0536 19.4487 13.0003 19.9505V20.9998ZM12.0003 16.9998C8.13433 16.9998 5.00032 13.8658 5.00032 9.99983C5.00032 6.13384 8.13433 2.99983 12.0003 2.99983C15.8663 2.99983 19.0003 6.13384 19.0003 9.99983C19.0003 13.8658 15.8663 16.9998 12.0003 16.9998ZM12.0003 14.9998C14.7617 14.9998 17.0003 12.7613 17.0003 9.99983C17.0003 7.23841 14.7617 4.99983 12.0003 4.99983C9.2389 4.99983 7.00032 7.23841 7.00032 9.99983C7.00032 12.7613 9.2389 14.9998 12.0003 14.9998Z"/>
</symbol>
<symbol id="icon-google" viewBox="0 0 24 24">
<path d="M12 11H20.5329C20.5769 11.3847 20.6 11.7792 20.6 12.1837C20.6 14.9184 19.6204 17.2204 17.9224 18.7837C16.4367 20.1551 14.404 20.9592 11.9796 20.9592C8.46933 20.9592 5.43266 18.947 3.9551 16.0123C3.34695 14.8 3 13.4286 3 11.9796C3 10.5306 3.34695 9.1592 3.9551 7.94698C5.43266 5.01226 8.46933 3 11.9796 3C14.4 3 16.4326 3.88983 17.9877 5.33878L16.5255 6.80101C15.3682 5.68153 13.8028 5 12 5C8.13401 5 5 8.13401 5 12C5 15.866 8.13401 19 12 19C15.5265 19 18.1443 16.3923 18.577 13H12V11Z"/>
</symbol>
<symbol id="icon-grid" viewBox="0 0 24 24">
<path d="M22 12.999V20C22 20.5523 21.5523 21 21 21H13V12.999H22ZM11 12.999V21H3C2.44772 21 2 20.5523 2 20V12.999H11ZM11 3V10.999H2V4C2 3.44772 2.44772 3 3 3H11ZM21 3C21.5523 3 22 3.44772 22 4V10.999H13V3H21Z"/>
</symbol>

Before

Width:  |  Height:  |  Size: 98 KiB

After

Width:  |  Height:  |  Size: 99 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -782,7 +782,7 @@ class App
if ($input instanceof Page) {
try {
$html = $input->render();
} catch (ErrorPageException $e) {
} catch (ErrorPageException|NotFoundException $e) {
return $this->io($e);
}

View File

@@ -190,8 +190,19 @@ trait AppErrors
protected function getAdditionalWhoopsHandler(): CallbackHandler
{
return new CallbackHandler(function ($exception, $inspector, $run) {
$this->trigger('system.exception', compact('exception'));
error_log($exception);
$isLogged = true;
// allow hook to modify whether the exception should be logged
$isLogged = $this->apply(
'system.exception',
compact('exception', 'isLogged'),
'isLogged'
);
if ($isLogged !== false) {
error_log($exception);
}
return Handler::DONE;
});
}

View File

@@ -624,7 +624,7 @@ class File extends ModelWithContent
* Page URL and the filename as a more stable
* alternative for the media URLs.
*/
public function previewUrl(): string
public function previewUrl(): string|null
{
$parent = $this->parent();
$url = Url::to($this->id());
@@ -633,6 +633,12 @@ class File extends ModelWithContent
case 'page':
$preview = $parent->blueprint()->preview();
// user has no permission to preview page,
// also return null for file preview
if ($preview === false) {
return null;
}
// the page has a custom preview setting,
// thus the file is only accessible through
// the direct media URL

View File

@@ -315,7 +315,7 @@ class FileRules
public static function validMime(File $file, string $mime = null): bool
{
// make it easier to compare the mime
$mime = strtolower($mime);
$mime = strtolower($mime ?? '');
if (empty($mime)) {
throw new InvalidArgumentException([

View File

@@ -7,6 +7,7 @@ use Kirby\Exception\NotFoundException;
use Kirby\Http\Router;
use Kirby\Toolkit\A;
use Kirby\Toolkit\Str;
use Kirby\Uuid\Uuid;
/**
* The language router is used internally
@@ -84,6 +85,27 @@ class LanguageRouter
}
}
// Language-specific UUID URLs
$routes[] = [
'pattern' => '@/(page|file)/(:all)',
'method' => 'ALL',
'env' => 'site',
'action' => function (string $languageCode, string $type, string $id) use ($kirby, $language) {
// try to resolve to model, but only from UUID cache;
// this ensures that only existing UUIDs can be queried
// and attackers can't force Kirby to go through the whole
// site index with a non-existing UUID
if ($model = Uuid::for($type . '://' . $id)?->model(true)) {
return $kirby
->response()
->redirect($model->url($language->code()));
}
// render the error page
return false;
}
];
return $routes;
}

View File

@@ -3,6 +3,7 @@
namespace Kirby\Cms;
use Kirby\Filesystem\F;
use Kirby\Toolkit\Str;
class LanguageRoutes
{
@@ -29,9 +30,26 @@ class LanguageRoutes
'pattern' => $language->pattern(),
'method' => 'ALL',
'env' => 'site',
'action' => function ($path = null) use ($language) {
'action' => function ($path = null) use ($kirby, $language) {
$result = $language->router()->call($path);
// redirect secondary-language pages that have
// been accessed with non-translated slugs in their path
// to their fully translated URL
if ($path !== null && $result instanceof Page) {
if (Str::endsWith($result->url(), $path) === false) {
$url = $result->url();
$query = $kirby->request()->query()->toString();
// preserve query across redirect
if (empty($query) === false) {
$url .= '?' . $query;
}
return $kirby->response()->redirect($url);
}
}
// explicitly test for null as $result can
// contain falsy values that should still be returned
if ($result !== null) {

View File

@@ -22,7 +22,7 @@ use Throwable;
*/
class License
{
protected const HISTORY = [
public const HISTORY = [
'3' => '2019-02-05',
'4' => '2023-11-28'
];

View File

@@ -43,8 +43,16 @@ abstract class ModelPermissions
return $this->toArray();
}
public function can(string $action): bool
{
/**
* Returns whether the current user is allowed to do
* a certain action on the model
*
* @param bool $default Will be returned if $action does not exist
*/
public function can(
string $action,
bool $default = false
): bool {
$user = $this->user->id();
$role = $this->user->role()->id();
@@ -95,12 +103,20 @@ abstract class ModelPermissions
}
}
return $this->permissions->for($this->category, $action);
return $this->permissions->for($this->category, $action, $default);
}
public function cannot(string $action): bool
{
return $this->can($action) === false;
/**
* Returns whether the current user is not allowed to do
* a certain action on the model
*
* @param bool $default Will be returned if $action does not exist
*/
public function cannot(
string $action,
bool $default = true
): bool {
return $this->can($action, !$default) === false;
}
public function toArray(): array

View File

@@ -180,7 +180,7 @@ class PageBlueprint extends Blueprint
return $this->model->toString($preview);
}
return $preview;
return $this->model->permissions()->can('preview', true);
}
/**

View File

@@ -110,18 +110,21 @@ class Permissions
}
}
public function for(string $category = null, string $action = null): bool
{
public function for(
string|null $category = null,
string|null $action = null,
bool $default = false
): bool {
if ($action === null) {
if ($this->hasCategory($category) === false) {
return false;
return $default;
}
return $this->actions[$category];
}
if ($this->hasAction($category, $action) === false) {
return false;
return $default;
}
return $this->actions[$category][$action];

View File

@@ -51,6 +51,6 @@ class SiteBlueprint extends Blueprint
return $this->model->toString($preview);
}
return $preview;
return $this->model->permissions()->can('preview', true);
}
}

View File

@@ -2,6 +2,8 @@
namespace Kirby\Filesystem;
use Kirby\Cms\App;
use Kirby\Cms\Language;
use Kirby\Toolkit\Str;
/**
@@ -28,44 +30,32 @@ use Kirby\Toolkit\Str;
*/
class Filename
{
/**
* List of all applicable attributes
*/
protected array $attributes;
/**
* The sanitized file extension
*/
protected string $extension;
/**
* The source original filename
*/
protected string $filename;
/**
* The sanitized file name
*/
protected string $name;
/**
* The template for the final name
*/
protected string $template;
/**
* Creates a new Filename object
*
* @param string $template for the final name
* @param array $attributes List of all applicable attributes
*/
public function __construct(string $filename, string $template, array $attributes = [])
{
$this->filename = $filename;
$this->template = $template;
$this->attributes = $attributes;
$this->extension = $this->sanitizeExtension(
public function __construct(
protected string $filename,
protected string $template,
protected array $attributes = []
) {
$this->name = $this->sanitizeName($filename);
$this->extension = $this->sanitizeExtension(
$attributes['format'] ??
pathinfo($filename, PATHINFO_EXTENSION)
);
$this->name = $this->sanitizeName($filename);
}
/**
@@ -242,7 +232,24 @@ class Filename
*/
protected function sanitizeName(string $name): string
{
return F::safeBasename($name);
// temporarily store language rules
$rules = Str::$language;
$kirby = App::instance(null, true);
// if current user, add rules for their language to `Str` class
if ($user = $kirby?->user()) {
Str::$language = [
...Str::$language,
...Language::loadRules($user->language())];
}
// sanitize name
$name = F::safeBasename($this->filename);
// restore language rules
Str::$language = $rules;
return $name;
}
/**

View File

@@ -162,11 +162,18 @@ class Validations
*/
public static function pattern(Field|FieldClass $field, mixed $value): bool
{
if ($field->isEmpty($value) === false && $field->pattern() !== null) {
if (V::match($value, '/' . $field->pattern() . '/i') === false) {
throw new InvalidArgumentException(
V::message('match')
);
if ($field->isEmpty($value) === false) {
if ($pattern = $field->pattern()) {
// ensure that that pattern needs to match the whole
// input value from start to end, not just a partial match
// https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern#overview
$pattern = '^(?:' . $pattern . ')$';
if (V::match($value, '/' . $pattern . '/i') === false) {
throw new InvalidArgumentException(
V::message('match')
);
}
}
}

View File

@@ -602,13 +602,7 @@ class Environment
*/
protected function detectRequestUri(string|null $requestUri = null): Uri
{
// make sure the URL parser works properly when there's a
// colon in the request URI but the URI is relative
if (Url::isAbsolute($requestUri) === false) {
$requestUri = 'https://getkirby.com' . $requestUri;
}
$uri = new Uri($requestUri);
$uri = new Uri($requestUri ?? '');
// create the URI object as a combination of base uri parts
// and the parts from REQUEST_URI

View File

@@ -88,7 +88,16 @@ class Uri
public function __construct(array|string $props = [], array $inject = [])
{
if (is_string($props) === true) {
$props = parse_url($props);
// make sure the URL parser works properly when there's a
// colon in the string but the string is a relative URL
if (Url::isAbsolute($props) === false) {
$props = 'https://getkirby.com/' . $props;
$props = parse_url($props);
unset($props['scheme'], $props['host']);
} else {
$props = parse_url($props);
}
$props['username'] = $props['user'] ?? null;
$props['password'] = $props['pass'] ?? null;

View File

@@ -352,12 +352,15 @@ class File extends Model
$id = $this->model->id();
if (empty($params['model']) === false) {
$parent = $this->model->parent();
$parent = $this->model->parent();
$absolute = $parent !== $params['model'];
// if the file belongs to the current parent model,
// store only name as ID to keep its path relative to the model
$id = $parent === $params['model'] ? $name : $id;
$absolute = $parent !== $params['model'];
$id = match ($absolute) {
true => $id,
false => $name
};
}
$params['text'] ??= '{{ file.filename }}';
@@ -399,6 +402,7 @@ class File extends Model
'template' => $file->template(),
'type' => $file->type(),
'url' => $file->url(),
'uuid' => fn () => $file->uuid()?->toString(),
],
'preview' => [
'focusable' => $this->isFocusable(),

View File

@@ -335,7 +335,7 @@ abstract class Model
'link' => $this->url(true),
'sortable' => true,
'text' => $this->model->toSafeString($params['text'] ?? false),
'uuid' => $this->model->uuid()?->toString() ?? $this->model->id(),
'uuid' => $this->model->uuid()?->toString()
];
}

View File

@@ -339,6 +339,7 @@ class Page extends Model
'previewUrl' => $page->previewUrl(),
'status' => $page->status(),
'title' => $page->title()->toString(),
'uuid' => fn () => $page->uuid()?->toString(),
],
'status' => function () use ($page) {
if ($status = $page->status()) {

View File

@@ -71,6 +71,7 @@ class Site extends Model
'link' => $this->url(true),
'previewUrl' => $this->model->previewUrl(),
'title' => $this->model->title()->toString(),
'uuid' => fn () => $this->model->uuid()?->toString(),
]
]);
}

View File

@@ -237,6 +237,7 @@ class User extends Model
'name' => $user->name()->toString(),
'role' => $user->role()->title(),
'username' => $user->username(),
'uuid' => fn () => $user->uuid()?->toString()
]
]
);

View File

@@ -738,12 +738,18 @@ class A
/**
* Returns a number of random elements from an array,
* either in original or shuffled order
*
* @throws \Exception When $count is larger than array length
*/
public static function random(
array $array,
int $count = 1,
bool $shuffle = false
): array {
if ($count > count($array)) {
throw new InvalidArgumentException('$count is larger than available array items');
}
if ($shuffle === true) {
return array_slice(self::shuffle($array), 0, $count);
}

View File

@@ -12,6 +12,7 @@ use Kirby\Cms\Site;
use Kirby\Cms\User;
use Kirby\Exception\InvalidArgumentException;
use Kirby\Exception\LogicException;
use Kirby\Exception\NotFoundException;
use Kirby\Toolkit\Str;
/**
@@ -217,7 +218,13 @@ abstract class Uuid
return (static::$generator)($length);
}
if (App::instance()->option('content.uuid') === 'uuid-v4') {
$option = App::instance()->option('content.uuid');
if (is_array($option) === true) {
$option = $option['format'] ?? null;
}
if ($option === 'uuid-v4') {
return Str::uuid();
}
@@ -332,6 +339,10 @@ abstract class Uuid
}
if ($lazy === false) {
if (App::instance()->option('content.uuid.index') === false) {
throw new NotFoundException('Model for UUID ' . $this->uri->toString() . ' could not be found without searching in the site index');
}
if ($this->model = $this->findByIndex()) {
// lazily fill cache by writing to cache
// whenever looked up from index to speed

View File

@@ -1,5 +0,0 @@
@ECHO OFF
setlocal DISABLEDELAYEDEXPANSION
SET BIN_TARGET=%~dp0/yaml-lint
SET COMPOSER_RUNTIME_BIN_DIR=%~dp0
php "%BIN_TARGET%" %*

View File

@@ -148,6 +148,10 @@ return array(
'Kirby\\Cms\\UserRules' => $baseDir . '/src/Cms/UserRules.php',
'Kirby\\Cms\\Users' => $baseDir . '/src/Cms/Users.php',
'Kirby\\Cms\\Visitor' => $baseDir . '/src/Cms/Visitor.php',
'Kirby\\ComposerInstaller\\CmsInstaller' => $vendorDir . '/getkirby/composer-installer/src/ComposerInstaller/CmsInstaller.php',
'Kirby\\ComposerInstaller\\Installer' => $vendorDir . '/getkirby/composer-installer/src/ComposerInstaller/Installer.php',
'Kirby\\ComposerInstaller\\Plugin' => $vendorDir . '/getkirby/composer-installer/src/ComposerInstaller/Plugin.php',
'Kirby\\ComposerInstaller\\PluginInstaller' => $vendorDir . '/getkirby/composer-installer/src/ComposerInstaller/PluginInstaller.php',
'Kirby\\Content\\Content' => $baseDir . '/src/Content/Content.php',
'Kirby\\Content\\ContentStorage' => $baseDir . '/src/Content/ContentStorage.php',
'Kirby\\Content\\ContentStorageHandler' => $baseDir . '/src/Content/ContentStorageHandler.php',

View File

@@ -269,6 +269,10 @@ class ComposerStaticInit0bf5c8a9cfa251a218fc581ac888fe35
'Kirby\\Cms\\UserRules' => __DIR__ . '/../..' . '/src/Cms/UserRules.php',
'Kirby\\Cms\\Users' => __DIR__ . '/../..' . '/src/Cms/Users.php',
'Kirby\\Cms\\Visitor' => __DIR__ . '/../..' . '/src/Cms/Visitor.php',
'Kirby\\ComposerInstaller\\CmsInstaller' => __DIR__ . '/..' . '/getkirby/composer-installer/src/ComposerInstaller/CmsInstaller.php',
'Kirby\\ComposerInstaller\\Installer' => __DIR__ . '/..' . '/getkirby/composer-installer/src/ComposerInstaller/Installer.php',
'Kirby\\ComposerInstaller\\Plugin' => __DIR__ . '/..' . '/getkirby/composer-installer/src/ComposerInstaller/Plugin.php',
'Kirby\\ComposerInstaller\\PluginInstaller' => __DIR__ . '/..' . '/getkirby/composer-installer/src/ComposerInstaller/PluginInstaller.php',
'Kirby\\Content\\Content' => __DIR__ . '/../..' . '/src/Content/Content.php',
'Kirby\\Content\\ContentStorage' => __DIR__ . '/../..' . '/src/Content/ContentStorage.php',
'Kirby\\Content\\ContentStorageHandler' => __DIR__ . '/../..' . '/src/Content/ContentStorageHandler.php',

View File

@@ -120,17 +120,17 @@
},
{
"name": "composer/semver",
"version": "3.4.0",
"version_normalized": "3.4.0.0",
"version": "3.4.2",
"version_normalized": "3.4.2.0",
"source": {
"type": "git",
"url": "https://github.com/composer/semver.git",
"reference": "35e8d0af4486141bc745f23a29cc2091eb624a32"
"reference": "c51258e759afdb17f1fd1fe83bc12baaef6309d6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/semver/zipball/35e8d0af4486141bc745f23a29cc2091eb624a32",
"reference": "35e8d0af4486141bc745f23a29cc2091eb624a32",
"url": "https://api.github.com/repos/composer/semver/zipball/c51258e759afdb17f1fd1fe83bc12baaef6309d6",
"reference": "c51258e759afdb17f1fd1fe83bc12baaef6309d6",
"shasum": ""
},
"require": {
@@ -140,7 +140,7 @@
"phpstan/phpstan": "^1.4",
"symfony/phpunit-bridge": "^4.2 || ^5"
},
"time": "2023-08-31T09:50:34+00:00",
"time": "2024-07-12T11:35:52+00:00",
"type": "library",
"extra": {
"branch-alias": {
@@ -184,7 +184,7 @@
"support": {
"irc": "ircs://irc.libera.chat:6697/composer",
"issues": "https://github.com/composer/semver/issues",
"source": "https://github.com/composer/semver/tree/3.4.0"
"source": "https://github.com/composer/semver/tree/3.4.2"
},
"funding": [
{
@@ -598,23 +598,23 @@
},
{
"name": "psr/log",
"version": "3.0.0",
"version_normalized": "3.0.0.0",
"version": "3.0.2",
"version_normalized": "3.0.2.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/log.git",
"reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001"
"reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001",
"reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001",
"url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3",
"reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3",
"shasum": ""
},
"require": {
"php": ">=8.0.0"
},
"time": "2021-07-14T16:46:02+00:00",
"time": "2024-09-11T13:17:53+00:00",
"type": "library",
"extra": {
"branch-alias": {
@@ -645,7 +645,7 @@
"psr-3"
],
"support": {
"source": "https://github.com/php-fig/log/tree/3.0.0"
"source": "https://github.com/php-fig/log/tree/3.0.2"
},
"install-path": "../psr/log"
},
@@ -721,21 +721,21 @@
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.29.0",
"version_normalized": "1.29.0.0",
"version": "v1.31.0",
"version_normalized": "1.31.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4"
"reference": "a3cc8b044a6ea513310cbd48ef7333b384945638"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ef4d7e442ca910c4764bce785146269b30cb5fc4",
"reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638",
"reference": "a3cc8b044a6ea513310cbd48ef7333b384945638",
"shasum": ""
},
"require": {
"php": ">=7.1"
"php": ">=7.2"
},
"provide": {
"ext-ctype": "*"
@@ -743,7 +743,7 @@
"suggest": {
"ext-ctype": "For best performance"
},
"time": "2024-01-29T20:11:03+00:00",
"time": "2024-09-09T11:45:10+00:00",
"type": "library",
"extra": {
"thanks": {
@@ -783,7 +783,7 @@
"portable"
],
"support": {
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.29.0"
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0"
},
"funding": [
{
@@ -803,17 +803,17 @@
},
{
"name": "symfony/polyfill-intl-idn",
"version": "v1.29.0",
"version_normalized": "1.29.0.0",
"version": "v1.30.0",
"version_normalized": "1.30.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-idn.git",
"reference": "a287ed7475f85bf6f61890146edbc932c0fff919"
"reference": "a6e83bdeb3c84391d1dfe16f42e40727ce524a5c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/a287ed7475f85bf6f61890146edbc932c0fff919",
"reference": "a287ed7475f85bf6f61890146edbc932c0fff919",
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/a6e83bdeb3c84391d1dfe16f42e40727ce524a5c",
"reference": "a6e83bdeb3c84391d1dfe16f42e40727ce524a5c",
"shasum": ""
},
"require": {
@@ -824,7 +824,7 @@
"suggest": {
"ext-intl": "For best performance"
},
"time": "2024-01-29T20:11:03+00:00",
"time": "2024-05-31T15:07:36+00:00",
"type": "library",
"extra": {
"thanks": {
@@ -870,7 +870,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.29.0"
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.30.0"
},
"funding": [
{
@@ -890,26 +890,26 @@
},
{
"name": "symfony/polyfill-intl-normalizer",
"version": "v1.29.0",
"version_normalized": "1.29.0.0",
"version": "v1.31.0",
"version_normalized": "1.31.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
"reference": "bc45c394692b948b4d383a08d7753968bed9a83d"
"reference": "3833d7255cc303546435cb650316bff708a1c75c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/bc45c394692b948b4d383a08d7753968bed9a83d",
"reference": "bc45c394692b948b4d383a08d7753968bed9a83d",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c",
"reference": "3833d7255cc303546435cb650316bff708a1c75c",
"shasum": ""
},
"require": {
"php": ">=7.1"
"php": ">=7.2"
},
"suggest": {
"ext-intl": "For best performance"
},
"time": "2024-01-29T20:11:03+00:00",
"time": "2024-09-09T11:45:10+00:00",
"type": "library",
"extra": {
"thanks": {
@@ -954,7 +954,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.29.0"
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0"
},
"funding": [
{
@@ -974,17 +974,17 @@
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.29.0",
"version_normalized": "1.29.0.0",
"version": "v1.30.0",
"version_normalized": "1.30.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec"
"reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9773676c8a1bb1f8d4340a62efe641cf76eda7ec",
"reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fd22ab50000ef01661e2a31d850ebaa297f8e03c",
"reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c",
"shasum": ""
},
"require": {
@@ -996,7 +996,7 @@
"suggest": {
"ext-mbstring": "For best performance"
},
"time": "2024-01-29T20:11:03+00:00",
"time": "2024-06-19T12:30:46+00:00",
"type": "library",
"extra": {
"thanks": {
@@ -1037,7 +1037,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.29.0"
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.30.0"
},
"funding": [
{
@@ -1057,17 +1057,17 @@
},
{
"name": "symfony/yaml",
"version": "v6.4.8",
"version_normalized": "6.4.8.0",
"version": "v6.4.11",
"version_normalized": "6.4.11.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
"reference": "52903de178d542850f6f341ba92995d3d63e60c9"
"reference": "be37e7f13195e05ab84ca5269365591edd240335"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/yaml/zipball/52903de178d542850f6f341ba92995d3d63e60c9",
"reference": "52903de178d542850f6f341ba92995d3d63e60c9",
"url": "https://api.github.com/repos/symfony/yaml/zipball/be37e7f13195e05ab84ca5269365591edd240335",
"reference": "be37e7f13195e05ab84ca5269365591edd240335",
"shasum": ""
},
"require": {
@@ -1081,7 +1081,7 @@
"require-dev": {
"symfony/console": "^5.4|^6.0|^7.0"
},
"time": "2024-05-31T14:49:08+00:00",
"time": "2024-08-12T09:55:28+00:00",
"bin": [
"Resources/bin/yaml-lint"
],
@@ -1112,7 +1112,7 @@
"description": "Loads and dumps YAML files",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/yaml/tree/v6.4.8"
"source": "https://github.com/symfony/yaml/tree/v6.4.11"
},
"funding": [
{

View File

@@ -1,9 +1,9 @@
<?php return array(
'root' => array(
'name' => 'getkirby/cms',
'pretty_version' => '4.3.1',
'version' => '4.3.1.0',
'reference' => null,
'pretty_version' => '4.4.0',
'version' => '4.4.0.0',
'reference' => NULL,
'type' => 'kirby-cms',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
@@ -29,9 +29,9 @@
'dev_requirement' => false,
),
'composer/semver' => array(
'pretty_version' => '3.4.0',
'version' => '3.4.0.0',
'reference' => '35e8d0af4486141bc745f23a29cc2091eb624a32',
'pretty_version' => '3.4.2',
'version' => '3.4.2.0',
'reference' => 'c51258e759afdb17f1fd1fe83bc12baaef6309d6',
'type' => 'library',
'install_path' => __DIR__ . '/./semver',
'aliases' => array(),
@@ -47,9 +47,9 @@
'dev_requirement' => false,
),
'getkirby/cms' => array(
'pretty_version' => '4.3.1',
'version' => '4.3.1.0',
'reference' => null,
'pretty_version' => '4.4.0',
'version' => '4.4.0.0',
'reference' => NULL,
'type' => 'kirby-cms',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
@@ -107,9 +107,9 @@
'dev_requirement' => false,
),
'psr/log' => array(
'pretty_version' => '3.0.0',
'version' => '3.0.0.0',
'reference' => 'fe5ea303b0887d5caefd3d431c3e61ad47037001',
'pretty_version' => '3.0.2',
'version' => '3.0.2.0',
'reference' => 'f16e1d5863e37f8d8c2a01719f5b34baa2b714d3',
'type' => 'library',
'install_path' => __DIR__ . '/../psr/log',
'aliases' => array(),
@@ -125,36 +125,36 @@
'dev_requirement' => false,
),
'symfony/polyfill-ctype' => array(
'pretty_version' => 'v1.29.0',
'version' => '1.29.0.0',
'reference' => 'ef4d7e442ca910c4764bce785146269b30cb5fc4',
'pretty_version' => 'v1.31.0',
'version' => '1.31.0.0',
'reference' => 'a3cc8b044a6ea513310cbd48ef7333b384945638',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-ctype',
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/polyfill-intl-idn' => array(
'pretty_version' => 'v1.29.0',
'version' => '1.29.0.0',
'reference' => 'a287ed7475f85bf6f61890146edbc932c0fff919',
'pretty_version' => 'v1.30.0',
'version' => '1.30.0.0',
'reference' => 'a6e83bdeb3c84391d1dfe16f42e40727ce524a5c',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-intl-idn',
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/polyfill-intl-normalizer' => array(
'pretty_version' => 'v1.29.0',
'version' => '1.29.0.0',
'reference' => 'bc45c394692b948b4d383a08d7753968bed9a83d',
'pretty_version' => 'v1.31.0',
'version' => '1.31.0.0',
'reference' => '3833d7255cc303546435cb650316bff708a1c75c',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-intl-normalizer',
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/polyfill-mbstring' => array(
'pretty_version' => 'v1.29.0',
'version' => '1.29.0.0',
'reference' => '9773676c8a1bb1f8d4340a62efe641cf76eda7ec',
'pretty_version' => 'v1.30.0',
'version' => '1.30.0.0',
'reference' => 'fd22ab50000ef01661e2a31d850ebaa297f8e03c',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-mbstring',
'aliases' => array(),
@@ -167,9 +167,9 @@
),
),
'symfony/yaml' => array(
'pretty_version' => 'v6.4.8',
'version' => '6.4.8.0',
'reference' => '52903de178d542850f6f341ba92995d3d63e60c9',
'pretty_version' => 'v6.4.11',
'version' => '6.4.11.0',
'reference' => 'be37e7f13195e05ab84ca5269365591edd240335',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/yaml',
'aliases' => array(),

View File

@@ -1,11 +0,0 @@
parameters:
ignoreErrors:
-
message: "#^Parameter \\#1 \\$operator of class Composer\\\\Semver\\\\Constraint\\\\Constraint constructor expects '\\!\\='\\|'\\<'\\|'\\<\\='\\|'\\<\\>'\\|'\\='\\|'\\=\\='\\|'\\>'\\|'\\>\\=', non\\-falsy\\-string given\\.$#"
count: 1
path: src/VersionParser.php
-
message: "#^Strict comparison using \\=\\=\\= between null and non\\-empty\\-string will always evaluate to false\\.$#"
count: 2
path: src/VersionParser.php

View File

@@ -82,11 +82,16 @@ class VersionParser
* @param string $stability
*
* @return string
* @phpstan-return 'stable'|'RC'|'beta'|'alpha'|'dev'
*/
public static function normalizeStability($stability)
{
$stability = strtolower((string) $stability);
if (!in_array($stability, array('stable', 'rc', 'beta', 'alpha', 'dev'), true)) {
throw new \InvalidArgumentException('Invalid stability string "'.$stability.'", expected one of stable, RC, beta, alpha or dev');
}
return $stability === 'rc' ? 'RC' : $stability;
}

View File

@@ -9,10 +9,6 @@ interface LoggerAwareInterface
{
/**
* Sets a logger instance on the object.
*
* @param LoggerInterface $logger
*
* @return void
*/
public function setLogger(LoggerInterface $logger): void;
}

View File

@@ -9,15 +9,11 @@ trait LoggerAwareTrait
{
/**
* The logger instance.
*
* @var LoggerInterface|null
*/
protected ?LoggerInterface $logger = null;
/**
* Sets a logger.
*
* @param LoggerInterface $logger
*/
public function setLogger(LoggerInterface $logger): void
{

View File

@@ -22,10 +22,7 @@ interface LoggerInterface
/**
* System is unusable.
*
* @param string|\Stringable $message
* @param mixed[] $context
*
* @return void
*/
public function emergency(string|\Stringable $message, array $context = []): void;
@@ -35,10 +32,7 @@ interface LoggerInterface
* Example: Entire website down, database unavailable, etc. This should
* trigger the SMS alerts and wake you up.
*
* @param string|\Stringable $message
* @param mixed[] $context
*
* @return void
*/
public function alert(string|\Stringable $message, array $context = []): void;
@@ -47,10 +41,7 @@ interface LoggerInterface
*
* Example: Application component unavailable, unexpected exception.
*
* @param string|\Stringable $message
* @param mixed[] $context
*
* @return void
*/
public function critical(string|\Stringable $message, array $context = []): void;
@@ -58,10 +49,7 @@ interface LoggerInterface
* Runtime errors that do not require immediate action but should typically
* be logged and monitored.
*
* @param string|\Stringable $message
* @param mixed[] $context
*
* @return void
*/
public function error(string|\Stringable $message, array $context = []): void;
@@ -71,20 +59,14 @@ interface LoggerInterface
* Example: Use of deprecated APIs, poor use of an API, undesirable things
* that are not necessarily wrong.
*
* @param string|\Stringable $message
* @param mixed[] $context
*
* @return void
*/
public function warning(string|\Stringable $message, array $context = []): void;
/**
* Normal but significant events.
*
* @param string|\Stringable $message
* @param mixed[] $context
*
* @return void
*/
public function notice(string|\Stringable $message, array $context = []): void;
@@ -93,32 +75,23 @@ interface LoggerInterface
*
* Example: User logs in, SQL logs.
*
* @param string|\Stringable $message
* @param mixed[] $context
*
* @return void
*/
public function info(string|\Stringable $message, array $context = []): void;
/**
* Detailed debug information.
*
* @param string|\Stringable $message
* @param mixed[] $context
*
* @return void
*/
public function debug(string|\Stringable $message, array $context = []): void;
/**
* Logs with an arbitrary level.
*
* @param mixed $level
* @param string|\Stringable $message
* @param mixed $level
* @param mixed[] $context
*
* @return void
*
* @throws \Psr\Log\InvalidArgumentException
*/
public function log($level, string|\Stringable $message, array $context = []): void;

View File

@@ -14,11 +14,6 @@ trait LoggerTrait
{
/**
* System is unusable.
*
* @param string|\Stringable $message
* @param array $context
*
* @return void
*/
public function emergency(string|\Stringable $message, array $context = []): void
{
@@ -30,11 +25,6 @@ trait LoggerTrait
*
* Example: Entire website down, database unavailable, etc. This should
* trigger the SMS alerts and wake you up.
*
* @param string|\Stringable $message
* @param array $context
*
* @return void
*/
public function alert(string|\Stringable $message, array $context = []): void
{
@@ -45,11 +35,6 @@ trait LoggerTrait
* Critical conditions.
*
* Example: Application component unavailable, unexpected exception.
*
* @param string|\Stringable $message
* @param array $context
*
* @return void
*/
public function critical(string|\Stringable $message, array $context = []): void
{
@@ -59,11 +44,6 @@ trait LoggerTrait
/**
* Runtime errors that do not require immediate action but should typically
* be logged and monitored.
*
* @param string|\Stringable $message
* @param array $context
*
* @return void
*/
public function error(string|\Stringable $message, array $context = []): void
{
@@ -75,11 +55,6 @@ trait LoggerTrait
*
* Example: Use of deprecated APIs, poor use of an API, undesirable things
* that are not necessarily wrong.
*
* @param string|\Stringable $message
* @param array $context
*
* @return void
*/
public function warning(string|\Stringable $message, array $context = []): void
{
@@ -88,11 +63,6 @@ trait LoggerTrait
/**
* Normal but significant events.
*
* @param string|\Stringable $message
* @param array $context
*
* @return void
*/
public function notice(string|\Stringable $message, array $context = []): void
{
@@ -103,11 +73,6 @@ trait LoggerTrait
* Interesting events.
*
* Example: User logs in, SQL logs.
*
* @param string|\Stringable $message
* @param array $context
*
* @return void
*/
public function info(string|\Stringable $message, array $context = []): void
{
@@ -116,11 +81,6 @@ trait LoggerTrait
/**
* Detailed debug information.
*
* @param string|\Stringable $message
* @param array $context
*
* @return void
*/
public function debug(string|\Stringable $message, array $context = []): void
{
@@ -130,11 +90,7 @@ trait LoggerTrait
/**
* Logs with an arbitrary level.
*
* @param mixed $level
* @param string|\Stringable $message
* @param array $context
*
* @return void
* @param mixed $level
*
* @throws \Psr\Log\InvalidArgumentException
*/

View File

@@ -15,11 +15,7 @@ class NullLogger extends AbstractLogger
/**
* Logs with an arbitrary level.
*
* @param mixed $level
* @param string|\Stringable $message
* @param array $context
*
* @return void
* @param mixed[] $context
*
* @throws \Psr\Log\InvalidArgumentException
*/

View File

@@ -16,7 +16,7 @@
}
],
"require": {
"php": ">=7.1"
"php": ">=7.2"
},
"provide": {
"ext-ctype": "*"

View File

@@ -280,10 +280,6 @@ final class Idn
switch ($data['status']) {
case 'disallowed':
$info->errors |= self::ERROR_DISALLOWED;
// no break.
case 'valid':
$str .= mb_chr($codePoint, 'utf-8');
@@ -294,7 +290,7 @@ final class Idn
break;
case 'mapped':
$str .= $data['mapping'];
$str .= $transitional && 0x1E9E === $codePoint ? 'ss' : $data['mapping'];
break;
@@ -346,6 +342,18 @@ final class Idn
$validationOptions = $options;
if ('xn--' === substr($label, 0, 4)) {
// Step 4.1. If the label contains any non-ASCII code point (i.e., a code point greater than U+007F),
// record that there was an error, and continue with the next label.
if (preg_match('/[^\x00-\x7F]/', $label)) {
$info->errors |= self::ERROR_PUNYCODE;
continue;
}
// Step 4.2. Attempt to convert the rest of the label to Unicode according to Punycode [RFC3492]. If
// that conversion fails, record that there was an error, and continue
// with the next label. Otherwise replace the original label in the string by the results of the
// conversion.
try {
$label = self::punycodeDecode(substr($label, 4));
} catch (\Exception $e) {
@@ -516,6 +524,8 @@ final class Idn
if ('-' === substr($label, -1, 1)) {
$info->errors |= self::ERROR_TRAILING_HYPHEN;
}
} elseif ('xn--' === substr($label, 0, 4)) {
$info->errors |= self::ERROR_PUNYCODE;
}
// Step 4. The label must not contain a U+002E (.) FULL STOP.

View File

@@ -16,7 +16,7 @@
}
],
"require": {
"php": ">=7.1"
"php": ">=7.2"
},
"autoload": {
"psr-4": { "Symfony\\Polyfill\\Intl\\Normalizer\\": "" },

View File

@@ -48,6 +48,8 @@ namespace Symfony\Polyfill\Mbstring;
* - mb_strstr - Finds first occurrence of a string within another
* - mb_strwidth - Return width of string
* - mb_substr_count - Count the number of substring occurrences
* - mb_ucfirst - Make a string's first character uppercase
* - mb_lcfirst - Make a string's first character lowercase
*
* Not implemented:
* - mb_convert_kana - Convert "kana" one from another ("zen-kaku", "han-kaku" and more)
@@ -80,6 +82,21 @@ final class Mbstring
public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null)
{
if (\is_array($s)) {
if (PHP_VERSION_ID < 70200) {
trigger_error('mb_convert_encoding() expects parameter 1 to be string, array given', \E_USER_WARNING);
return null;
}
$r = [];
foreach ($s as $str) {
$r[] = self::mb_convert_encoding($str, $toEncoding, $fromEncoding);
}
return $r;
}
if (\is_array($fromEncoding) || (null !== $fromEncoding && false !== strpos($fromEncoding, ','))) {
$fromEncoding = self::mb_detect_encoding($s, $fromEncoding);
} else {
@@ -410,7 +427,7 @@ final class Mbstring
public static function mb_check_encoding($var = null, $encoding = null)
{
if (PHP_VERSION_ID < 70200 && \is_array($var)) {
if (\PHP_VERSION_ID < 70200 && \is_array($var)) {
trigger_error('mb_check_encoding() expects parameter 1 to be string, array given', \E_USER_WARNING);
return null;
@@ -437,7 +454,6 @@ final class Mbstring
}
return true;
}
public static function mb_detect_encoding($str, $encodingList = null, $strict = false)
@@ -827,7 +843,7 @@ final class Mbstring
return $code;
}
public static function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = \STR_PAD_RIGHT, string $encoding = null): string
public static function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = \STR_PAD_RIGHT, ?string $encoding = null): string
{
if (!\in_array($pad_type, [\STR_PAD_RIGHT, \STR_PAD_LEFT, \STR_PAD_BOTH], true)) {
throw new \ValueError('mb_str_pad(): Argument #4 ($pad_type) must be STR_PAD_LEFT, STR_PAD_RIGHT, or STR_PAD_BOTH');
@@ -835,17 +851,8 @@ final class Mbstring
if (null === $encoding) {
$encoding = self::mb_internal_encoding();
}
try {
$validEncoding = @self::mb_check_encoding('', $encoding);
} catch (\ValueError $e) {
throw new \ValueError(sprintf('mb_str_pad(): Argument #5 ($encoding) must be a valid encoding, "%s" given', $encoding));
}
// BC for PHP 7.3 and lower
if (!$validEncoding) {
throw new \ValueError(sprintf('mb_str_pad(): Argument #5 ($encoding) must be a valid encoding, "%s" given', $encoding));
} else {
self::assertEncoding($encoding, 'mb_str_pad(): Argument #5 ($encoding) must be a valid encoding, "%s" given');
}
if (self::mb_strlen($pad_string, $encoding) <= 0) {
@@ -871,6 +878,34 @@ final class Mbstring
}
}
public static function mb_ucfirst(string $string, ?string $encoding = null): string
{
if (null === $encoding) {
$encoding = self::mb_internal_encoding();
} else {
self::assertEncoding($encoding, 'mb_ucfirst(): Argument #2 ($encoding) must be a valid encoding, "%s" given');
}
$firstChar = mb_substr($string, 0, 1, $encoding);
$firstChar = mb_convert_case($firstChar, \MB_CASE_TITLE, $encoding);
return $firstChar.mb_substr($string, 1, null, $encoding);
}
public static function mb_lcfirst(string $string, ?string $encoding = null): string
{
if (null === $encoding) {
$encoding = self::mb_internal_encoding();
} else {
self::assertEncoding($encoding, 'mb_lcfirst(): Argument #2 ($encoding) must be a valid encoding, "%s" given');
}
$firstChar = mb_substr($string, 0, 1, $encoding);
$firstChar = mb_convert_case($firstChar, \MB_CASE_LOWER, $encoding);
return $firstChar.mb_substr($string, 1, null, $encoding);
}
private static function getSubpart($pos, $part, $haystack, $encoding)
{
if (false === $pos) {
@@ -944,4 +979,18 @@ final class Mbstring
return $encoding;
}
private static function assertEncoding(string $encoding, string $errorFormat): void
{
try {
$validEncoding = @self::mb_check_encoding('', $encoding);
} catch (\ValueError $e) {
throw new \ValueError(\sprintf($errorFormat, $encoding));
}
// BC for PHP 7.3 and lower
if (!$validEncoding) {
throw new \ValueError(\sprintf($errorFormat, $encoding));
}
}
}

View File

@@ -136,6 +136,14 @@ if (!function_exists('mb_str_pad')) {
function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = STR_PAD_RIGHT, ?string $encoding = null): string { return p\Mbstring::mb_str_pad($string, $length, $pad_string, $pad_type, $encoding); }
}
if (!function_exists('mb_ucfirst')) {
function mb_ucfirst(string $string, ?string $encoding = null): string { return p\Mbstring::mb_ucfirst($string, $encoding); }
}
if (!function_exists('mb_lcfirst')) {
function mb_lcfirst(string $string, ?string $encoding = null): string { return p\Mbstring::mb_lcfirst($string, $encoding); }
}
if (extension_loaded('mbstring')) {
return;
}

View File

@@ -132,6 +132,14 @@ if (!function_exists('mb_str_pad')) {
function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = STR_PAD_RIGHT, ?string $encoding = null): string { return p\Mbstring::mb_str_pad($string, $length, $pad_string, $pad_type, $encoding); }
}
if (!function_exists('mb_ucfirst')) {
function mb_ucfirst($string, ?string $encoding = null): string { return p\Mbstring::mb_ucfirst($string, $encoding); }
}
if (!function_exists('mb_lcfirst')) {
function mb_lcfirst($string, ?string $encoding = null): string { return p\Mbstring::mb_lcfirst($string, $encoding); }
}
if (extension_loaded('mbstring')) {
return;
}

View File

@@ -709,8 +709,13 @@ class Inline
case Parser::preg_match('/^(-|\+)?[0-9][0-9_]*(\.[0-9_]+)?$/', $scalar):
return (float) str_replace('_', '', $scalar);
case Parser::preg_match(self::getTimestampRegex(), $scalar):
// When no timezone is provided in the parsed date, YAML spec says we must assume UTC.
$time = new \DateTimeImmutable($scalar, new \DateTimeZone('UTC'));
try {
// When no timezone is provided in the parsed date, YAML spec says we must assume UTC.
$time = new \DateTimeImmutable($scalar, new \DateTimeZone('UTC'));
} catch (\Exception $e) {
// Some dates accepted by the regex are not valid dates.
throw new ParseException(\sprintf('The date "%s" could not be parsed as it is an invalid date.', $scalar), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename, $e);
}
if (Yaml::PARSE_DATETIME & $flags) {
return $time;