Update to Kirby 5
This commit is contained in:
parent
5d9979fca8
commit
0fefc5e2e1
472 changed files with 30853 additions and 10301 deletions
|
@ -1,5 +1,6 @@
|
|||
<?php
|
||||
|
||||
use Kirby\Cms\Helpers;
|
||||
use Kirby\Exception\InvalidArgumentException;
|
||||
use Kirby\Field\FieldOptions;
|
||||
use Kirby\Toolkit\A;
|
||||
|
@ -24,8 +25,10 @@ return [
|
|||
* The CSS format (hex, rgb, hsl) to display and store the value
|
||||
*/
|
||||
'format' => function (string $format = 'hex'): string {
|
||||
if (in_array($format, ['hex', 'hsl', 'rgb']) === false) {
|
||||
throw new InvalidArgumentException('Unsupported format for color field (supported: hex, rgb, hsl)');
|
||||
if (in_array($format, ['hex', 'hsl', 'rgb'], true) === false) {
|
||||
throw new InvalidArgumentException(
|
||||
message: 'Unsupported format for color field (supported: hex, rgb, hsl)'
|
||||
);
|
||||
}
|
||||
|
||||
return $format;
|
||||
|
@ -35,8 +38,10 @@ return [
|
|||
* show the `options` as toggles
|
||||
*/
|
||||
'mode' => function (string $mode = 'picker'): string {
|
||||
if (in_array($mode, ['picker', 'input', 'options']) === false) {
|
||||
throw new InvalidArgumentException('Unsupported mode for color field (supported: picker, input, options)');
|
||||
if (in_array($mode, ['picker', 'input', 'options'], true) === false) {
|
||||
throw new InvalidArgumentException(
|
||||
message: 'Unsupported mode for color field (supported: picker, input, options)'
|
||||
);
|
||||
}
|
||||
|
||||
return $mode;
|
||||
|
@ -69,30 +74,33 @@ return [
|
|||
return [];
|
||||
}
|
||||
|
||||
$options = match (true) {
|
||||
// simple array of values
|
||||
// or value=text (from Options class)
|
||||
if (
|
||||
is_numeric($options[0]['value']) ||
|
||||
$options[0]['value'] === $options[0]['text']
|
||||
=> A::map($options, fn ($option) => [
|
||||
'value' => $option['text']
|
||||
]),
|
||||
) {
|
||||
// simple array of values
|
||||
// or value=text (from Options class)
|
||||
$options = 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'])
|
||||
]),
|
||||
} elseif ($this->isColor($options[0]['text'])) {
|
||||
// @deprecated 4.0.0
|
||||
// TODO: Remove in Kirby 6
|
||||
|
||||
default
|
||||
=> A::map($options, fn ($option) => [
|
||||
Helpers::deprecated('Color field "' . $this->name . '": the text => value notation for options has been deprecated and will be removed in Kirby 6. Please rewrite your options as value => text.');
|
||||
|
||||
$options = A::map($options, fn ($option) => [
|
||||
'value' => $option['text'],
|
||||
// ensure that any HTML in the new text is escaped
|
||||
'text' => Escape::html($option['value'])
|
||||
]);
|
||||
} else {
|
||||
$options = A::map($options, fn ($option) => [
|
||||
'value' => $option['value'],
|
||||
'text' => $option['text']
|
||||
]),
|
||||
};
|
||||
]);
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
@ -121,24 +129,24 @@ return [
|
|||
}
|
||||
|
||||
if ($this->format === 'hex' && $this->isHex($value) === false) {
|
||||
throw new InvalidArgumentException([
|
||||
'key' => 'validation.color',
|
||||
'data' => ['format' => 'hex']
|
||||
]);
|
||||
throw new InvalidArgumentException(
|
||||
key: 'validation.color',
|
||||
data: ['format' => 'hex']
|
||||
);
|
||||
}
|
||||
|
||||
if ($this->format === 'rgb' && $this->isRgb($value) === false) {
|
||||
throw new InvalidArgumentException([
|
||||
'key' => 'validation.color',
|
||||
'data' => ['format' => 'rgb']
|
||||
]);
|
||||
throw new InvalidArgumentException(
|
||||
key: 'validation.color',
|
||||
data: ['format' => 'rgb']
|
||||
);
|
||||
}
|
||||
|
||||
if ($this->format === 'hsl' && $this->isHsl($value) === false) {
|
||||
throw new InvalidArgumentException([
|
||||
'key' => 'validation.color',
|
||||
'data' => ['format' => 'hsl']
|
||||
]);
|
||||
throw new InvalidArgumentException(
|
||||
key: 'validation.color',
|
||||
data: ['format' => 'hsl']
|
||||
);
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
@ -125,27 +125,27 @@ return [
|
|||
$format = $this->time === false ? 'd.m.Y' : 'd.m.Y H:i';
|
||||
|
||||
if ($min && $max && $value->isBetween($min, $max) === false) {
|
||||
throw new Exception([
|
||||
'key' => 'validation.date.between',
|
||||
'data' => [
|
||||
throw new Exception(
|
||||
key: 'validation.date.between',
|
||||
data: [
|
||||
'min' => $min->format($format),
|
||||
'max' => $max->format($format)
|
||||
]
|
||||
]);
|
||||
} elseif ($min && $value->isMin($min) === false) {
|
||||
throw new Exception([
|
||||
'key' => 'validation.date.after',
|
||||
'data' => [
|
||||
'date' => $min->format($format),
|
||||
]
|
||||
]);
|
||||
} elseif ($max && $value->isMax($max) === false) {
|
||||
throw new Exception([
|
||||
'key' => 'validation.date.before',
|
||||
'data' => [
|
||||
'date' => $max->format($format),
|
||||
]
|
||||
]);
|
||||
);
|
||||
}
|
||||
|
||||
if ($min && $value->isMin($min) === false) {
|
||||
throw new Exception(
|
||||
key: 'validation.date.after',
|
||||
data: ['date' => $min->format($format)]
|
||||
);
|
||||
}
|
||||
|
||||
if ($max && $value->isMax($max) === false) {
|
||||
throw new Exception(
|
||||
key: 'validation.date.before',
|
||||
data: ['date' => $max->format($format)]
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -48,7 +48,7 @@ return [
|
|||
'activeTypes' => function () {
|
||||
return array_filter(
|
||||
$this->availableTypes(),
|
||||
fn (string $type) => in_array($type, $this->props['options']),
|
||||
fn (string $type) => in_array($type, $this->props['options'], true),
|
||||
ARRAY_FILTER_USE_KEY
|
||||
);
|
||||
},
|
||||
|
@ -153,17 +153,17 @@ return [
|
|||
$detected = true;
|
||||
|
||||
if ($options['validate']($link) === false) {
|
||||
throw new InvalidArgumentException([
|
||||
'key' => 'validation.' . $type
|
||||
]);
|
||||
throw new InvalidArgumentException(
|
||||
key: 'validation.' . $type
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// none of the configured types has been detected
|
||||
if ($detected === false) {
|
||||
throw new InvalidArgumentException([
|
||||
'key' => 'validation.linkType'
|
||||
]);
|
||||
throw new InvalidArgumentException(
|
||||
key: 'validation.linkType'
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -7,8 +7,11 @@ return [
|
|||
* Available layouts: `list`, `cardlets`, `cards`
|
||||
*/
|
||||
'layout' => function (string $layout = 'list') {
|
||||
$layouts = ['list', 'cardlets', 'cards'];
|
||||
return in_array($layout, $layouts) ? $layout : 'list';
|
||||
return match ($layout) {
|
||||
'cards' => 'cards',
|
||||
'cardlets' => 'cardlets',
|
||||
default => 'list'
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -36,7 +36,7 @@ return [
|
|||
},
|
||||
'sanitizeOption' => function ($value) {
|
||||
$options = array_column($this->options(), 'value');
|
||||
return in_array($value, $options) === true ? $value : null;
|
||||
return in_array($value, $options) ? $value : null;
|
||||
},
|
||||
'sanitizeOptions' => function ($values) {
|
||||
$options = array_column($this->options(), 'value');
|
||||
|
|
|
@ -34,7 +34,9 @@ return [
|
|||
$parent = $this->uploadParent($uploads['parent'] ?? null);
|
||||
|
||||
if ($parent === null) {
|
||||
throw new InvalidArgumentException('"' . $uploads['parent'] . '" could not be resolved as a valid parent for the upload');
|
||||
throw new InvalidArgumentException(
|
||||
message: '"' . $uploads['parent'] . '" could not be resolved as a valid parent for the upload'
|
||||
);
|
||||
}
|
||||
|
||||
$file = new File([
|
||||
|
@ -52,7 +54,9 @@ return [
|
|||
'methods' => [
|
||||
'upload' => function (Api $api, $params, Closure $map) {
|
||||
if ($params === false) {
|
||||
throw new Exception('Uploads are disabled for this field');
|
||||
throw new Exception(
|
||||
message: 'Uploads are disabled for this field'
|
||||
);
|
||||
}
|
||||
|
||||
$parent = $this->uploadParent($params['parent'] ?? null);
|
||||
|
@ -68,7 +72,9 @@ return [
|
|||
$file = $parent->createFile($props, true);
|
||||
|
||||
if ($file instanceof File === false) {
|
||||
throw new Exception('The file could not be uploaded');
|
||||
throw new Exception(
|
||||
message: 'The file could not be uploaded'
|
||||
);
|
||||
}
|
||||
|
||||
return $map($file, $parent);
|
||||
|
|
|
@ -38,7 +38,7 @@ return [
|
|||
],
|
||||
'methods' => [
|
||||
'toNumber' => function ($value): float|null {
|
||||
if ($this->isEmpty($value) === true) {
|
||||
if ($this->isEmptyValue($value) === true) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -91,13 +91,13 @@ return [
|
|||
$name = array_key_first($errors);
|
||||
$error = $errors[$name];
|
||||
|
||||
throw new InvalidArgumentException([
|
||||
'key' => 'object.validation',
|
||||
'data' => [
|
||||
throw new InvalidArgumentException(
|
||||
key: 'object.validation',
|
||||
data: [
|
||||
'label' => $error['label'] ?? $name,
|
||||
'message' => implode("\n", $error['message'])
|
||||
]
|
||||
]);
|
||||
);
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
@ -20,7 +20,8 @@ return [
|
|||
],
|
||||
'computed' => [
|
||||
'default' => function () {
|
||||
return $this->sanitizeOption($this->default);
|
||||
$default = $this->model()->toString($this->default);
|
||||
return $this->sanitizeOption($default);
|
||||
},
|
||||
'value' => function () {
|
||||
return $this->sanitizeOption($this->value) ?? '';
|
||||
|
|
|
@ -18,7 +18,7 @@ return [
|
|||
return $icon;
|
||||
},
|
||||
/**
|
||||
* Custom placeholder string for empty option.
|
||||
* Text shown when no option is selected yet
|
||||
*/
|
||||
'placeholder' => function (string|array $placeholder = '—') {
|
||||
return I18n::translate($placeholder, $placeholder);
|
||||
|
|
|
@ -149,7 +149,7 @@ return [
|
|||
|
||||
// make the first column visible on mobile
|
||||
// if no other mobile columns are defined
|
||||
if (in_array(true, array_column($columns, 'mobile')) === false) {
|
||||
if (in_array(true, array_column($columns, 'mobile'), true) === false) {
|
||||
$columns[array_key_first($columns)]['mobile'] = true;
|
||||
}
|
||||
|
||||
|
@ -166,24 +166,37 @@ return [
|
|||
continue;
|
||||
}
|
||||
|
||||
$value[] = $this->form($row)->values();
|
||||
$value[] = $this->form()->fill(input: $row, passthrough: true)->toFormValues();
|
||||
}
|
||||
|
||||
return $value;
|
||||
},
|
||||
'form' => function (array $values = []) {
|
||||
return new Form([
|
||||
'fields' => $this->attrs['fields'] ?? [],
|
||||
'values' => $values,
|
||||
'model' => $this->model
|
||||
]);
|
||||
},
|
||||
'form' => function () {
|
||||
$this->form ??= new Form(
|
||||
fields: $this->attrs['fields'] ?? [],
|
||||
model: $this->model,
|
||||
language: 'current'
|
||||
);
|
||||
|
||||
return $this->form->reset();
|
||||
}
|
||||
],
|
||||
'save' => function ($value) {
|
||||
$data = [];
|
||||
$data = [];
|
||||
$form = $this->form();
|
||||
$defaults = $form->defaults();
|
||||
|
||||
foreach ($value as $row) {
|
||||
$row = $this->form($row)->content();
|
||||
foreach ($value as $index => $row) {
|
||||
$row = $form
|
||||
->reset()
|
||||
->fill(
|
||||
input: $defaults,
|
||||
)
|
||||
->submit(
|
||||
input: $row,
|
||||
passthrough: true
|
||||
)
|
||||
->toStoredValues();
|
||||
|
||||
// remove frontend helper id
|
||||
unset($row['_id']);
|
||||
|
@ -204,19 +217,20 @@ return [
|
|||
$values = A::wrap($value);
|
||||
|
||||
foreach ($values as $index => $value) {
|
||||
$form = $this->form($value);
|
||||
$form = $this->form();
|
||||
$form->fill(input: $value);
|
||||
|
||||
foreach ($form->fields() as $field) {
|
||||
$errors = $field->errors();
|
||||
|
||||
if (empty($errors) === false) {
|
||||
throw new InvalidArgumentException([
|
||||
'key' => 'structure.validation',
|
||||
'data' => [
|
||||
throw new InvalidArgumentException(
|
||||
key: 'structure.validation',
|
||||
data: [
|
||||
'field' => $field->label() ?? Str::ucfirst($field->name()),
|
||||
'index' => $index + 1
|
||||
]
|
||||
]);
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,11 +10,14 @@ return [
|
|||
* The field value will be converted with the selected converter before the value gets saved. Available converters: `lower`, `upper`, `ucfirst`, `slug`
|
||||
*/
|
||||
'converter' => function ($value = null) {
|
||||
if ($value !== null && array_key_exists($value, $this->converters()) === false) {
|
||||
throw new InvalidArgumentException([
|
||||
'key' => 'field.converter.invalid',
|
||||
'data' => ['converter' => $value]
|
||||
]);
|
||||
if (
|
||||
$value !== null &&
|
||||
array_key_exists($value, $this->converters()) === false
|
||||
) {
|
||||
throw new InvalidArgumentException(
|
||||
key: 'field.converter.invalid',
|
||||
data: ['converter' => $value]
|
||||
);
|
||||
}
|
||||
|
||||
return $value;
|
||||
|
|
|
@ -89,12 +89,11 @@ return [
|
|||
[
|
||||
'pattern' => 'files',
|
||||
'action' => function () {
|
||||
$params = array_merge($this->field()->files(), [
|
||||
return $this->field()->filepicker([
|
||||
...$this->field()->files(),
|
||||
'page' => $this->requestQuery('page'),
|
||||
'search' => $this->requestQuery('search')
|
||||
]);
|
||||
|
||||
return $this->field()->filepicker($params);
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -104,14 +103,12 @@ return [
|
|||
$field = $this->field();
|
||||
$uploads = $field->uploads();
|
||||
|
||||
return $this->field()->upload($this, $uploads, function ($file, $parent) use ($field) {
|
||||
$absolute = $field->model()->is($parent) === false;
|
||||
|
||||
return [
|
||||
'filename' => $file->filename(),
|
||||
'dragText' => $file->panel()->dragText('auto', $absolute),
|
||||
];
|
||||
});
|
||||
return $this->field()->upload($this, $uploads, fn ($file, $parent) => [
|
||||
'filename' => $file->filename(),
|
||||
'dragText' => $file->panel()->dragText(
|
||||
absolute: $field->model()->is($parent) === false
|
||||
),
|
||||
]);
|
||||
}
|
||||
]
|
||||
];
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
use Kirby\Exception\Exception;
|
||||
use Kirby\Exception\InvalidArgumentException;
|
||||
use Kirby\Toolkit\Date;
|
||||
use Kirby\Toolkit\I18n;
|
||||
|
||||
|
@ -97,27 +97,27 @@ return [
|
|||
$format = 'H:i:s';
|
||||
|
||||
if ($min && $max && $value->isBetween($min, $max) === false) {
|
||||
throw new Exception([
|
||||
'key' => 'validation.time.between',
|
||||
'data' => [
|
||||
throw new InvalidArgumentException(
|
||||
key: 'validation.time.between',
|
||||
data: [
|
||||
'min' => $min->format($format),
|
||||
'max' => $min->format($format)
|
||||
]
|
||||
]);
|
||||
} elseif ($min && $value->isMin($min) === false) {
|
||||
throw new Exception([
|
||||
'key' => 'validation.time.after',
|
||||
'data' => [
|
||||
'time' => $min->format($format),
|
||||
]
|
||||
]);
|
||||
} elseif ($max && $value->isMax($max) === false) {
|
||||
throw new Exception([
|
||||
'key' => 'validation.time.before',
|
||||
'data' => [
|
||||
'time' => $max->format($format),
|
||||
]
|
||||
]);
|
||||
);
|
||||
}
|
||||
|
||||
if ($min && $value->isMin($min) === false) {
|
||||
throw new InvalidArgumentException(
|
||||
key: 'validation.time.after',
|
||||
data: ['time' => $min->format($format)]
|
||||
);
|
||||
}
|
||||
|
||||
if ($max && $value->isMax($max) === false) {
|
||||
throw new InvalidArgumentException(
|
||||
key: 'validation.time.before',
|
||||
data: ['time' => $max->format($format)]
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -65,8 +65,13 @@ return [
|
|||
'validations' => [
|
||||
'boolean',
|
||||
'required' => function ($value) {
|
||||
if ($this->isRequired() && ($value === false || $this->isEmpty($value))) {
|
||||
throw new InvalidArgumentException(I18n::translate('field.required'));
|
||||
if (
|
||||
$this->isRequired() &&
|
||||
($value === false || $this->isEmptyValue($value))
|
||||
) {
|
||||
throw new InvalidArgumentException(
|
||||
message: I18n::translate('field.required')
|
||||
);
|
||||
}
|
||||
},
|
||||
]
|
||||
|
|
|
@ -79,10 +79,10 @@ return [
|
|||
$this->minlength &&
|
||||
V::minLength(strip_tags($value), $this->minlength) === false
|
||||
) {
|
||||
throw new InvalidArgumentException([
|
||||
'key' => 'validation.minlength',
|
||||
'data' => ['min' => $this->minlength]
|
||||
]);
|
||||
throw new InvalidArgumentException(
|
||||
key: 'validation.minlength',
|
||||
data: ['min' => $this->minlength]
|
||||
);
|
||||
}
|
||||
},
|
||||
'maxlength' => function ($value) {
|
||||
|
@ -90,10 +90,10 @@ return [
|
|||
$this->maxlength &&
|
||||
V::maxLength(strip_tags($value), $this->maxlength) === false
|
||||
) {
|
||||
throw new InvalidArgumentException([
|
||||
'key' => 'validation.maxlength',
|
||||
'data' => ['max' => $this->maxlength]
|
||||
]);
|
||||
throw new InvalidArgumentException(
|
||||
key: 'validation.maxlength',
|
||||
data: ['max' => $this->maxlength]
|
||||
);
|
||||
}
|
||||
},
|
||||
]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue