Upgrade to 4.1.0

This commit is contained in:
Bastian Allgeier
2024-01-30 16:41:06 +01:00
parent 5c44c8fcfd
commit 9345fc1a0b
59 changed files with 678 additions and 274 deletions

View File

@@ -84,9 +84,9 @@ return [
'kirby\cms\kirbytag' => 'Kirby\Text\KirbyTag',
'kirby\cms\kirbytags' => 'Kirby\Text\KirbyTags',
'kirby\cms\template' => 'Kirby\Template\Template',
'kirby\form\options' => 'Kirby\Options\Options',
'kirby\form\optionsapi' => 'Kirby\Options\OptionsApi',
'kirby\form\optionsquery' => 'Kirby\Options\OptionsQuery',
'kirby\form\options' => 'Kirby\Option\Options',
'kirby\form\optionsapi' => 'Kirby\Option\OptionsApi',
'kirby\form\optionsquery' => 'Kirby\Option\OptionsQuery',
'kirby\toolkit\dir' => 'Kirby\Filesystem\Dir',
'kirby\toolkit\f' => 'Kirby\Filesystem\F',
'kirby\toolkit\file' => 'Kirby\Filesystem\File',

View File

@@ -10,6 +10,7 @@ use Kirby\Panel\ChangesDialog;
use Kirby\Panel\Field;
use Kirby\Panel\PageCreateDialog;
use Kirby\Panel\Panel;
use Kirby\Toolkit\Escape;
use Kirby\Toolkit\I18n;
use Kirby\Toolkit\Str;
use Kirby\Uuid\Uuids;

View File

@@ -21,7 +21,7 @@ return [
'license' => [
'code' => $license->code($obfuscated),
'icon' => $status->icon(),
'info' => $status->info($license->renewal('Y-m-d')),
'info' => $status->info($license->renewal('Y-m-d', 'date')),
'theme' => $status->theme(),
'type' => $license->label(),
],

View File

@@ -1,7 +1,9 @@
<?php
use Kirby\Exception\InvalidArgumentException;
use Kirby\Field\FieldOptions;
use Kirby\Toolkit\A;
use Kirby\Toolkit\Escape;
use Kirby\Toolkit\Str;
return [
@@ -52,42 +54,87 @@ return [
return Str::lower($this->default);
},
'options' => function (): array {
return A::map(array_keys($this->options), fn ($key) => [
'value' => $this->options[$key],
'text' => is_string($key) ? $key : null
// resolve options to support manual arrays
// alongside api and query options
$props = FieldOptions::polyfill($this->props);
$options = FieldOptions::factory([
'text' => '{{ item.value }}',
'value' => '{{ item.key }}',
...$props['options']
]);
$options = $options->render($this->model());
if (empty($options) === true) {
return [];
}
$options = match (true) {
// simple array of values
// or value=text (from Options class)
is_numeric($options[0]['value']) ||
$options[0]['value'] === $options[0]['text']
=> A::map($options, fn ($option) => [
'value' => $option['text']
]),
// deprecated: name => value, flipping
// TODO: start throwing in warning in v5
$this->isColor($options[0]['text'])
=> A::map($options, fn ($option) => [
'value' => $option['text'],
// ensure that any HTML in the new text is escaped
'text' => Escape::html($option['value'])
]),
default
=> A::map($options, fn ($option) => [
'value' => $option['value'],
'text' => $option['text']
]),
};
return $options;
}
],
'methods' => [
'isColor' => function (string $value): bool {
return
$this->isHex($value) ||
$this->isRgb($value) ||
$this->isHsl($value);
},
'isHex' => function (string $value): bool {
return preg_match('/^#([\da-f]{3,4}){1,2}$/i', $value) === 1;
},
'isHsl' => function (string $value): bool {
return preg_match('/^hsla?\(\s*(\d{1,3}\.?\d*)(deg|rad|grad|turn)?(?:,|\s)+(\d{1,3})%(?:,|\s)+(\d{1,3})%(?:,|\s|\/)*(\d*(?:\.\d+)?)(%?)\s*\)?$/i', $value) === 1;
},
'isRgb' => function (string $value): bool {
return preg_match('/^rgba?\(\s*(\d{1,3})(%?)(?:,|\s)+(\d{1,3})(%?)(?:,|\s)+(\d{1,3})(%?)(?:,|\s|\/)*(\d*(?:\.\d+)?)(%?)\s*\)?$/i', $value) === 1;
},
],
'validations' => [
'color' => function ($value) {
if (empty($value) === true) {
return true;
}
if (
$this->format === 'hex' &&
preg_match('/^#([\da-f]{3,4}){1,2}$/i', $value) !== 1
) {
if ($this->format === 'hex' && $this->isHex($value) === false) {
throw new InvalidArgumentException([
'key' => 'validation.color',
'data' => ['format' => 'hex']
]);
}
if (
$this->format === 'rgb' &&
preg_match('/^rgba?\(\s*(\d{1,3})(%?)(?:,|\s)+(\d{1,3})(%?)(?:,|\s)+(\d{1,3})(%?)(?:,|\s|\/)*(\d*(?:\.\d+)?)(%?)\s*\)?$/i', $value) !== 1
) {
if ($this->format === 'rgb' && $this->isRgb($value) === false) {
throw new InvalidArgumentException([
'key' => 'validation.color',
'data' => ['format' => 'rgb']
]);
}
if (
$this->format === 'hsl' &&
preg_match('/^hsla?\(\s*(\d{1,3}\.?\d*)(deg|rad|grad|turn)?(?:,|\s)+(\d{1,3})%(?:,|\s)+(\d{1,3})%(?:,|\s|\/)*(\d*(?:\.\d+)?)(%?)\s*\)?$/i', $value) !== 1
) {
if ($this->format === 'hsl' && $this->isHsl($value) === false) {
throw new InvalidArgumentException([
'key' => 'validation.color',
'data' => ['format' => 'hsl']

View File

@@ -173,7 +173,7 @@ return [
},
'form' => function (array $values = []) {
return new Form([
'fields' => $this->attrs['fields'],
'fields' => $this->attrs['fields'] ?? [],
'values' => $values,
'model' => $this->model
]);

View File

@@ -257,7 +257,7 @@ return function (App $app) {
try {
return Structure::factory(
Data::decode($field->value, 'yaml'),
['parent' => $field->parent()]
['parent' => $field->parent(), 'field' => $field]
);
} catch (Exception) {
$message = 'Invalid structure data for "' . $field->key() . '" field';

View File

@@ -55,7 +55,7 @@ return [
'parent' => function () {
return $this->parentModel();
},
'files' => function () {
'models' => function () {
if ($this->query !== null) {
$files = $this->parent->query($this->query, Files::class) ?? new Files([]);
} else {
@@ -99,6 +99,9 @@ return [
return $files;
},
'files' => function () {
return $this->models;
},
'data' => function () {
$data = [];
@@ -106,7 +109,7 @@ return [
// a different parent model
$dragTextAbsolute = $this->model->is($this->parent) === false;
foreach ($this->files as $file) {
foreach ($this->models as $file) {
$panel = $file->panel();
$item = [
@@ -137,7 +140,7 @@ return [
return $data;
},
'total' => function () {
return $this->files->pagination()->total();
return $this->models->pagination()->total();
},
'errors' => function () {
$errors = [];
@@ -191,13 +194,14 @@ return [
'multiple' => $multiple,
'max' => $max,
'api' => $this->parent->apiUrl(true) . '/files',
'attributes' => array_filter([
'attributes' => [
// TODO: an edge issue that needs to be solved:
// if multiple users load the same section at the same time
// and upload a file, uploaded files have the same sort number
// if multiple users load the same section
// at the same time and upload a file,
// uploaded files have the same sort number
'sort' => $this->sortable === true ? $this->total + 1 : null,
'template' => $template
])
]
];
}
],
@@ -208,7 +212,7 @@ return [
'options' => [
'accept' => $this->accept,
'apiUrl' => $this->parent->apiUrl(true),
'columns' => $this->columns,
'columns' => $this->columnsWithTypes(),
'empty' => $this->empty,
'headline' => $this->headline,
'help' => $this->help,

View File

@@ -1,5 +1,6 @@
<?php
use Kirby\Cms\ModelWithContent;
use Kirby\Toolkit\I18n;
use Kirby\Toolkit\Str;
@@ -28,7 +29,7 @@ return [
],
'computed' => [
'columns' => function () {
$columns = [];
$columns = [];
if ($this->layout !== 'table') {
return [];
@@ -94,7 +95,27 @@ return [
},
],
'methods' => [
'columnsValues' => function (array $item, $model) {
'columnsWithTypes' => function () {
$columns = $this->columns;
// add the type to the columns for the table layout
if ($this->layout === 'table') {
$blueprint = $this->models->first()?->blueprint();
if ($blueprint === null) {
return $columns;
}
foreach ($columns as $columnName => $column) {
if ($id = $column['id'] ?? null) {
$columns[$columnName]['type'] ??= $blueprint->field($id)['type'] ?? null;
}
}
}
return $columns;
},
'columnsValues' => function (array $item, ModelWithContent $model) {
$item['title'] = [
// override toSafeString() coming from `$item`
// because the table cells don't use v-html

View File

@@ -82,7 +82,7 @@ return [
return $parent;
},
'pages' => function () {
'models' => function () {
if ($this->query !== null) {
$pages = $this->parent->query($this->query, Pages::class) ?? new Pages([]);
} else {
@@ -156,13 +156,16 @@ return [
return $pages;
},
'pages' => function () {
return $this->models;
},
'total' => function () {
return $this->pages->pagination()->total();
return $this->models->pagination()->total();
},
'data' => function () {
$data = [];
foreach ($this->pages as $page) {
foreach ($this->models as $page) {
$panel = $page->panel();
$permissions = $page->permissions();
@@ -284,7 +287,7 @@ return [
'errors' => $this->errors,
'options' => [
'add' => $this->add,
'columns' => $this->columns,
'columns' => $this->columnsWithTypes(),
'empty' => $this->empty,
'headline' => $this->headline,
'help' => $this->help,

View File

@@ -53,6 +53,7 @@ return [
$value = $report['value'] ?? null;
$reports[] = [
'icon' => $toString($report['icon'] ?? null),
'info' => $toString(I18n::translate($info, $info)),
'label' => $toString(I18n::translate($label, $label)),
'link' => $toString(I18n::translate($link, $link)),

View File

@@ -2,6 +2,7 @@
use Kirby\Cms\Html;
use Kirby\Cms\Url;
use Kirby\Exception\NotFoundException;
use Kirby\Text\KirbyTag;
use Kirby\Toolkit\A;
use Kirby\Toolkit\Str;
@@ -61,7 +62,7 @@ return [
],
'html' => function (KirbyTag $tag): string {
if (!$file = $tag->file($tag->value)) {
return $tag->text;
return $tag->text ?? $tag->value;
}
// use filename if the text is empty and make sure to
@@ -197,7 +198,20 @@ return [
Uuid::is($tag->value, 'page') === true ||
Uuid::is($tag->value, 'file') === true
) {
$tag->value = Uuid::for($tag->value)->model()->url();
$tag->value = Uuid::for($tag->value)->model()?->url();
}
// if url is empty, throw exception or link to the error page
if ($tag->value === null) {
if ($tag->kirby()->option('debug', false) === true) {
if (empty($tag->text) === false) {
throw new NotFoundException('The linked page cannot be found for the link text "' . $tag->text . '"');
} else {
throw new NotFoundException('The linked page cannot be found');
}
} else {
$tag->value = Url::to($tag->kirby()->site()->errorPageId());
}
}
return Html::a($tag->value, $tag->text, [