Upgrade to 4.1.0
This commit is contained in:
@@ -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',
|
||||
|
@@ -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;
|
||||
|
@@ -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(),
|
||||
],
|
||||
|
@@ -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']
|
||||
|
@@ -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
|
||||
]);
|
||||
|
@@ -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';
|
||||
|
@@ -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,
|
||||
|
@@ -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
|
||||
|
@@ -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,
|
||||
|
@@ -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)),
|
||||
|
@@ -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, [
|
||||
|
Reference in New Issue
Block a user