Upgrade to 3.9.5

This commit is contained in:
Bastian Allgeier
2023-06-07 14:12:49 +02:00
parent 38c8ba7e59
commit f76fbaa53e
49 changed files with 625 additions and 633 deletions

View File

@@ -26,7 +26,7 @@ class NodeString extends NodeProperty
public static function factory($value = null): static|null
{
if ($value === null) {
return $value;
return null;
}
return new static($value);

View File

@@ -364,8 +364,8 @@ class App
* by name. All relevant dependencies are
* automatically injected
*
* @param string $name
* @return \Kirby\Cms\Collection|null
* @return \Kirby\Toolkit\Collection|null
* @todo 5.0 Add return type declaration
*/
public function collection(string $name)
{
@@ -379,10 +379,8 @@ class App
/**
* Returns all user-defined collections
*
* @return \Kirby\Cms\Collections
*/
public function collections()
public function collections(): Collections
{
return $this->collections ??= new Collections();
}

View File

@@ -66,7 +66,7 @@ trait AppUsers
} finally {
// ensure that the impersonation is *always* reset
// to the original value, even if an error occurred
$auth->impersonate($userBefore !== null ? $userBefore->id() : null);
$auth->impersonate($userBefore?->id());
}
}

View File

@@ -209,9 +209,9 @@ class Collection extends BaseCollection
* or ids and then search accordingly.
*
* @param string|object $needle
* @return int
* @return int|false
*/
public function indexOf($needle): int
public function indexOf($needle): int|false
{
if (is_string($needle) === true) {
return array_search($needle, $this->keys());

View File

@@ -28,25 +28,20 @@ class Collections
* has been called, to avoid further
* processing on sequential calls to
* the same collection.
*
* @var array
*/
protected $cache = [];
protected array $cache = [];
/**
* Store of all collections
*
* @var array
*/
protected $collections = [];
protected array $collections = [];
/**
* Magic caller to enable something like
* `$collections->myCollection()`
*
* @param string $name
* @param array $arguments
* @return \Kirby\Cms\Collection|null
* @return \Kirby\Toolkit\Collection|null
* @todo 5.0 Add return type declaration
*/
public function __call(string $name, array $arguments = [])
{
@@ -56,9 +51,9 @@ class Collections
/**
* Loads a collection by name if registered
*
* @param string $name
* @param array $data
* @return \Kirby\Cms\Collection|null
* @return \Kirby\Toolkit\Collection|null
* @todo 4.0 Add deprecation warning when anything else than a Collection is returned
* @todo 5.0 Add return type declaration
*/
public function get(string $name, array $data = [])
{

View File

@@ -95,7 +95,7 @@ trait HasFiles
// find by global UUID
if (Uuid::is($filename, 'file') === true) {
return Uuid::for($filename, $this->files())->model();
return Uuid::for($filename, $this->$in())->model();
}
if (strpos($filename, '/') !== false) {

View File

@@ -19,9 +19,9 @@ trait HasSiblings
*
* @param \Kirby\Cms\Collection|null $collection
*
* @return int
* @return int|false
*/
public function indexOf($collection = null): int
public function indexOf($collection = null): int|false
{
$collection ??= $this->siblingsCollection();
return $collection->indexOf($this);
@@ -29,10 +29,13 @@ trait HasSiblings
/**
* Returns the next item in the collection if available
* @todo `static` return type hint is not 100% accurate because of
* quirks in the `Form` classes; would break if enforced
* (https://github.com/getkirby/kirby/pull/5175)
*
* @param \Kirby\Cms\Collection|null $collection
*
* @return \Kirby\Cms\Model|null
* @return static|null
*/
public function next($collection = null)
{
@@ -55,10 +58,13 @@ trait HasSiblings
/**
* Returns the previous item in the collection if available
* @todo `static` return type hint is not 100% accurate because of
* quirks in the `Form` classes; would break if enforced
* (https://github.com/getkirby/kirby/pull/5175)
*
* @param \Kirby\Cms\Collection|null $collection
*
* @return \Kirby\Cms\Model|null
* @return static|null
*/
public function prev($collection = null)
{

View File

@@ -270,9 +270,9 @@ class Pages extends Collection
$query = $startAt;
foreach ($path as $key) {
$collection = $item ? $item->children() : $this;
$query = ltrim($query . '/' . $key, '/');
$item = $collection->get($query) ?? null;
$collection = $item?->children() ?? $this;
$query = ltrim($query . '/' . $key, '/');
$item = $collection->get($query) ?? null;
if ($item === null && $multiLang === true && !App::instance()->language()->isDefault()) {
if (count($path) > 1 || $collection->parent()) {

View File

@@ -62,7 +62,7 @@ class Database
/**
* The last error
*/
protected Exception|null $lastError = null;
protected Throwable|null $lastError = null;
/**
* The last insert id
@@ -280,7 +280,7 @@ class Database
/**
* Returns the last db error
*/
public function lastError(): Throwable
public function lastError(): Throwable|null
{
return $this->lastError;
}

View File

@@ -354,7 +354,7 @@ class File
return F::modified(
$this->root(),
$format,
$handler ?? ($kirby ? $kirby->option('date.handler', 'date') : 'date')
$handler ?? $kirby?->option('date.handler', 'date') ?? 'date'
);
}

View File

@@ -402,7 +402,7 @@ class Field extends Component
if ($formFields !== null) {
foreach ($this->when as $field => $value) {
$field = $formFields->get($field);
$inputValue = $field !== null ? $field->value() : '';
$inputValue = $field?->value() ?? '';
// if the input data doesn't match the requested `when` value,
// that means that this field is not required and can be saved

View File

@@ -49,7 +49,7 @@ class LayoutField extends BlocksField
$settings = $this->settings();
return new Form([
'fields' => $settings ? $settings->fields() : [],
'fields' => $settings?->fields() ?? [],
'model' => $this->model,
'strict' => true,
'values' => $input,
@@ -66,7 +66,7 @@ class LayoutField extends BlocksField
$settings = $this->settings();
return array_merge(parent::props(), [
'settings' => $settings !== null ? $settings->toArray() : null,
'settings' => $settings?->toArray(),
'layouts' => $this->layouts()
]);
}

View File

@@ -427,7 +427,7 @@ abstract class FieldClass
if ($formFields !== null) {
foreach ($this->when as $field => $value) {
$field = $formFields->get($field);
$inputValue = $field !== null ? $field->value() : '';
$inputValue = $field?->value() ?? '';
// if the input data doesn't match the requested `when` value,
// that means that this field is not required and can be saved

View File

@@ -377,8 +377,8 @@ class Environment
$data['https'] = $this->detectHttpsProtocol($fields['proto']);
}
if ($data['port'] === null && $data['https'] === true) {
$data['port'] = 443;
if ($data['https'] === true) {
$data['port'] ??= 443;
}
$data['for'] = $parts['for'] ?? null;

View File

@@ -195,7 +195,7 @@ class Request
*/
public function data(): array
{
return array_merge($this->body()->toArray(), $this->query()->toArray());
return array_replace($this->body()->toArray(), $this->query()->toArray());
}
/**
@@ -210,8 +210,8 @@ class Request
// the request method can be overwritten with a header
$methodOverride = strtoupper(Environment::getGlobally('HTTP_X_HTTP_METHOD_OVERRIDE', ''));
if ($method === null && in_array($methodOverride, $methods) === true) {
$method = $methodOverride;
if (in_array($methodOverride, $methods) === true) {
$method ??= $methodOverride;
}
// final chain of options to detect the method

View File

@@ -69,10 +69,15 @@ class Document
'custom' => static::customAsset('panel.css'),
],
'icons' => static::favicon($url),
// loader for plugins' index.dev.mjs files inlined, so we provide the code instead of the asset URL
// loader for plugins' index.dev.mjs files
// inlined, so we provide the code instead of the asset URL
'plugin-imports' => $plugins->read('mjs'),
'js' => [
'vendor' => [
'vue' => [
'nonce' => $nonce,
'src' => $url . '/js/vue.js'
],
'vendor' => [
'nonce' => $nonce,
'src' => $url . '/js/vendor.js',
'type' => 'module'
@@ -82,17 +87,17 @@ class Document
'src' => $url . '/js/plugins.js',
'type' => 'module'
],
'plugins' => [
'plugins' => [
'nonce' => $nonce,
'src' => $plugins->url('js'),
'defer' => true
],
'custom' => [
'custom' => [
'nonce' => $nonce,
'src' => static::customAsset('panel.js'),
'type' => 'module'
],
'index' => [
'index' => [
'nonce' => $nonce,
'src' => $url . '/js/index.js',
'type' => 'module'
@@ -115,6 +120,9 @@ class Document
'type' => 'module'
];
// load the development version of Vue
$assets['js']['vue']['src'] = $url . '/node_modules/vue/dist/vue.js';
unset($assets['css']['index'], $assets['js']['vendor']);
}

View File

@@ -137,7 +137,7 @@ class View
$user = $kirby->user();
// user permissions
$permissions = $user ? $user->role()->permissions()->toArray() : [];
$permissions = $user?->role()->permissions()->toArray() ?? [];
// current content language
$language = $kirby->language();

View File

@@ -117,20 +117,23 @@ class A
$keys = explode('.', $key);
$firstKey = array_shift($keys);
// if the input array also uses dot notation, try to find a subset of the $keys
// if the input array also uses dot notation,
// try to find a subset of the $keys
if (isset($array[$firstKey]) === false) {
$currentKey = $firstKey;
while ($innerKey = array_shift($keys)) {
$currentKey .= '.' . $innerKey;
// the element needs to exist and also needs to be an array; otherwise
// we cannot find the remaining keys within it (invalid array structure)
// the element needs to exist and also needs
// to be an array; otherwise we cannot find the
// remaining keys within it (invalid array structure)
if (
isset($array[$currentKey]) === true &&
is_array($array[$currentKey]) === true
) {
// $keys only holds the remaining keys that have not been shifted off yet
// $keys only holds the remaining keys
// that have not been shifted off yet
return static::get(
$array[$currentKey],
implode('.', $keys),
@@ -204,7 +207,10 @@ class A
*/
public static function keyBy(array $array, string|callable $keyBy): array
{
$keys = is_callable($keyBy) ? static::map($array, $keyBy) : static::pluck($array, $keyBy);
$keys =
is_callable($keyBy) ?
static::map($array, $keyBy) :
static::pluck($array, $keyBy);
if (count($keys) !== count($array)) {
throw new InvalidArgumentException('The "key by" argument must be a valid key or a callable');
@@ -600,7 +606,7 @@ class A
$key = array_shift($subKeys);
// skip the magic for ignored keys
if (isset($ignore[$key]) === true && $ignore[$key] === true) {
if (($ignore[$key] ?? null) === true) {
$result[$fullKey] = $value;
continue;
}
@@ -618,8 +624,7 @@ class A
// merge arrays with previous results if necessary
// (needed when the same keys are used both with and without dot notation)
if (
isset($result[$key]) === true &&
is_array($result[$key]) === true &&
is_array($result[$key] ?? null) === true &&
is_array($value) === true
) {
$value = array_replace_recursive($result[$key], $value);
@@ -704,8 +709,12 @@ class A
* PHP by sort flags
* @return array The sorted array
*/
public static function sort(array $array, string $field, string $direction = 'desc', $method = SORT_REGULAR): array
{
public static function sort(
array $array,
string $field,
string $direction = 'desc',
$method = SORT_REGULAR
): array {
$direction = strtolower($direction) === 'desc' ? SORT_DESC : SORT_ASC;
$helper = [];
$result = [];
@@ -818,7 +827,7 @@ class A
{
foreach ($update as $key => $value) {
if ($value instanceof Closure) {
$value = call_user_func($value, static::get($array, $key));
$value = $value(static::get($array, $key));
}
$array[$key] = $value;

View File

@@ -84,10 +84,6 @@ class Component
/**
* Magic caller for defined methods and properties
*
* @param string $name
* @param array $arguments
* @return mixed
*/
public function __call(string $name, array $arguments = [])
{
@@ -108,9 +104,6 @@ class Component
/**
* Creates a new component for the given type
*
* @param string $type
* @param array $attrs
*/
public function __construct(string $type, array $attrs = [])
{
@@ -142,8 +135,6 @@ class Component
/**
* Improved `var_dump` output
*
* @return array
*/
public function __debugInfo(): array
{
@@ -153,9 +144,6 @@ class Component
/**
* Fallback for missing properties to return
* null instead of an error
*
* @param string $attr
* @return null
*/
public function __get(string $attr)
{
@@ -167,8 +155,6 @@ class Component
* This can be overwritten by extended classes
* to define basic options that should always
* be applied.
*
* @return array
*/
public static function defaults(): array
{
@@ -178,9 +164,6 @@ class Component
/**
* Register all defined props and apply the
* passed values.
*
* @param array $props
* @return void
*/
protected function applyProps(array $props): void
{
@@ -208,9 +191,6 @@ class Component
/**
* Register all computed properties and calculate their values.
* This must happen after all props are registered.
*
* @param array $computed
* @return void
*/
protected function applyComputed(array $computed): void
{
@@ -223,9 +203,6 @@ class Component
/**
* Load a component definition by type
*
* @param string $type
* @return array
*/
public static function load(string $type): array
{
@@ -248,9 +225,6 @@ class Component
* mixes in the defaults from the defaults method and
* then injects all additional mixins, defined in the
* component options.
*
* @param string $type
* @return array
*/
public static function setup(string $type): array
{
@@ -292,8 +266,6 @@ class Component
/**
* Converts all props and computed props to an array
*
* @return array
*/
public function toArray(): array
{

View File

@@ -44,7 +44,7 @@ class Controller
return $this->function->call($bind, ...$args);
}
public static function load(string $file)
public static function load(string $file): static|null
{
if (is_file($file) === false) {
return null;

View File

@@ -2,6 +2,7 @@
namespace Kirby\Toolkit;
use DateInterval;
use DateTime;
use DateTimeInterface;
use DateTimeZone;
@@ -27,8 +28,10 @@ class Date extends DateTime
* @param string|int|\DateTimeInterface $datetime Datetime string, UNIX timestamp or object
* @param \DateTimeZone|null $timezone Optional default timezone if `$datetime` is string
*/
public function __construct($datetime = 'now', ?DateTimeZone $timezone = null)
{
public function __construct(
string|int|DateTimeInterface $datetime = 'now',
DateTimeZone|null $timezone = null
) {
if (is_int($datetime) === true) {
$datetime = date('r', $datetime);
}
@@ -42,8 +45,6 @@ class Date extends DateTime
/**
* Returns the datetime in `YYYY-MM-DD hh:mm:ss` format with timezone
*
* @return string
*/
public function __toString(): string
{
@@ -58,7 +59,7 @@ class Date extends DateTime
*
* @throws \Kirby\Exception\InvalidArgumentException If the unit name is invalid
*/
public function ceil(string $unit)
public function ceil(string $unit): static
{
static::validateUnit($unit);
@@ -70,20 +71,17 @@ class Date extends DateTime
/**
* Returns the interval between the provided and the object's datetime
*
* @param string|int|\DateTimeInterface $datetime
* @param \DateTimeZone|null $timezone Optional default timezone if `$datetime` is string
* @return \DateInterval
*/
public function compare($datetime = 'now', ?DateTimeZone $timezone = null)
{
public function compare(
string|int|DateTimeInterface $datetime = 'now',
DateTimeZone|null $timezone = null
): DateInterval {
return $this->diff(new static($datetime, $timezone));
}
/**
* Gets or sets the day value
*
* @param int|null $day
* @return int
*/
public function day(int|null $day = null): int
{
@@ -103,7 +101,7 @@ class Date extends DateTime
*
* @throws \Kirby\Exception\InvalidArgumentException If the unit name is invalid
*/
public function floor(string $unit)
public function floor(string $unit): static
{
static::validateUnit($unit);
@@ -123,9 +121,6 @@ class Date extends DateTime
/**
* Gets or sets the hour value
*
* @param int|null $hour
* @return int
*/
public function hour(int|null $hour = null): int
{
@@ -140,79 +135,75 @@ class Date extends DateTime
/**
* Checks if the object's datetime is the same as the given datetime
*
* @param string|int|\DateTimeInterface $datetime
* @param \DateTimeZone|null $timezone Optional default timezone if `$datetime` is string
* @return bool
*/
public function is($datetime = 'now', ?DateTimeZone $timezone = null): bool
{
public function is(
string|int|DateTimeInterface $datetime = 'now',
DateTimeZone|null $timezone = null
): bool {
return $this == new static($datetime, $timezone);
}
/**
* Checks if the object's datetime is after the given datetime
*
* @param string|int|\DateTimeInterface $datetime
* @param \DateTimeZone|null $timezone Optional default timezone if `$datetime` is string
* @return bool
*/
public function isAfter($datetime = 'now', ?DateTimeZone $timezone = null): bool
{
public function isAfter(
string|int|DateTimeInterface $datetime = 'now',
DateTimeZone|null $timezone = null
): bool {
return $this > new static($datetime, $timezone);
}
/**
* Checks if the object's datetime is before the given datetime
*
* @param string|int|\DateTimeInterface $datetime
* @param \DateTimeZone|null $timezone Optional default timezone if `$datetime` is string
* @return bool
*/
public function isBefore($datetime = 'now', ?DateTimeZone $timezone = null): bool
{
public function isBefore(
string|int|DateTimeInterface $datetime = 'now',
DateTimeZone|null $timezone = null
): bool {
return $this < new static($datetime, $timezone);
}
/**
* Checks if the object's datetime is between the given datetimes
*
* @param string|int|\DateTimeInterface $min
* @param string|int|\DateTimeInterface $max
* @return bool
*/
public function isBetween($min, $max): bool
{
public function isBetween(
string|int|DateTimeInterface $min,
string|int|DateTimeInterface $max
): bool {
return $this->isMin($min) === true && $this->isMax($max) === true;
}
/**
* Checks if the object's datetime is at or before the given datetime
*
* @param string|int|\DateTimeInterface $datetime
* @param \DateTimeZone|null $timezone Optional default timezone if `$datetime` is string
* @return bool
*/
public function isMax($datetime = 'now', ?DateTimeZone $timezone = null): bool
{
public function isMax(
string|int|DateTimeInterface $datetime = 'now',
DateTimeZone|null $timezone = null
): bool {
return $this <= new static($datetime, $timezone);
}
/**
* Checks if the object's datetime is at or after the given datetime
*
* @param string|int|\DateTimeInterface $datetime
* @param \DateTimeZone|null $timezone Optional default timezone if `$datetime` is string
* @return bool
*/
public function isMin($datetime = 'now', ?DateTimeZone $timezone = null): bool
{
public function isMin(
string|int|DateTimeInterface $datetime = 'now',
DateTimeZone|null $timezone = null
): bool {
return $this >= new static($datetime, $timezone);
}
/**
* Gets the microsecond value
*
* @return int
*/
public function microsecond(): int
{
@@ -221,8 +212,6 @@ class Date extends DateTime
/**
* Gets the millisecond value
*
* @return int
*/
public function millisecond(): int
{
@@ -231,9 +220,6 @@ class Date extends DateTime
/**
* Gets or sets the minute value
*
* @param int|null $minute
* @return int
*/
public function minute(int|null $minute = null): int
{
@@ -247,9 +233,6 @@ class Date extends DateTime
/**
* Gets or sets the month value
*
* @param int|null $month
* @return int
*/
public function month(int|null $month = null): int
{
@@ -265,10 +248,10 @@ class Date extends DateTime
* Returns the datetime which is nearest to the object's datetime
*
* @param string|int|\DateTimeInterface ...$datetime Datetime strings, UNIX timestamps or objects
* @return string|int|\DateTimeInterface
*/
public function nearest(...$datetime)
{
public function nearest(
string|int|DateTimeInterface ...$datetime
): string|int|DateTimeInterface {
$timestamp = $this->timestamp();
$minDiff = PHP_INT_MAX;
$nearest = null;
@@ -291,9 +274,8 @@ class Date extends DateTime
* Returns an instance of the current datetime
*
* @param \DateTimeZone|null $timezone
* @return static
*/
public static function now(?DateTimeZone $timezone = null)
public static function now(DateTimeZone|null $timezone = null): static
{
return new static('now', $timezone);
}
@@ -301,13 +283,11 @@ class Date extends DateTime
/**
* Tries to create an instance from the given string
* or fails silently by returning `null` on error
*
* @param string|null $datetime
* @param \DateTimeZone|null $timezone
* @return static|null
*/
public static function optional(string|null $datetime = null, ?DateTimeZone $timezone = null)
{
public static function optional(
string|null $datetime = null,
DateTimeZone|null $timezone = null
): static|null {
if (empty($datetime) === true) {
return null;
}
@@ -328,7 +308,7 @@ class Date extends DateTime
*
* @throws \Kirby\Exception\InvalidArgumentException If the unit name or size is invalid
*/
public function round(string $unit, int $size = 1)
public function round(string $unit, int $size = 1): static
{
static::validateUnit($unit);
@@ -365,12 +345,12 @@ class Date extends DateTime
* by the defined step
* @since 3.7.0
*
* @param string|null $date
* @param int|array|null $step array of `unit` and `size` to round to nearest
* @return int|null
*/
public static function roundedTimestamp(string|null $date = null, $step = null): int|null
{
public static function roundedTimestamp(
string|null $date = null,
int|array|null $step = null
): int|null {
if ($date = static::optional($date)) {
if ($step !== null) {
$step = static::stepConfig($step, [
@@ -388,9 +368,6 @@ class Date extends DateTime
/**
* Gets or sets the second value
*
* @param int|null $second
* @return int
*/
public function second(int|null $second = null): int
{
@@ -408,8 +385,10 @@ class Date extends DateTime
* @param string|int|\DateTimeInterface $datetime Datetime string, UNIX timestamp or object
* @param \DateTimeZone|null $timezone Optional default timezone if `$datetime` is string
*/
public function set($datetime, ?DateTimeZone $timezone = null)
{
public function set(
string|int|DateTimeInterface $datetime,
DateTimeZone|null $timezone = null
): void {
$datetime = new static($datetime, $timezone);
$this->setTimestamp($datetime->timestamp());
}
@@ -422,13 +401,11 @@ class Date extends DateTime
* @param array|null $default Default values to use if one or both values are not provided
* @return array
*/
public static function stepConfig($input = null, array|null $default = null): array
{
$default ??= [
'size' => 1,
'unit' => 'day'
];
public static function stepConfig(
// no type hint to use InvalidArgumentException at the end
$input = null,
array|null $default = ['size' => 1, 'unit' => 'day']
): array {
if ($input === null) {
return $default;
}
@@ -452,8 +429,6 @@ class Date extends DateTime
/**
* Returns the time in `hh:mm:ss` format
*
* @return string
*/
public function time(): string
{
@@ -462,8 +437,6 @@ class Date extends DateTime
/**
* Returns the UNIX timestamp
*
* @return int
*/
public function timestamp(): int
{
@@ -472,21 +445,16 @@ class Date extends DateTime
/**
* Returns the timezone object
*
* @return \DateTimeZone
*/
public function timezone()
public function timezone(): DateTimeZone|false
{
return $this->getTimezone();
}
/**
* Returns an instance of the beginning of the current day
*
* @param \DateTimeZone|null $timezone
* @return static
*/
public static function today(?DateTimeZone $timezone = null)
public static function today(DateTimeZone|null $timezone = null): static
{
return new static('today', $timezone);
}
@@ -497,12 +465,13 @@ class Date extends DateTime
*
* @param string $mode `date`, `time` or `datetime`
* @param bool $timezone Whether the timezone is printed as well
* @return string
*
* @throws \Kirby\Exception\InvalidArgumentException If the mode is invalid
*/
public function toString(string $mode = 'datetime', bool $timezone = true): string
{
public function toString(
string $mode = 'datetime',
bool $timezone = true
): string {
$format = match ($mode) {
'date' => 'Y-m-d',
'time' => 'H:i:s',
@@ -519,9 +488,6 @@ class Date extends DateTime
/**
* Gets or sets the year value
*
* @param int|null $year
* @return int
*/
public function year(int|null $year = null): int
{
@@ -536,9 +502,6 @@ class Date extends DateTime
/**
* Ensures that the provided string is a valid unit name
*
* @param string $unit
* @return void
*
* @throws \Kirby\Exception\InvalidArgumentException
*/
protected static function validateUnit(string $unit): void

View File

@@ -17,17 +17,11 @@ abstract class Facade
/**
* Returns the instance that should be
* available statically
*
* @return mixed
*/
abstract public static function instance();
/**
* Proxy for all public instance calls
*
* @param string $method
* @param array $args
* @return mixed
*/
public static function __callStatic(string $method, array $args = null)
{

View File

@@ -90,10 +90,11 @@ class Html extends Xml
*
* @param string $tag Tag name
* @param array $arguments Further arguments for the Html::tag() method
* @return string
*/
public static function __callStatic(string $tag, array $arguments = []): string
{
public static function __callStatic(
string $tag,
array $arguments = []
): string {
if (static::isVoid($tag) === true) {
return static::tag($tag, null, ...$arguments);
}
@@ -133,8 +134,12 @@ class Html extends Xml
* @param string|null $after An optional string that will be appended if the result is not empty
* @return string|null The generated HTML attributes string
*/
public static function attr($name, $value = null, string|null $before = null, string|null $after = null): string|null
{
public static function attr(
string|array $name,
$value = null,
string|null $before = null,
string|null $after = null
): string|null {
// HTML supports boolean attributes without values
if (is_array($name) === false && is_bool($value) === true) {
return $value === true ? strtolower($name) : null;
@@ -167,9 +172,6 @@ class Html extends Xml
/**
* Converts lines in a string into HTML breaks
*
* @param string $string
* @return string
*/
public static function breaks(string $string): string
{
@@ -184,8 +186,11 @@ class Html extends Xml
* @param array $attr Additional attributes for the tag
* @return string The generated HTML
*/
public static function email(string $email, $text = null, array $attr = []): string
{
public static function email(
string $email,
string|array|null $text = null,
array $attr = []
): string {
if (empty($email) === true) {
return '';
}
@@ -214,14 +219,15 @@ class Html extends Xml
/**
* Converts a string to an HTML-safe string
*
* @param string|null $string
* @param bool $keepTags If true, existing tags won't be escaped
* @return string The HTML string
*
* @psalm-suppress ParamNameMismatch
*/
public static function encode(string|null $string, bool $keepTags = false): string
{
public static function encode(
string|null $string,
bool $keepTags = false
): string {
if ($string === null) {
return '';
}
@@ -241,8 +247,6 @@ class Html extends Xml
/**
* Returns the entity translation table
*
* @return array
*/
public static function entities(): array
{
@@ -257,8 +261,11 @@ class Html extends Xml
* @param array $attr Additional attributes for the `<figure>` tag
* @return string The generated HTML
*/
public static function figure($content, $caption = '', array $attr = []): string
{
public static function figure(
string|array $content,
string|array|null $caption = '',
array $attr = []
): string {
if ($caption) {
$figcaption = static::tag('figcaption', $caption);
@@ -280,8 +287,11 @@ class Html extends Xml
* @param array $attr Additional attributes for the `<script>` tag
* @return string The generated HTML
*/
public static function gist(string $url, string|null $file = null, array $attr = []): string
{
public static function gist(
string $url,
string|null $file = null,
array $attr = []
): string {
$src = $url . '.js';
if ($file !== null) {
@@ -294,7 +304,6 @@ class Html extends Xml
/**
* Creates an `<iframe>`
*
* @param string $src
* @param array $attr Additional attributes for the `<iframe>` tag
* @return string The generated HTML
*/
@@ -322,9 +331,6 @@ class Html extends Xml
/**
* Checks if a tag is self-closing
*
* @param string $tag
* @return bool
*/
public static function isVoid(string $tag): bool
{
@@ -339,8 +345,11 @@ class Html extends Xml
* @param array $attr Additional attributes for the tag
* @return string The generated HTML
*/
public static function link(string $href, $text = null, array $attr = []): string
{
public static function link(
string $href,
string|array|null $text = null,
array $attr = []
): string {
$attr = array_merge(['href' => $href], $attr);
if (empty($text) === true) {
@@ -364,8 +373,10 @@ class Html extends Xml
* @param string|null $target Current `target` value
* @return string|null New `rel` value or `null` if not needed
*/
public static function rel(string|null $rel = null, string|null $target = null): string|null
{
public static function rel(
string|null $rel = null,
string|null $target = null
): string|null {
$rel = trim($rel ?? '');
if ($target === '_blank') {
@@ -390,8 +401,13 @@ class Html extends Xml
* @param int $level Indentation level
* @return string The generated HTML
*/
public static function tag(string $name, $content = '', array $attr = [], string $indent = null, int $level = 0): string
{
public static function tag(
string $name,
array|string|null $content = '',
array $attr = [],
string $indent = null,
int $level = 0
): string {
// treat an explicit `null` value as an empty tag
// as void tags are already covered below
$content ??= '';
@@ -412,8 +428,11 @@ class Html extends Xml
* @param array $attr Additional attributes for the tag
* @return string The generated HTML
*/
public static function tel(string $tel, $text = null, array $attr = []): string
{
public static function tel(
string $tel,
string|array|null $text = null,
array $attr = []
): string {
$number = preg_replace('![^0-9\+]+!', '', $tel);
if (empty($text) === true) {
@@ -425,9 +444,6 @@ class Html extends Xml
/**
* Properly encodes tag contents
*
* @param mixed $value
* @return string|null
*/
public static function value($value): string|null
{
@@ -461,8 +477,11 @@ class Html extends Xml
* @param array $attr Additional attributes for the `<iframe>` tag
* @return string|null The generated HTML
*/
public static function video(string $url, array $options = [], array $attr = []): string|null
{
public static function video(
string $url,
array $options = [],
array $attr = []
): string|null {
// YouTube video
if (Str::contains($url, 'youtu', true) === true) {
return static::youtube($url, $options['youtube'] ?? [], $attr);
@@ -494,9 +513,6 @@ class Html extends Xml
/**
* Generates a list of attributes
* for video iframes
*
* @param array $attr
* @return array
*/
public static function videoAttr(array $attr = []): array
{
@@ -521,8 +537,11 @@ class Html extends Xml
* @param array $attr Additional attributes for the `<iframe>` tag
* @return string|null The generated HTML
*/
public static function vimeo(string $url, array $options = [], array $attr = []): string|null
{
public static function vimeo(
string $url,
array $options = [],
array $attr = []
): string|null {
$uri = new Uri($url);
$path = $uri->path();
$query = $uri->query();
@@ -556,8 +575,11 @@ class Html extends Xml
* @param array $attr Additional attributes for the `<iframe>` tag
* @return string|null The generated HTML
*/
public static function youtube(string $url, array $options = [], array $attr = []): string|null
{
public static function youtube(
string $url,
array $options = [],
array $attr = []
): string|null {
if (preg_match('!youtu!i', $url) !== 1) {
return null;
}

View File

@@ -23,14 +23,8 @@ use IteratorAggregate;
*/
class Iterator implements IteratorAggregate
{
/**
* The data array
*/
public array $data = [];
/**
* Constructor
*/
public function __construct(array $data = [])
{
$this->data = $data;

View File

@@ -17,9 +17,6 @@ use stdClass;
*/
class Obj extends stdClass
{
/**
* Constructor
*/
public function __construct(array $data = [])
{
foreach ($data as $key => $val) {

View File

@@ -22,38 +22,28 @@ class Pagination
/**
* The current page
*
* @var int
*/
protected $page;
protected int $page = 1;
/**
* Total number of items
*
* @var int
*/
protected $total = 0;
protected int $total = 0;
/**
* The number of items per page
*
* @var int
*/
protected $limit = 20;
protected int $limit = 20;
/**
* Whether validation of the pagination page
* is enabled; will throw Exceptions if true
*
* @var bool
*/
public static $validate = true;
public static bool $validate = true;
/**
* Creates a new pagination object
* with the given parameters
*
* @param array $props
*/
public function __construct(array $props = [])
{
@@ -63,53 +53,35 @@ class Pagination
/**
* Creates a pagination instance for the given
* collection with a flexible argument api
*
* @param \Kirby\Toolkit\Collection $collection
* @param mixed ...$arguments
* @return static
*/
public static function for(Collection $collection, ...$arguments)
public static function for(Collection $collection, ...$arguments): static
{
$a = $arguments[0] ?? null;
$b = $arguments[1] ?? null;
$params = [];
// First argument is a pagination object
if ($a instanceof static) {
/**
* First argument is a pagination/self object
*/
return $a;
} elseif (is_array($a) === true) {
/**
* First argument is an option array
*
* $collection->paginate([...])
*/
}
if (is_array($a) === true) {
// First argument is an option array
// $collection->paginate([...])
$params = $a;
} elseif (is_int($a) === true && $b === null) {
/**
* First argument is the limit
*
* $collection->paginate(10)
*/
// First argument is the limit
// $collection->paginate(10)
$params['limit'] = $a;
} elseif (is_int($a) === true && is_int($b) === true) {
/**
* First argument is the limit,
* second argument is the page
*
* $collection->paginate(10, 2)
*/
// First argument is the limit, second argument is the page
// $collection->paginate(10, 2)
$params['limit'] = $a;
$params['page'] = $b;
} elseif (is_int($a) === true && is_array($b) === true) {
/**
* First argument is the limit,
* second argument are options
*
* $collection->paginate(10, [...])
*/
// First argument is the limit, second argument are options
// $collection->paginate(10, [...])
$params = $b;
$params['limit'] = $a;
}
@@ -126,8 +98,6 @@ class Pagination
/**
* Getter for the current page
*
* @return int
*/
public function page(): int
{
@@ -136,8 +106,6 @@ class Pagination
/**
* Getter for the total number of items
*
* @return int
*/
public function total(): int
{
@@ -146,8 +114,6 @@ class Pagination
/**
* Getter for the number of items per page
*
* @return int
*/
public function limit(): int
{
@@ -156,40 +122,24 @@ class Pagination
/**
* Returns the index of the first item on the page
*
* @return int
*/
public function start(): int
{
$index = $this->page() - 1;
if ($index < 0) {
$index = 0;
}
$index = max(0, $this->page() - 1);
return $index * $this->limit() + 1;
}
/**
* Returns the index of the last item on the page
*
* @return int
*/
public function end(): int
{
$value = ($this->start() - 1) + $this->limit();
if ($value <= $this->total()) {
return $value;
}
return $this->total();
$value = min($this->total(), ($this->start() - 1) + $this->limit());
return $value;
}
/**
* Returns the total number of pages
*
* @return int
*/
public function pages(): int
{
@@ -202,8 +152,6 @@ class Pagination
/**
* Returns the first page
*
* @return int
*/
public function firstPage(): int
{
@@ -212,8 +160,6 @@ class Pagination
/**
* Returns the last page
*
* @return int
*/
public function lastPage(): int
{
@@ -222,8 +168,6 @@ class Pagination
/**
* Returns the offset (i.e. for db queries)
*
* @return int
*/
public function offset(): int
{
@@ -232,9 +176,6 @@ class Pagination
/**
* Checks if the given page exists
*
* @param int $page
* @return bool
*/
public function hasPage(int $page): bool
{
@@ -251,8 +192,6 @@ class Pagination
/**
* Checks if there are any pages at all
*
* @return bool
*/
public function hasPages(): bool
{
@@ -261,8 +200,6 @@ class Pagination
/**
* Checks if there's a previous page
*
* @return bool
*/
public function hasPrevPage(): bool
{
@@ -271,18 +208,14 @@ class Pagination
/**
* Returns the previous page
*
* @return int|null
*/
public function prevPage()
public function prevPage(): int|null
{
return $this->hasPrevPage() ? $this->page() - 1 : null;
}
/**
* Checks if there's a next page
*
* @return bool
*/
public function hasNextPage(): bool
{
@@ -291,18 +224,14 @@ class Pagination
/**
* Returns the next page
*
* @return int|null
*/
public function nextPage()
public function nextPage(): int|null
{
return $this->hasNextPage() ? $this->page() + 1 : null;
}
/**
* Checks if the current page is the first page
*
* @return bool
*/
public function isFirstPage(): bool
{
@@ -311,8 +240,6 @@ class Pagination
/**
* Checks if the current page is the last page
*
* @return bool
*/
public function isLastPage(): bool
{
@@ -321,9 +248,6 @@ class Pagination
/**
* Creates a range of page numbers for Google-like pagination
*
* @param int $range
* @return array
*/
public function range(int $range = 5): array
{
@@ -355,9 +279,6 @@ class Pagination
/**
* Returns the first page of the created range
*
* @param int $range
* @return int
*/
public function rangeStart(int $range = 5): int
{
@@ -366,9 +287,6 @@ class Pagination
/**
* Returns the last page of the created range
*
* @param int $range
* @return int
*/
public function rangeEnd(int $range = 5): int
{
@@ -383,7 +301,7 @@ class Pagination
* @param array $props Array with keys limit, total and/or page
* @return $this
*/
protected function setProperties(array $props)
protected function setProperties(array $props): static
{
$this->baseSetProperties($props);
@@ -415,10 +333,9 @@ class Pagination
/**
* Sets the number of items per page
*
* @param int $limit
* @return $this
*/
protected function setLimit(int $limit = 20)
protected function setLimit(int $limit = 20): static
{
if ($limit < 1) {
throw new Exception('Invalid pagination limit: ' . $limit);
@@ -431,10 +348,9 @@ class Pagination
/**
* Sets the total number of items
*
* @param int $total
* @return $this
*/
protected function setTotal(int $total = 0)
protected function setTotal(int $total = 0): static
{
if ($total < 0) {
throw new Exception('Invalid total number of items: ' . $total);
@@ -451,7 +367,7 @@ class Pagination
* automatically determined if null
* @return $this
*/
protected function setPage($page = null)
protected function setPage(int|string|null $page = null): static
{
// if $page is null, it is set to a default in the setProperties() method
if ($page !== null) {
@@ -467,8 +383,6 @@ class Pagination
/**
* Returns an array with all properties
*
* @return array
*/
public function toArray(): array
{

View File

@@ -166,8 +166,11 @@ class Str
/**
* Returns the rest of the string after the given substring or character
*/
public static function after(string $string, string $needle, bool $caseInsensitive = false): string
{
public static function after(
string $string,
string $needle,
bool $caseInsensitive = false
): string {
$position = static::position($string, $needle, $caseInsensitive);
if ($position === false) {
@@ -182,8 +185,11 @@ class Str
* only from the start of the string
* @since 3.7.0
*/
public static function afterStart(string $string, string $needle, bool $caseInsensitive = false): string
{
public static function afterStart(
string $string,
string $needle,
bool $caseInsensitive = false
): string {
if ($needle === '') {
return $string;
}
@@ -218,8 +224,11 @@ class Str
/**
* Returns the beginning of a string before the given substring or character
*/
public static function before(string $string, string $needle, bool $caseInsensitive = false): string
{
public static function before(
string $string,
string $needle,
bool $caseInsensitive = false
): string {
$position = static::position($string, $needle, $caseInsensitive);
if ($position === false) {
@@ -233,8 +242,11 @@ class Str
* Removes the given substring or character only from the end of the string
* @since 3.7.0
*/
public static function beforeEnd(string $string, string $needle, bool $caseInsensitive = false): string
{
public static function beforeEnd(
string $string,
string $needle,
bool $caseInsensitive = false
): string {
if ($needle === '') {
return $string;
}
@@ -249,8 +261,11 @@ class Str
/**
* Returns everything between two strings from the first occurrence of a given string
*/
public static function between(string $string = null, string $start, string $end): string
{
public static function between(
string $string = null,
string $start,
string $end
): string {
return static::before(static::after($string, $start), $end);
}
@@ -267,8 +282,11 @@ class Str
/**
* Checks if a str contains another string
*/
public static function contains(string $string = null, string $needle, bool $caseInsensitive = false): bool
{
public static function contains(
string $string = null,
string $needle,
bool $caseInsensitive = false
): bool {
if ($needle === '') {
return true;
}
@@ -283,8 +301,11 @@ class Str
*
* @param string $handler date, intl or strftime
*/
public static function date(int|null $time = null, string|IntlDateFormatter $format = null, string $handler = 'date'): string|int|false
{
public static function date(
int|null $time = null,
string|IntlDateFormatter $format = null,
string $handler = 'date'
): string|int|false {
if (is_null($format) === true) {
return $time;
}
@@ -321,8 +342,11 @@ class Str
/**
* Converts a string to a different encoding
*/
public static function convert(string $string, string $targetEncoding, string $sourceEncoding = null): string
{
public static function convert(
string $string,
string $targetEncoding,
string $sourceEncoding = null
): string {
// detect the source encoding if not passed as third argument
$sourceEncoding ??= static::encoding($string);
@@ -365,8 +389,11 @@ class Str
/**
* Checks if a string ends with the passed needle
*/
public static function endsWith(string $string = null, string $needle, bool $caseInsensitive = false): bool
{
public static function endsWith(
string $string = null,
string $needle,
bool $caseInsensitive = false
): bool {
if ($needle === '') {
return true;
}
@@ -389,8 +416,10 @@ class Str
* @param string $context Location of output (`html`, `attr`, `js`, `css`, `url` or `xml`)
* @return string Escaped data
*/
public static function esc(string $string, string $context = 'html'): string
{
public static function esc(
string $string,
string $context = 'html'
): string {
if (method_exists(Escape::class, $context) === true) {
return Escape::$context($string);
}
@@ -409,8 +438,12 @@ class Str
* @param string $rep The element, which should be added if the string is too long. Ellipsis is the default.
* @return string The shortened string
*/
public static function excerpt($string, $chars = 140, $strip = true, $rep = ' …')
{
public static function excerpt(
string $string,
int $chars = 140,
bool $strip = true,
string $rep = ' …'
): string {
if ($strip === true) {
// ensure that opening tags are preceded by a space, so that
// when tags are skipped we can be sure that words stay separate
@@ -441,8 +474,9 @@ class Str
* Convert the value to a float with a decimal
* point, no matter what the locale setting is
*/
public static function float(string|int|float|null $value): string
{
public static function float(
string|int|float|null $value = null
): string {
// make sure $value is not null
$value ??= '';
@@ -459,8 +493,11 @@ class Str
/**
* Returns the rest of the string starting from the given character
*/
public static function from(string $string, string $needle, bool $caseInsensitive = false): string
{
public static function from(
string $string,
string $needle,
bool $caseInsensitive = false
): string {
$position = static::position($string, $needle, $caseInsensitive);
if ($position === false) {
@@ -477,8 +514,11 @@ class Str
* @param string $string The string to increment
* @param int $first Starting number
*/
public static function increment(string $string, string $separator = '-', int $first = 1): string
{
public static function increment(
string $string,
string $separator = '-',
int $first = 1
): string {
preg_match('/(.+)' . preg_quote($separator, '/') . '([0-9]+)$/', $string, $matches);
if (isset($matches[2]) === true) {
@@ -569,8 +609,10 @@ class Str
/**
* Get a character pool with various possible combinations
*/
public static function pool(string|array $type, bool $array = true): string|array
{
public static function pool(
string|array $type,
bool $array = true
): string|array {
$pool = [];
if (is_array($type) === true) {
@@ -597,8 +639,11 @@ class Str
*
* @throws \Kirby\Exception\InvalidArgumentException for empty $needle
*/
public static function position(string $string = null, string $needle, bool $caseInsensitive = false): int|bool
{
public static function position(
string $string = null,
string $needle,
bool $caseInsensitive = false
): int|bool {
if ($needle === '') {
throw new InvalidArgumentException('The needle must not be empty');
}
@@ -626,8 +671,10 @@ class Str
* @param int $length The length of the random string
* @param string $type Pool type (type of allowed characters)
*/
public static function random(int $length = null, string $type = 'alphaNum'): string|false
{
public static function random(
int $length = null,
string $type = 'alphaNum'
): string|false {
$length ??= random_int(5, 10);
$pool = static::pool($type, false);
@@ -665,9 +712,15 @@ class Str
* @return string|array String with replaced values;
* if $string is an array, array of strings
* @psalm-return ($string is array ? array : string)
*
* @todo the types aren't correct, refactor to apply native type hinting
*/
public static function replace($string, $search, $replace, $limit = -1)
{
public static function replace(
$string,
$search,
$replace,
$limit = -1
): string|array {
// convert Kirby collections to arrays
if ($string instanceof Collection) {
$string = $string->toArray();
@@ -720,9 +773,14 @@ class Str
* defaults to no limit
* @return array List of replacement arrays, each with a
* 'search', 'replace' and 'limit' attribute
*
* @todo the types aren't correct, refactor to apply native type hinting
*/
public static function replacements($search, $replace, $limit): array
{
public static function replacements(
$search,
$replace,
$limit
): array {
$replacements = [];
if (is_array($search) === true && is_array($replace) === true) {
@@ -768,18 +826,26 @@ class Str
* @param array $replacements Replacement array from Str::replacements()
* @return string String with replaced values
*/
public static function replaceReplacements(string $string, array $replacements): string
{
public static function replaceReplacements(
string $string,
array $replacements
): string {
// replace in the order of the replacements
// behavior is identical to the official PHP str_replace()
foreach ($replacements as $replacement) {
if (is_int($replacement['limit']) === false) {
throw new Exception('Invalid limit "' . $replacement['limit'] . '".');
} elseif ($replacement['limit'] === -1) {
}
if ($replacement['limit'] === -1) {
// no limit, we don't need our special replacement routine
$string = str_replace($replacement['search'], $replacement['replace'], $string);
$string = str_replace(
$replacement['search'],
$replacement['replace'],
$string
);
} elseif ($replacement['limit'] > 0) {
// limit given, only replace for $replacement['limit'] times per replacement
// limit given, only replace for as many times per replacement
$position = -1;
for ($i = 0; $i < $replacement['limit']; $i++) {
@@ -886,8 +952,11 @@ class Str
* string is too long. Ellipsis is the default.
* @return string The shortened string
*/
public static function short(string $string = null, int $length = 0, string $appendix = '…'): string
{
public static function short(
string $string = null,
int $length = 0,
string $appendix = '…'
): string {
if ($string === null) {
return '';
}
@@ -915,8 +984,11 @@ class Str
* @return array matches: Number of matching chars in both strings
* percent: Similarity in percent
*/
public static function similarity(string $first, string $second, bool $caseInsensitive = false): array
{
public static function similarity(
string $first,
string $second,
bool $caseInsensitive = false
): array {
$matches = 0;
$percent = 0.0;
@@ -1020,11 +1092,14 @@ class Str
/**
* Convert a string to snake case.
*/
public static function snake(string $value = null, string $delimiter = '_'): string
{
if (!ctype_lower($value)) {
public static function snake(
string $value = null,
string $delimiter = '_'
): string {
if (ctype_lower($value) === false) {
$value = preg_replace('/\s+/u', '', ucwords($value));
$value = static::lower(preg_replace('/(.)(?=[A-Z])/u', '$1' . $delimiter, $value));
$value = preg_replace('/(.)(?=[A-Z])/u', '$1' . $delimiter, $value);
$value = static::lower($value);
}
return $value;
}
@@ -1040,8 +1115,11 @@ class Str
* @param int $length The min length of values.
* @return array An array of found values
*/
public static function split(string|array|null $string, string $separator = ',', int $length = 1): array
{
public static function split(
string|array|null $string,
string $separator = ',',
int $length = 1
): array {
if (is_array($string) === true) {
return $string;
}
@@ -1065,8 +1143,11 @@ class Str
/**
* Checks if a string starts with the passed needle
*/
public static function startsWith(string $string = null, string $needle, bool $caseInsensitive = false): bool
{
public static function startsWith(
string $string = null,
string $needle,
bool $caseInsensitive = false
): bool {
if ($needle === '') {
return true;
}
@@ -1088,8 +1169,11 @@ class Str
/**
* A UTF-8 safe version of substr()
*/
public static function substr(string $string = null, int $start = 0, int $length = null): string
{
public static function substr(
string $string = null,
int $start = 0,
int $length = null
): string {
return mb_substr($string ?? '', $start, $length, 'UTF-8');
}
@@ -1149,15 +1233,14 @@ class Str
if ($callback !== null) {
$callbackResult = $callback((string)$result, $query, $data);
if ($result === null && $callbackResult === '') {
if ($result !== null || $callbackResult !== '') {
// the empty string came just from string casting,
// keep the null value and ignore the callback result
} else {
$result = $callbackResult;
}
}
// if we still don't have a result, keep the original placeholder
// wihtout a result, keep the original placeholder
return $result ?? $match[0];
},
$string
@@ -1246,8 +1329,11 @@ class Str
/**
* Returns the beginning of a string until the given character
*/
public static function until(string $string, string $needle, bool $caseInsensitive = false): string
{
public static function until(
string $string,
string $needle,
bool $caseInsensitive = false
): string {
$position = static::position($string, $needle, $caseInsensitive);
if ($position === false) {
@@ -1304,9 +1390,11 @@ class Str
$string ??= '';
// Replace space between last word and punctuation
$string = preg_replace_callback('|(\S)\s(\S?)$|u', function ($matches) {
return $matches[1] . '&nbsp;' . $matches[2];
}, $string);
$string = preg_replace_callback(
'|(\S)\s(\S?)$|u',
fn ($matches) => $matches[1] . '&nbsp;' . $matches[2],
$string
);
// Replace space between last two words
return preg_replace_callback('|(\s)(?=\S*$)(\S+)|u', function ($matches) {
@@ -1325,8 +1413,11 @@ class Str
* @param string $before String to prepend
* @param string|null $after String to append (if different from `$before`)
*/
public static function wrap(string $string, string $before, string $after = null): string
{
public static function wrap(
string $string,
string $before,
string $after = null
): string {
return $before . $string . ($after ?? $before);
}
}

View File

@@ -21,8 +21,10 @@ class Tpl
*
* @throws Throwable
*/
public static function load(string|null $file = null, array $data = []): string
{
public static function load(
string|null $file = null,
array $data = []
): string {
if ($file === null || is_file($file) === false) {
return '';
}
@@ -39,10 +41,10 @@ class Tpl
$content = ob_get_contents();
ob_end_clean();
if ($exception === null) {
return $content;
if ($exception !== null) {
throw $exception;
}
throw $exception;
return $content;
}
}

View File

@@ -32,8 +32,11 @@ class V
* and returns an array with all error messages.
* The array will be empty if the input is valid
*/
public static function errors($input, array $rules, array $messages = []): array
{
public static function errors(
$input,
array $rules,
array $messages = []
): array {
$errors = static::value($input, $rules, $messages, false);
return $errors === true ? [] : $errors;
@@ -44,8 +47,11 @@ class V
* checks if the data is invalid
* @since 3.7.0
*/
public static function invalid(array $data = [], array $rules = [], array $messages = []): array
{
public static function invalid(
array $data = [],
array $rules = [],
array $messages = []
): array {
$errors = [];
foreach ($rules as $field => $validations) {
@@ -108,8 +114,10 @@ class V
* and the arguments. This is used mainly internally
* to create error messages
*/
public static function message(string $validatorName, ...$params): string|null
{
public static function message(
string $validatorName,
...$params
): string|null {
$validatorName = strtolower($validatorName);
$translationKey = 'error.validation.' . $validatorName;
$validators = array_change_key_case(static::$validators);
@@ -157,8 +165,12 @@ class V
* a set of rules, using all registered
* validators
*/
public static function value($value, array $rules, array $messages = [], bool $fail = true): bool|array
{
public static function value(
$value,
array $rules,
array $messages = [],
bool $fail = true
): bool|array {
$errors = [];
foreach ($rules as $validatorName => $validatorOptions) {

View File

@@ -17,23 +17,14 @@ use Throwable;
*/
class View
{
/**
* The absolute path to the view file
*/
protected string $file;
/**
* The view data
*/
protected array $data = [];
/**
* Creates a new view object
*/
public function __construct(string $file, array $data = [])
{
$this->file = $file;
$this->data = $data;
public function __construct(
// The absolute path to the view file
protected string $file,
protected array $data = []
) {
}
/**

View File

@@ -70,8 +70,10 @@ class Xml
* If used with a `$name` array, this can be set to `false` to disable attribute sorting.
* @return string|null The generated XML attributes string
*/
public static function attr(string|array $name, $value = null): string|null
{
public static function attr(
string|array $name,
$value = null
): string|null {
if (is_array($name) === true) {
if ($value !== false) {
ksort($name);
@@ -235,8 +237,10 @@ class Xml
*
* @param bool $html True = Convert to HTML-safe first
*/
public static function encode(string|null $string, bool $html = true): string
{
public static function encode(
string|null $string,
bool $html = true
): string {
if ($string === null) {
return '';
}
@@ -282,8 +286,10 @@ class Xml
*
* @param bool $collectName Whether the element name should be collected (for the root element)
*/
public static function simplify(SimpleXMLElement $element, bool $collectName = true): array|string
{
public static function simplify(
SimpleXMLElement $element,
bool $collectName = true
): array|string {
// get all XML namespaces of the whole document to iterate over later;
// we don't need the global namespace (empty string) in the list
$usedNamespaces = $element->getNamespaces(true);
@@ -347,18 +353,18 @@ class Xml
}
}
return $array;
} else {
// we didn't find any XML children above, only use the string value
$element = (string)$element;
if (count($array) === 0) {
return $element;
}
$array['@value'] = $element;
return $array;
}
// we didn't find any XML children above, only use the string value
$element = (string)$element;
if (count($array) === 0) {
return $element;
}
$array['@value'] = $element;
return $array;
}
/**
@@ -372,8 +378,13 @@ class Xml
* @param int $level Indentation level
* @return string The generated XML
*/
public static function tag(string $name, $content = '', array $attr = [], string $indent = null, int $level = 0): string
{
public static function tag(
string $name,
array|string|null $content = '',
array $attr = [],
string $indent = null,
int $level = 0
): string {
$attr = static::attr($attr);
$start = '<' . $name . ($attr ? ' ' . $attr : '') . '>';
$startShort = '<' . $name . ($attr ? ' ' . $attr : '') . static::$void;