composer update

This commit is contained in:
isUnknown 2025-09-23 08:15:07 +02:00
parent 0b3c362c5e
commit a1f0701630
142 changed files with 4530 additions and 1195 deletions

View file

@ -222,7 +222,6 @@ class Cookie
protected static function trackUsage(string $key): void
{
// lazily request the instance for non-CMS use cases
$kirby = App::instance(null, true);
$kirby?->response()->usesCookie($key);
App::instance(lazy: true)?->response()->usesCookie($key);
}
}

View file

@ -13,13 +13,13 @@ use Kirby\Toolkit\Str;
* secure host and base URL detection, as
* well as loading the dedicated
* environment options.
* @since 3.7.0
*
* @package Kirby Http
* @author Bastian Allgeier <bastian@getkirby.com>
* @link https://getkirby.com
* @copyright Bastian Allgeier
* @license https://opensource.org/licenses/MIT
* @since 3.7.0
*/
class Environment
{

View file

@ -68,7 +68,7 @@ class Header
$header = 'Content-type: ' . $mime;
if (empty($charset) === false) {
if ($charset !== '') {
$header .= '; charset=' . $charset;
}

View file

@ -38,7 +38,7 @@ class Params extends Obj implements Stringable
*/
public static function extract(string|array|null $path = null): array
{
if (empty($path) === true) {
if ($path === null || $path === '' || $path === []) {
return [
'path' => null,
'params' => null,
@ -62,12 +62,16 @@ class Params extends Obj implements Stringable
continue;
}
$paramParts = Str::split($p, $separator);
$paramKey = $paramParts[0] ?? null;
$paramValue = $paramParts[1] ?? null;
$parts = Str::split($p, $separator);
if ($paramKey !== null) {
$params[rawurldecode($paramKey)] = $paramValue !== null ? rawurldecode($paramValue) : null;
if ($key = $parts[0] ?? null) {
$key = rawurldecode($key);
if ($value = $parts[1] ?? null) {
$value = rawurldecode($value);
}
$params[$key] = $value;
}
unset($path[$index]);
@ -89,7 +93,7 @@ class Params extends Obj implements Stringable
public function isEmpty(): bool
{
return empty((array)$this) === true;
return (array)$this === [];
}
public function isNotEmpty(): bool
@ -97,6 +101,23 @@ class Params extends Obj implements Stringable
return $this->isEmpty() === false;
}
/**
* Merges the current params with the given params
* @since 5.1.0
*
* @return $this
*/
public function merge(array|string|null $params): static
{
$params = new static($params);
foreach ($params as $key => $value) {
$this->$key = $value;
}
return $this;
}
/**
* Returns the param separator according
* to the operating system.
@ -106,15 +127,7 @@ class Params extends Obj implements Stringable
*/
public static function separator(): string
{
if (static::$separator !== null) {
return static::$separator;
}
if (DIRECTORY_SEPARATOR === '/') {
return static::$separator = ':';
}
return static::$separator = ';';
return static::$separator ??= DIRECTORY_SEPARATOR === '/' ? ':' : ';';
}
/**
@ -134,7 +147,9 @@ class Params extends Obj implements Stringable
foreach ($this as $key => $value) {
if ($value !== null && $value !== '') {
$params[] = rawurlencode($key) . $separator . rawurlencode($value);
$key = rawurlencode($key);
$value = rawurlencode($value);
$params[] = $key . $separator . $value;
}
}

View file

@ -29,7 +29,7 @@ class Query extends Obj implements Stringable
public function isEmpty(): bool
{
return empty((array)$this) === true;
return (array)$this === [];
}
public function isNotEmpty(): bool
@ -37,11 +37,28 @@ class Query extends Obj implements Stringable
return $this->isEmpty() === false;
}
/**
* Merges the current query with the given query
* @since 5.1.0
*
* @return $this
*/
public function merge(string|array|null $query): static
{
$query = new static($query);
foreach ($query as $key => $value) {
$this->$key = $value;
}
return $this;
}
public function toString(bool $questionMark = false): string
{
$query = http_build_query($this, '', '&', PHP_QUERY_RFC3986);
if (empty($query) === true) {
if ($query === '') {
return '';
}

View file

@ -47,13 +47,14 @@ class Remote
public string $errorMessage;
public array $headers = [];
public array $info = [];
public array $options = [];
/**
* @throws \Exception when the curl request failed
*/
public function __construct(string $url, array $options = [])
{
public function __construct(
string $url,
public array $options = []
) {
$defaults = static::$defaults;
// use the system CA store by default if
@ -71,11 +72,8 @@ class Remote
$defaults = [...$defaults, ...$app->option('remote', [])];
}
// set all options
$this->options = [...$defaults, ...$options];
// add the url
$this->options['url'] = $url;
// set all options, incl. url
$this->options = [...$defaults, ...$options, 'url' => $url];
// send the request
$this->fetch();
@ -277,7 +275,7 @@ class Remote
$query = http_build_query($options['data']);
if (empty($query) === false) {
if ($query !== '') {
$url = match (Url::hasQuery($url)) {
true => $url . '&' . $query,
default => $url . '?' . $query
@ -339,7 +337,7 @@ class Remote
*/
protected function postfields($data)
{
if (is_object($data) || is_array($data)) {
if (is_object($data) === true || is_array($data) === true) {
return http_build_query($data);
}

View file

@ -67,12 +67,6 @@ class Request
*/
protected string $method;
/**
* All options that have been passed to
* the request in the constructor
*/
protected array $options;
/**
* The Query object is a wrapper around
* the URL query string, which parses the
@ -96,9 +90,9 @@ class Request
* data via the $options array or use
* the data from the incoming request.
*/
public function __construct(array $options = [])
{
$this->options = $options;
public function __construct(
protected array $options = []
) {
$this->method = $this->detectRequestMethod($options['method'] ?? null);
if (isset($options['body']) === true) {
@ -155,7 +149,7 @@ class Request
}
// lazily request the instance for non-CMS use cases
$kirby = App::instance(null, true);
$kirby = App::instance(lazy: true);
// tell the CMS responder that the response relies on
// the `Authorization` header and its value (even if
@ -224,13 +218,26 @@ class Request
public function detectRequestMethod(string|null $method = null): string
{
// all possible methods
$methods = ['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'CONNECT', 'OPTIONS', 'TRACE', 'PATCH'];
$methods = [
'CONNECT',
'DELETE',
'GET',
'HEAD',
'OPTIONS',
'PATCH',
'POST',
'PUT',
'TRACE',
];
// the request method can be overwritten with a header
$methodOverride = strtoupper(Environment::getGlobally('HTTP_X_HTTP_METHOD_OVERRIDE', ''));
if ($method === null) {
$override = Environment::getGlobally('HTTP_X_HTTP_METHOD_OVERRIDE', '');
$override = strtoupper($override);
if (in_array($methodOverride, $methods, true) === true) {
$method ??= $methodOverride;
if (in_array($override, $methods, true) === true) {
$method = $override;
}
}
// final chain of options to detect the method
@ -410,14 +417,15 @@ class Request
// both variants need to be checked separately
// because empty strings are treated as invalid
// but the `??` operator wouldn't do the fallback
$option = $this->options['auth'] ?? null;
if (empty($option) === false) {
if (is_string($option) === true && $option !== '') {
return $option;
}
$header = $this->header('authorization');
if (empty($header) === false) {
if (is_string($header) === true && $header !== '') {
return $header;
}

View file

@ -20,11 +20,6 @@ class Body implements Stringable
{
use Data;
/**
* The raw body content
*/
protected string|array|null $contents;
/**
* The parsed content as array
*/
@ -36,10 +31,12 @@ class Body implements Stringable
* If null is being passed, the class will
* fetch the body either from the $_POST global
* or from php://input.
*
* @param array|string|null $contents The raw body content
*/
public function __construct(array|string|null $contents = null)
{
$this->contents = $contents;
public function __construct(
protected array|string|null $contents = null
) {
}
/**
@ -52,7 +49,7 @@ class Body implements Stringable
return $this->contents;
}
if (empty($_POST) === false) {
if ($_POST !== []) {
return $this->contents = $_POST;
}
@ -90,7 +87,7 @@ class Body implements Stringable
// try to parse the body as query string
parse_str($contents, $parsed);
if (is_array($parsed)) {
if (is_array($parsed) === true) {
return $this->data = $parsed;
}
}

View file

@ -45,9 +45,11 @@ trait Data
{
if (is_array($key) === true) {
$result = [];
foreach ($key as $k) {
$result[$k] = $this->get($k);
}
return $result;
}

View file

@ -34,7 +34,7 @@ class Files
$files ??= $_FILES;
foreach ($files as $key => $file) {
if (is_array($file['name'])) {
if (is_array($file['name']) === true) {
foreach ($file['name'] as $i => $name) {
$this->files[$key][] = [
'name' => $file['name'][$i] ?? null,

View file

@ -22,7 +22,7 @@ class Query implements Stringable
/**
* The Query data array
*/
protected array|null $data = null;
protected array $data;
/**
* Creates a new Query object.
@ -56,7 +56,7 @@ class Query implements Stringable
*/
public function isEmpty(): bool
{
return empty($this->data) === true;
return $this->data === [];
}
/**
@ -64,7 +64,7 @@ class Query implements Stringable
*/
public function isNotEmpty(): bool
{
return empty($this->data) === false;
return $this->data !== [];
}
/**

View file

@ -281,8 +281,11 @@ class Response implements Stringable
*
* @since 5.0.3
*/
public static function refresh(string $location = '/', int $code = 302, int $refresh = 0): static
{
public static function refresh(
string $location = '/',
int $code = 302,
int $refresh = 0
): static {
return new static([
'code' => $code,
'headers' => [
@ -312,6 +315,19 @@ class Response implements Stringable
return $this->body();
}
/**
* Sets the provided headers in case they are not already set
* @internal
* @return $this
*/
public function setHeaderFallbacks(array $headers): static
{
// the case-insensitive nature of headers will be
// handled by PHP's `header()` functions
$this->headers = [...$headers, ...$this->headers];
return $this;
}
/**
* Converts all relevant response attributes
* to an associative array for debugging,

View file

@ -13,26 +13,11 @@ use Closure;
*/
class Route
{
/**
* The callback action function
*/
protected Closure $action;
/**
* Listed of parsed arguments
*/
protected array $arguments = [];
/**
* An array of all passed attributes
*/
protected array $attributes = [];
/**
* The registered request method
*/
protected string $method;
/**
* The registered pattern
*/
@ -74,14 +59,11 @@ class Route
*/
public function __construct(
string $pattern,
string $method,
Closure $action,
array $attributes = []
protected string $method,
protected Closure $action,
protected array $attributes = []
) {
$this->action = $action;
$this->attributes = $attributes;
$this->method = $method;
$this->pattern = $this->regex(ltrim($pattern, '/'));
$this->pattern = $this->regex(ltrim($pattern, '/'));
}
/**

View file

@ -158,6 +158,9 @@ class Router
* The Route's arguments method is used to
* find matches and return all the found
* arguments in the path.
*
* @param array|null $ignore (Passing null has been deprecated)
* @todo Remove support for `$ignore = null` in v6
*/
public function find(
string $path,
@ -172,16 +175,14 @@ class Router
}
// remove leading and trailing slashes
$path = trim($path, '/');
$path = trim($path, '/');
$ignore ??= [];
foreach ($this->routes[$method] as $route) {
$arguments = $route->parse($route->pattern(), $path);
if ($arguments !== false) {
if (
empty($ignore) === true ||
in_array($route, $ignore, true) === false
) {
if (in_array($route, $ignore, true) === false) {
return $this->route = $route;
}
}

View file

@ -216,10 +216,10 @@ class Uri implements Stringable
if ($app = App::instance(null, true)) {
$environment = $app->environment();
} else {
$environment = new Environment();
}
$environment ??= new Environment();
return new static($environment->requestUrl(), $props);
}
@ -230,7 +230,7 @@ class Uri implements Stringable
*/
public function domain(): string|null
{
if (empty($this->host) === true || $this->host === '/') {
if ($this->host === null || $this->host === '' || $this->host === '/') {
return null;
}
@ -255,7 +255,7 @@ class Uri implements Stringable
public function hasFragment(): bool
{
return empty($this->fragment) === false;
return $this->fragment !== null && $this->fragment !== '';
}
public function hasPath(): bool
@ -281,8 +281,9 @@ class Uri implements Stringable
*/
public function idn(): static
{
if (empty($this->host) === false) {
$this->setHost(Idn::decode($this->host));
if ($this->isAbsolute() === true) {
$host = Idn::decode($this->host);
$this->setHost($host);
}
return $this;
}
@ -295,10 +296,10 @@ class Uri implements Stringable
{
if ($app = App::instance(null, true)) {
$url = $app->url('index');
} else {
$url = (new Environment())->baseUrl();
}
$url ??= (new Environment())->baseUrl();
return new static($url, $props);
}
@ -307,7 +308,16 @@ class Uri implements Stringable
*/
public function isAbsolute(): bool
{
return empty($this->host) === false;
return $this->host !== null && $this->host !== '';
}
/**
* Returns the fragment after the hash
* @since 5.1.0
*/
public function fragment(): string|null
{
return $this->fragment;
}
/**
@ -465,7 +475,7 @@ class Uri implements Stringable
$url = $this->base();
$slash = true;
if (empty($url) === true) {
if ($url === null || $url === '') {
$url = '/';
$slash = false;
}
@ -479,8 +489,8 @@ class Uri implements Stringable
$url .= $path;
$url .= $this->query->toString(true);
if (empty($this->fragment) === false) {
$url .= '#' . $this->fragment;
if ($this->hasFragment() === true) {
$url .= '#' . $this->fragment();
}
return $url;
@ -494,8 +504,9 @@ class Uri implements Stringable
*/
public function unIdn(): static
{
if (empty($this->host) === false) {
$this->setHost(Idn::encode($this->host));
if ($this->isAbsolute() === true) {
$host = Idn::encode($this->host);
$this->setHost($host);
}
return $this;
}

View file

@ -110,8 +110,10 @@ class Url
/**
* Convert a relative path into an absolute URL
*/
public static function makeAbsolute(string|null $path = null, string|null $home = null): string
{
public static function makeAbsolute(
string|null $path = null,
string|null $home = null
): string {
if ($path === '' || $path === '/' || $path === null) {
return $home ?? static::home();
}
@ -120,7 +122,7 @@ class Url
return $path;
}
if (static::isAbsolute($path)) {
if (static::isAbsolute($path) === true) {
return $path;
}
@ -128,11 +130,15 @@ class Url
$path = ltrim($path, '/');
$home ??= static::home();
if (empty($path) === true) {
if ($path === '') {
return $home;
}
return $home === '/' ? '/' . $path : $home . '/' . $path;
if ($home === '/') {
return '/' . $path;
}
return $home . '/' . $path;
}
/**

View file

@ -165,16 +165,16 @@ class Visitor
*/
public function preferredMimeType(string ...$mimeTypes): string|null
{
foreach ($this->acceptedMimeTypes() as $acceptedMime) {
foreach ($this->acceptedMimeTypes() as $accepted) {
// look for direct matches
if (in_array($acceptedMime->type(), $mimeTypes, true)) {
return $acceptedMime->type();
if (in_array($accepted->type(), $mimeTypes, true) === true) {
return $accepted->type();
}
// test each option against wildcard `Accept` values
foreach ($mimeTypes as $expectedMime) {
if (Mime::matches($expectedMime, $acceptedMime->type()) === true) {
return $expectedMime;
foreach ($mimeTypes as $expected) {
if (Mime::matches($expected, $accepted->type()) === true) {
return $expected;
}
}
}