Upgrade to 3.6.0

This commit is contained in:
Bastian Allgeier
2021-11-16 14:53:37 +01:00
parent 7388fa4d24
commit 92b7a330fa
318 changed files with 20017 additions and 6878 deletions

View File

@@ -238,7 +238,7 @@ class Field extends Component
'help' => function () {
/** @var \Kirby\Form\Field $this */
if ($this->help) {
$help = $this->model()->toString($this->help);
$help = $this->model()->toSafeString($this->help);
$help = $this->kirby()->kirbytext($help);
return $help;
}
@@ -441,7 +441,7 @@ class Field extends Component
ksort($array);
return array_filter($array, function ($item) {
return $item !== null;
return $item !== null && is_object($item) === false;
});
}

View File

@@ -5,10 +5,10 @@ namespace Kirby\Form\Field;
use Kirby\Cms\Block;
use Kirby\Cms\Blocks as BlocksCollection;
use Kirby\Cms\Fieldsets;
use Kirby\Cms\Form;
use Kirby\Exception\InvalidArgumentException;
use Kirby\Exception\NotFoundException;
use Kirby\Form\FieldClass;
use Kirby\Form\Form;
use Kirby\Form\Mixin\EmptyState;
use Kirby\Form\Mixin\Max;
use Kirby\Form\Mixin\Min;
@@ -146,6 +146,15 @@ class BlocksField extends FieldClass
return ['uuid' => uuid()];
}
],
[
'pattern' => 'paste',
'method' => 'POST',
'action' => function () use ($field) {
$value = BlocksCollection::parse(get('html'));
$blocks = BlocksCollection::factory($value);
return $field->blocksToValues($blocks->toArray());
}
],
[
'pattern' => 'fieldsets/(:any)',
'method' => 'GET',

View File

@@ -4,10 +4,10 @@ namespace Kirby\Form\Field;
use Kirby\Cms\Blueprint;
use Kirby\Cms\Fieldset;
use Kirby\Cms\Form;
use Kirby\Cms\Layout;
use Kirby\Cms\Layouts;
use Kirby\Exception\InvalidArgumentException;
use Kirby\Form\Form;
use Kirby\Toolkit\Str;
use Throwable;

View File

@@ -10,32 +10,116 @@ use Kirby\Toolkit\I18n;
use Kirby\Toolkit\Str;
use Throwable;
/**
* Abstract field class to be used instead
* of functional field components for more
* control.
*
* @package Kirby Form
* @author Bastian Allgeier <bastian@getkirby.com>
* @link https://getkirby.com
* @copyright Bastian Allgeier GmbH
* @license https://getkirby.com/license
*/
abstract class FieldClass
{
use HasSiblings;
/**
* @var string|null
*/
protected $after;
/**
* @var bool
*/
protected $autofocus;
/**
* @var string|null
*/
protected $before;
/**
* @var mixed
*/
protected $default;
/**
* @var bool
*/
protected $disabled;
/**
* @var string|null
*/
protected $help;
/**
* @var string|null
*/
protected $icon;
/**
* @var string|null
*/
protected $label;
/**
* @var \Kirby\Cms\ModelWithContent
*/
protected $model;
/**
* @var string
*/
protected $name;
/**
* @var array
*/
protected $params;
/**
* @var string|null
*/
protected $placeholder;
/**
* @var bool
*/
protected $required;
/**
* @var \Kirby\Form\Fields
*/
protected $siblings;
/**
* @var bool
*/
protected $translate;
/**
* @var mixed
*/
protected $value;
/**
* @var array|null
*/
protected $when;
/**
* @var string|null
*/
protected $width;
/**
* @param string $param
* @param array $args
* @return mixed
*/
public function __call(string $param, array $args)
{
if (isset($this->$param) === true) {
@@ -45,6 +129,9 @@ abstract class FieldClass
return $this->params[$param] ?? null;
}
/**
* @param array $params
*/
public function __construct(array $params = [])
{
$this->params = $params;
@@ -71,28 +158,41 @@ abstract class FieldClass
}
}
/**
* @return string|null
*/
public function after(): ?string
{
return $this->stringTemplate($this->after);
}
/**
* @return array
*/
public function api(): array
{
return $this->routes();
}
/**
* @return bool
*/
public function autofocus(): bool
{
return $this->autofocus;
}
/**
* @return string|null
*/
public function before(): ?string
{
return $this->stringTemplate($this->before);
}
/**
* @deprecated
* @deprecated 3.5.0
* @todo remove when the general field class setup has been refactored
*
* Returns the field data
* in a format to be stored
@@ -109,13 +209,11 @@ abstract class FieldClass
/**
* Returns the default value for the field,
* which will be used when a page/file/user is created
*
* @return mixed
*/
public function default()
{
if ($this->default === null) {
return;
}
if (is_string($this->default) === false) {
return $this->default;
}
@@ -125,89 +223,14 @@ abstract class FieldClass
/**
* If `true`, the field is no longer editable and will not be saved
*
* @return bool
*/
public function disabled(): bool
{
return $this->disabled;
}
/**
* Optional help text below the field
*/
public function help(): ?string
{
if (empty($this->help) === false) {
$help = $this->stringTemplate($this->help);
$help = $this->kirby()->kirbytext($help);
return $help;
}
return null;
}
protected function i18n($param)
{
return empty($param) === false ? I18n::translate($param, $param) : null;
}
/**
* Optional icon that will be shown at the end of the field
*/
public function icon(): ?string
{
return $this->icon;
}
public function id(): string
{
return $this->name();
}
public function isDisabled(): bool
{
return $this->disabled;
}
public function isEmpty(): bool
{
return $this->isEmptyValue($this->value());
}
public function isEmptyValue($value): bool
{
return in_array($value, [null, '', []], true);
}
/**
* Checks if the field is invalid
*
* @return bool
*/
public function isInvalid(): bool
{
return $this->isValid() === false;
}
public function isRequired(): bool
{
return $this->required;
}
public function isSaveable(): bool
{
return true;
}
/**
* Checks if the field is valid
*
* @return bool
*/
public function isValid(): bool
{
return empty($this->errors()) === true;
}
/**
* Runs all validations and returns an array of
* error messages
@@ -230,6 +253,110 @@ abstract class FieldClass
$this->value = $value;
}
/**
* Optional help text below the field
*
* @return string|null
*/
public function help(): ?string
{
if (empty($this->help) === false) {
$help = $this->stringTemplate($this->help);
$help = $this->kirby()->kirbytext($help);
return $help;
}
return null;
}
/**
* @param string|array|null $param
* @return string|null
*/
protected function i18n($param = null): ?string
{
return empty($param) === false ? I18n::translate($param, $param) : null;
}
/**
* Optional icon that will be shown at the end of the field
*
* @return string|null
*/
public function icon(): ?string
{
return $this->icon;
}
/**
* @return string
*/
public function id(): string
{
return $this->name();
}
/**
* @return bool
*/
public function isDisabled(): bool
{
return $this->disabled;
}
/**
* @return bool
*/
public function isEmpty(): bool
{
return $this->isEmptyValue($this->value());
}
/**
* @param mixed $value
* @return bool
*/
public function isEmptyValue($value = null): bool
{
return in_array($value, [null, '', []], true);
}
/**
* Checks if the field is invalid
*
* @return bool
*/
public function isInvalid(): bool
{
return $this->isValid() === false;
}
/**
* @return bool
*/
public function isRequired(): bool
{
return $this->required;
}
/**
* @return bool
*/
public function isSaveable(): bool
{
return true;
}
/**
* Checks if the field is valid
*
* @return bool
*/
public function isValid(): bool
{
return empty($this->errors()) === true;
}
/**
* Returns the Kirby instance
*
@@ -242,6 +369,8 @@ abstract class FieldClass
/**
* The field label can be set as string or associative array with translations
*
* @return string
*/
public function label(): string
{
@@ -251,7 +380,7 @@ abstract class FieldClass
/**
* Returns the parent model
*
* @return mixed|null
* @return mixed
*/
public function model()
{
@@ -324,6 +453,8 @@ abstract class FieldClass
/**
* Optional placeholder value that will be shown when the field is empty
*
* @return string|null
*/
public function placeholder(): ?string
{
@@ -379,8 +510,8 @@ abstract class FieldClass
}
/**
* @deprecated
*
* @deprecated 3.5.0
* @todo remove when the general field class setup has been refactored
* @return bool
*/
public function save()
@@ -388,91 +519,170 @@ abstract class FieldClass
return $this->isSaveable();
}
/**
* @param array|string|null $after
* @return void
*/
protected function setAfter($after = null)
{
$this->after = $this->i18n($after);
}
/**
* @param bool $autofocus
* @return void
*/
protected function setAutofocus(bool $autofocus = false)
{
$this->autofocus = $autofocus;
}
/**
* @param array|string|null $before
* @return void
*/
protected function setBefore($before = null)
{
$this->before = $this->i18n($before);
}
/**
* @param mixed $default
* @return void
*/
protected function setDefault($default = null)
{
$this->default = $default;
}
/**
* @param bool $disabled
* @return void
*/
protected function setDisabled(bool $disabled = false)
{
$this->disabled = $disabled;
}
/**
* @param array|string|null $help
* @return void
*/
protected function setHelp($help = null)
{
$this->help = $this->i18n($help);
}
protected function setIcon(string $icon = null)
/**
* @param string|null $icon
* @return void
*/
protected function setIcon(?string $icon = null)
{
$this->icon = $icon;
}
/**
* @param array|string|null $label
* @return void
*/
protected function setLabel($label = null)
{
$this->label = $this->i18n($label);
}
/**
* @param \Kirby\Cms\ModelWithContent $model
* @return void
*/
protected function setModel(ModelWithContent $model)
{
$this->model = $model;
}
/**
* @param string|null $name
* @return void
*/
protected function setName(string $name = null)
{
$this->name = $name;
}
/**
* @param array|string|null $placeholder
* @return void
*/
protected function setPlaceholder($placeholder = null)
{
$this->placeholder = $this->i18n($placeholder);
}
/**
* @param bool $required
* @return void
*/
protected function setRequired(bool $required = false)
{
$this->required = $required;
}
protected function setSiblings(Fields $siblings = null)
/**
* @param \Kirby\Form\Fields|null $siblings
* @return void
*/
protected function setSiblings(?Fields $siblings = null)
{
$this->siblings = $siblings ?? new Fields([]);
$this->siblings = $siblings ?? new Fields([$this]);
}
/**
* @param bool $translate
* @return void
*/
protected function setTranslate(bool $translate = true)
{
$this->translate = $translate;
}
/**
* Setter for the when condition
*
* @param mixed $when
* @return void
*/
protected function setWhen($when = null)
{
$this->when = $when;
}
/**
* Setter for the field width
*
* @param string|null $width
* @return void
*/
protected function setWidth(string $width = null)
{
$this->width = $width;
}
/**
* Returns all sibling fields
*
* @return \Kirby\Form\Fields
*/
protected function siblingsCollection()
{
return $this->siblings;
}
/**
* Parses a string template in the given value
*
* @param string|null $string
* @return string|null
*/
protected function stringTemplate(?string $string = null): ?string
{
if ($string !== null) {
@@ -482,6 +692,13 @@ abstract class FieldClass
return null;
}
/**
* Converts the given value to a value
* that can be stored in the text file
*
* @param mixed $value
* @return mixed
*/
public function store($value)
{
return $value;
@@ -514,6 +731,11 @@ abstract class FieldClass
});
}
/**
* Returns the field type
*
* @return string
*/
public function type(): string
{
return lcfirst(basename(str_replace(['\\', 'Field'], ['/', ''], static::class)));
@@ -587,6 +809,10 @@ abstract class FieldClass
return $this->value;
}
/**
* @param mixed $value
* @return array
*/
protected function valueFromJson($value): array
{
try {
@@ -596,11 +822,20 @@ abstract class FieldClass
}
}
protected function valueFromYaml($value)
/**
* @param mixed $value
* @return array
*/
protected function valueFromYaml($value): array
{
return Data::decode($value, 'yaml');
}
/**
* @param array|null $value
* @param bool $pretty
* @return string
*/
protected function valueToJson(array $value = null, bool $pretty = false): string
{
if ($pretty === true) {
@@ -610,6 +845,10 @@ abstract class FieldClass
return json_encode($value);
}
/**
* @param array|null $value
* @return string
*/
protected function valueToYaml(array $value = null): string
{
return Data::encode($value, 'yaml');

View File

@@ -3,7 +3,10 @@
namespace Kirby\Form;
use Kirby\Cms\App;
use Kirby\Cms\Model;
use Kirby\Data\Data;
use Kirby\Exception\NotFoundException;
use Kirby\Toolkit\Str;
use Throwable;
/**
@@ -54,6 +57,12 @@ class Form
$strict = $props['strict'] ?? false;
$inject = $props;
// prepare field properties for multilang setups
$fields = static::prepareFieldsForLanguage(
$fields,
$props['language'] ?? null
);
// lowercase all value names
$values = array_change_key_case($values);
$input = array_change_key_case($input);
@@ -194,6 +203,42 @@ class Form
return Field::factory('info', $props);
}
/**
* Get the field object by name
* and handle nested fields correctly
*
* @param string $name
* @throws \Kirby\Exception\NotFoundException
* @return \Kirby\Form\Field
*/
public function field(string $name)
{
$form = $this;
$fieldNames = Str::split($name, '+');
$index = 0;
$count = count($fieldNames);
$field = null;
foreach ($fieldNames as $fieldName) {
$index++;
if ($field = $form->fields()->get($fieldName)) {
if ($count !== $index) {
$form = $field->form();
}
} else {
throw new NotFoundException('The field "' . $fieldName . '" could not be found');
}
}
// it can get this error only if $name is an empty string as $name = ''
if ($field === null) {
throw new NotFoundException('No field could be loaded');
}
return $field;
}
/**
* Returns form fields
*
@@ -204,6 +249,47 @@ class Form
return $this->fields;
}
/**
* @param \Kirby\Cms\Model $model
* @param array $props
* @return static
*/
public static function for(Model $model, array $props = [])
{
// get the original model data
$original = $model->content($props['language'] ?? null)->toArray();
$values = $props['values'] ?? [];
// convert closures to values
foreach ($values as $key => $value) {
if (is_a($value, 'Closure') === true) {
$values[$key] = $value($original[$key] ?? null);
}
}
// set a few defaults
$props['values'] = array_merge($original, $values);
$props['fields'] = $props['fields'] ?? [];
$props['model'] = $model;
// search for the blueprint
if (method_exists($model, 'blueprint') === true && $blueprint = $model->blueprint()) {
$props['fields'] = $blueprint->fields();
}
$ignoreDisabled = $props['ignoreDisabled'] ?? false;
// REFACTOR: this could be more elegant
if ($ignoreDisabled === true) {
$props['fields'] = array_map(function ($field) {
$field['disabled'] = false;
return $field;
}, $props['fields']);
}
return new static($props);
}
/**
* Checks if the form is invalid
*
@@ -224,6 +310,40 @@ class Form
return empty($this->errors()) === true;
}
/**
* Disables fields in secondary languages when
* they are configured to be untranslatable
*
* @param array $fields
* @param string|null $language
* @return array
*/
protected static function prepareFieldsForLanguage(array $fields, ?string $language = null): array
{
$kirby = App::instance(null, true);
// only modify the fields if we have a valid Kirby multilang instance
if (!$kirby || $kirby->multilang() === false) {
return $fields;
}
if ($language === null) {
$language = $kirby->language()->code();
}
if ($language !== $kirby->defaultLanguage()->code()) {
foreach ($fields as $fieldName => $fieldProps) {
// switch untranslatable fields to readonly
if (($fieldProps['translate'] ?? true) === false) {
$fields[$fieldName]['unset'] = true;
$fields[$fieldName]['disabled'] = true;
}
}
}
return $fields;
}
/**
* Converts the data of fields to strings
*

View File

@@ -7,7 +7,6 @@ use Kirby\Exception\Exception;
use Kirby\Exception\InvalidArgumentException;
use Kirby\Http\Remote;
use Kirby\Http\Url;
use Kirby\Toolkit\Escape;
use Kirby\Toolkit\Properties;
use Kirby\Toolkit\Query;
use Kirby\Toolkit\Str;
@@ -27,17 +26,17 @@ class OptionsApi
use Properties;
/**
* @var
* @var array
*/
protected $data;
/**
* @var
* @var string|null
*/
protected $fetch;
/**
* @var
* @var array|string|null
*/
protected $options;
@@ -47,7 +46,7 @@ class OptionsApi
protected $text = '{{ item.value }}';
/**
* @var
* @var string
*/
protected $url;
@@ -90,11 +89,7 @@ class OptionsApi
protected function field(string $field, array $data): string
{
$value = $this->$field();
return Str::template($value, $data, [
'callback' => function ($result) {
return Escape::html($result);
}
]);
return Str::safeTemplate($value, $data);
}
/**
@@ -166,14 +161,14 @@ class OptionsApi
* @param string|null $fetch
* @return $this
*/
protected function setFetch(string $fetch = null)
protected function setFetch(?string $fetch = null)
{
$this->fetch = $fetch;
return $this;
}
/**
* @param $options
* @param array|string|null $options
* @return $this
*/
protected function setOptions($options = null)
@@ -183,30 +178,30 @@ class OptionsApi
}
/**
* @param $text
* @param string $text
* @return $this
*/
protected function setText($text = null)
protected function setText(?string $text = null)
{
$this->text = $text;
return $this;
}
/**
* @param $url
* @param string $url
* @return $this
*/
protected function setUrl($url)
protected function setUrl(string $url)
{
$this->url = $url;
return $this;
}
/**
* @param null $value
* @param string|null $value
* @return $this
*/
protected function setValue($value = null)
protected function setValue(?string $value = null)
{
$this->value = $value;
return $this;
@@ -215,7 +210,7 @@ class OptionsApi
/**
* @return string
*/
public function text()
public function text(): string
{
return $this->text;
}
@@ -240,7 +235,7 @@ class OptionsApi
/**
* @return string
*/
public function value()
public function value(): string
{
return $this->value;
}

View File

@@ -6,7 +6,6 @@ use Kirby\Cms\Field;
use Kirby\Exception\InvalidArgumentException;
use Kirby\Exception\NotFoundException;
use Kirby\Toolkit\Collection;
use Kirby\Toolkit\Escape;
use Kirby\Toolkit\Obj;
use Kirby\Toolkit\Properties;
use Kirby\Toolkit\Query;
@@ -103,26 +102,7 @@ class OptionsQuery
$value = $value[$object];
}
$result = Str::template($value, $data);
// escape the default queries for the `text` field
// TODO: remove after default escape implemented for query templates in 3.6
if ($field === 'text') {
$defaults = [
'arrayItem' => '{{ arrayItem.value }}',
'block' => '{{ block.type }}: {{ block.id }}',
'file' => '{{ file.filename }}',
'page' => '{{ page.title }}',
'structureItem' => '{{ structureItem.title }}',
'user' => '{{ user.username }}',
];
if (isset($defaults[$object]) && $value === $defaults[$object]) {
$result = Escape::html($result);
}
}
return $result;
return Str::safeTemplate($value, $data);
}
/**

View File

@@ -19,12 +19,12 @@ class Validations
/**
* Validates if the field value is boolean
*
* @param \Kirby\Form\Field $field
* @param \Kirby\Form\Field|\Kirby\Form\FieldClass $field
* @param $value
* @return bool
* @throws \Kirby\Exception\InvalidArgumentException
*/
public static function boolean(Field $field, $value): bool
public static function boolean($field, $value): bool
{
if ($field->isEmpty($value) === false) {
if (is_bool($value) === false) {
@@ -40,12 +40,12 @@ class Validations
/**
* Validates if the field value is valid date
*
* @param \Kirby\Form\Field $field
* @param \Kirby\Form\Field|\Kirby\Form\FieldClass $field
* @param $value
* @return bool
* @throws \Kirby\Exception\InvalidArgumentException
*/
public static function date(Field $field, $value): bool
public static function date($field, $value): bool
{
if ($field->isEmpty($value) === false) {
if (V::date($value) !== true) {
@@ -61,12 +61,12 @@ class Validations
/**
* Validates if the field value is valid email
*
* @param \Kirby\Form\Field $field
* @param \Kirby\Form\Field|\Kirby\Form\FieldClass $field
* @param $value
* @return bool
* @throws \Kirby\Exception\InvalidArgumentException
*/
public static function email(Field $field, $value): bool
public static function email($field, $value): bool
{
if ($field->isEmpty($value) === false) {
if (V::email($value) === false) {
@@ -82,12 +82,12 @@ class Validations
/**
* Validates if the field value is maximum
*
* @param \Kirby\Form\Field $field
* @param \Kirby\Form\Field|\Kirby\Form\FieldClass $field
* @param $value
* @return bool
* @throws \Kirby\Exception\InvalidArgumentException
*/
public static function max(Field $field, $value): bool
public static function max($field, $value): bool
{
if ($field->isEmpty($value) === false && $field->max() !== null) {
if (V::max($value, $field->max()) === false) {
@@ -103,12 +103,12 @@ class Validations
/**
* Validates if the field value is max length
*
* @param \Kirby\Form\Field $field
* @param \Kirby\Form\Field|\Kirby\Form\FieldClass $field
* @param $value
* @return bool
* @throws \Kirby\Exception\InvalidArgumentException
*/
public static function maxlength(Field $field, $value): bool
public static function maxlength($field, $value): bool
{
if ($field->isEmpty($value) === false && $field->maxlength() !== null) {
if (V::maxLength($value, $field->maxlength()) === false) {
@@ -124,12 +124,12 @@ class Validations
/**
* Validates if the field value is minimum
*
* @param \Kirby\Form\Field $field
* @param \Kirby\Form\Field|\Kirby\Form\FieldClass $field
* @param $value
* @return bool
* @throws \Kirby\Exception\InvalidArgumentException
*/
public static function min(Field $field, $value): bool
public static function min($field, $value): bool
{
if ($field->isEmpty($value) === false && $field->min() !== null) {
if (V::min($value, $field->min()) === false) {
@@ -145,12 +145,12 @@ class Validations
/**
* Validates if the field value is min length
*
* @param \Kirby\Form\Field $field
* @param \Kirby\Form\Field|\Kirby\Form\FieldClass $field
* @param $value
* @return bool
* @throws \Kirby\Exception\InvalidArgumentException
*/
public static function minlength(Field $field, $value): bool
public static function minlength($field, $value): bool
{
if ($field->isEmpty($value) === false && $field->minlength() !== null) {
if (V::minLength($value, $field->minlength()) === false) {
@@ -166,12 +166,12 @@ class Validations
/**
* Validates if the field value matches defined pattern
*
* @param \Kirby\Form\Field $field
* @param \Kirby\Form\Field|\Kirby\Form\FieldClass $field
* @param $value
* @return bool
* @throws \Kirby\Exception\InvalidArgumentException
*/
public static function pattern(Field $field, $value): bool
public static function pattern($field, $value): bool
{
if ($field->isEmpty($value) === false && $field->pattern() !== null) {
if (V::match($value, '/' . $field->pattern() . '/i') === false) {
@@ -187,12 +187,12 @@ class Validations
/**
* Validates if the field value is required
*
* @param \Kirby\Form\Field $field
* @param \Kirby\Form\Field|\Kirby\Form\FieldClass $field
* @param $value
* @return bool
* @throws \Kirby\Exception\InvalidArgumentException
*/
public static function required(Field $field, $value): bool
public static function required($field, $value): bool
{
if ($field->isRequired() === true && $field->save() === true && $field->isEmpty($value) === true) {
throw new InvalidArgumentException([
@@ -206,12 +206,12 @@ class Validations
/**
* Validates if the field value is in defined options
*
* @param \Kirby\Form\Field $field
* @param \Kirby\Form\Field|\Kirby\Form\FieldClass $field
* @param $value
* @return bool
* @throws \Kirby\Exception\InvalidArgumentException
*/
public static function option(Field $field, $value): bool
public static function option($field, $value): bool
{
if ($field->isEmpty($value) === false) {
$values = array_column($field->options(), 'value');
@@ -229,12 +229,12 @@ class Validations
/**
* Validates if the field values is in defined options
*
* @param \Kirby\Form\Field $field
* @param \Kirby\Form\Field|\Kirby\Form\FieldClass $field
* @param $value
* @return bool
* @throws \Kirby\Exception\InvalidArgumentException
*/
public static function options(Field $field, $value): bool
public static function options($field, $value): bool
{
if ($field->isEmpty($value) === false) {
$values = array_column($field->options(), 'value');
@@ -253,12 +253,12 @@ class Validations
/**
* Validates if the field value is valid time
*
* @param \Kirby\Form\Field $field
* @param \Kirby\Form\Field|\Kirby\Form\FieldClass $field
* @param $value
* @return bool
* @throws \Kirby\Exception\InvalidArgumentException
*/
public static function time(Field $field, $value): bool
public static function time($field, $value): bool
{
if ($field->isEmpty($value) === false) {
if (V::time($value) !== true) {
@@ -274,12 +274,12 @@ class Validations
/**
* Validates if the field value is valid url
*
* @param \Kirby\Form\Field $field
* @param \Kirby\Form\Field|\Kirby\Form\FieldClass $field
* @param $value
* @return bool
* @throws \Kirby\Exception\InvalidArgumentException
*/
public static function url(Field $field, $value): bool
public static function url($field, $value): bool
{
if ($field->isEmpty($value) === false) {
if (V::url($value) === false) {