Upgrade to 4.6.0

This commit is contained in:
Bastian Allgeier
2025-01-30 12:15:44 +01:00
parent d71db84033
commit daf499e2e4
179 changed files with 1848 additions and 688 deletions

View File

@@ -285,7 +285,7 @@ class App
*
* @return $this
*/
protected function bakeRoots(array $roots = null): static
protected function bakeRoots(array|null $roots = null): static
{
$roots = array_merge($this->core->roots(), (array)$roots);
$this->roots = Ingredients::bake($roots);
@@ -297,7 +297,7 @@ class App
*
* @return $this
*/
protected function bakeUrls(array $urls = null): static
protected function bakeUrls(array|null $urls = null): static
{
$urls = array_merge($this->core->urls(), (array)$urls);
$this->urls = Ingredients::bake($urls);
@@ -331,7 +331,7 @@ class App
/**
* Calls any Kirby route
*/
public function call(string $path = null, string $method = null): mixed
public function call(string|null $path = null, string|null $method = null): mixed
{
$path ??= $this->path();
$method ??= $this->request()->method();
@@ -697,7 +697,7 @@ class App
* @psalm-return ($lazy is false ? static : static|null)
*/
public static function instance(
self $instance = null,
self|null $instance = null,
bool $lazy = false
): static|null {
if ($instance !== null) {
@@ -852,7 +852,7 @@ class App
*
* @internal
*/
public function kirbytags(string $text = null, array $data = []): string
public function kirbytags(string|null $text = null, array $data = []): string
{
$data['kirby'] ??= $this;
$data['site'] ??= $data['kirby']->site();
@@ -872,7 +872,7 @@ class App
*
* @internal
*/
public function kirbytext(string $text = null, array $options = []): string
public function kirbytext(string|null $text = null, array $options = []): string
{
$text = $this->apply('kirbytext:before', compact('text'), 'text');
$text = $this->kirbytags($text, $options);
@@ -891,7 +891,7 @@ class App
* Returns the language by code or shortcut (`default`, `current`).
* Passing `null` is an alias for passing `current`
*/
public function language(string $code = null): Language|null
public function language(string|null $code = null): Language|null
{
if ($this->multilang() === false) {
return null;
@@ -909,7 +909,7 @@ class App
*
* @internal
*/
public function languageCode(string $languageCode = null): string|null
public function languageCode(string|null $languageCode = null): string|null
{
return $this->language($languageCode)?->code();
}
@@ -952,7 +952,7 @@ class App
*
* @internal
*/
public function markdown(string $text = null, array $options = null): string
public function markdown(string|null $text = null, array|null $options = null): string
{
// merge global options with local options
$options = array_merge(
@@ -1181,8 +1181,8 @@ class App
* current request
*/
public function render(
string $path = null,
string $method = null
string|null $path = null,
string|null $method = null
): Response|null {
if (($_ENV['KIRBY_RENDER'] ?? true) === false) {
return null;
@@ -1441,7 +1441,7 @@ class App
*
* @return $this
*/
protected function setLanguages(array $languages = null): static
protected function setLanguages(array|null $languages = null): static
{
if ($languages !== null) {
$objects = [];
@@ -1462,7 +1462,7 @@ class App
*
* @return $this
*/
protected function setPath(string $path = null): static
protected function setPath(string|null $path = null): static
{
$this->path = $path !== null ? trim($path, '/') : null;
return $this;
@@ -1473,7 +1473,7 @@ class App
*
* @return $this
*/
protected function setRequest(array $request = null): static
protected function setRequest(array|null $request = null): static
{
if ($request !== null) {
$this->request = new Request($request);
@@ -1487,7 +1487,7 @@ class App
*
* @return $this
*/
protected function setRoles(array $roles = null): static
protected function setRoles(array|null $roles = null): static
{
if ($roles !== null) {
$this->roles = Roles::factory($roles);
@@ -1501,7 +1501,7 @@ class App
*
* @return $this
*/
protected function setSite(Site|array $site = null): static
protected function setSite(Site|array|null $site = null): static
{
if (is_array($site) === true) {
$site = new Site($site);
@@ -1528,7 +1528,7 @@ class App
*
* @internal
*/
public function smartypants(string $text = null): string
public function smartypants(string|null $text = null): string
{
$options = $this->option('smartypants', []);

View File

@@ -99,7 +99,7 @@ trait AppPlugins
*/
public function extend(
array $extensions,
Plugin $plugin = null
Plugin|null $plugin = null
): array {
foreach ($this->extensions as $type => $registered) {
if (isset($extensions[$type]) === true) {
@@ -382,7 +382,7 @@ trait AppPlugins
*/
protected function extendOptions(
array $options,
Plugin $plugin = null
Plugin|null $plugin = null
): array {
if ($plugin !== null) {
$options = [$plugin->prefix() => $options];
@@ -428,7 +428,7 @@ trait AppPlugins
*/
protected function extendPermissions(
array $permissions,
Plugin $plugin = null
Plugin|null $plugin = null
): array {
if ($plugin !== null) {
$permissions = [$plugin->prefix() => $permissions];
@@ -583,7 +583,7 @@ trait AppPlugins
*
* @internal
*/
public function extensions(string $type = null): array
public function extensions(string|null $type = null): array
{
if ($type === null) {
return $this->extensions;
@@ -713,7 +713,7 @@ trait AppPlugins
*/
public static function plugin(
string $name,
array $extends = null,
array|null $extends = null,
array $info = [],
string|null $root = null,
string|null $version = null
@@ -747,7 +747,7 @@ trait AppPlugins
* @internal
* @param array|null $plugins Can be used to overwrite the plugins registry
*/
public function plugins(array $plugins = null): array
public function plugins(array|null $plugins = null): array
{
// overwrite the existing plugins registry
if ($plugins !== null) {

View File

@@ -108,7 +108,7 @@ trait AppTranslations
*
* @internal
*/
public function setCurrentTranslation(string $translationCode = null): void
public function setCurrentTranslation(string|null $translationCode = null): void
{
I18n::$locale = $translationCode ?? 'en';
}

View File

@@ -72,7 +72,7 @@ trait AppUsers
*
* @return $this
*/
protected function setUser(User|string $user = null): static
protected function setUser(User|string|null $user = null): static
{
$this->user = $user;
return $this;
@@ -83,7 +83,7 @@ trait AppUsers
*
* @return $this
*/
protected function setUsers(array $users = null): static
protected function setUsers(array|null $users = null): static
{
if ($users !== null) {
$this->users = Users::factory($users);

View File

@@ -202,7 +202,7 @@ class Auth
* @throws \Kirby\Exception\InvalidArgumentException if the authorization header is invalid
* @throws \Kirby\Exception\PermissionException if basic authentication is not allowed
*/
public function currentUserFromBasicAuth(BasicAuth $auth = null): User|null
public function currentUserFromBasicAuth(BasicAuth|null $auth = null): User|null
{
if ($this->kirby->option('api.basicAuth', false) !== true) {
throw new PermissionException('Basic authentication is not activated');
@@ -250,7 +250,7 @@ class Auth
* valid user id in there
*/
public function currentUserFromSession(
Session|array $session = null
Session|array|null $session = null
): User|null {
$session = $this->session($session);
@@ -440,7 +440,7 @@ class Auth
* logged in user will be returned
*/
public function status(
Session|array $session = null,
Session|array|null $session = null,
bool $allowImpersonation = true
): Status {
// try to return from cache
@@ -723,7 +723,7 @@ class Auth
* @throws \Throwable If an authentication error occurred
*/
public function user(
Session|array $session = null,
Session|array|null $session = null,
bool $allowImpersonation = true
): User|null {
if ($allowImpersonation === true && $this->impersonate !== null) {
@@ -887,7 +887,7 @@ class Auth
*/
protected function fail(
Throwable $exception,
Throwable $fallback = null
Throwable|null $fallback = null
): void {
$debug = $this->kirby->option('auth.debug', 'log');
@@ -911,7 +911,7 @@ class Auth
/**
* Creates a session object from the passed options
*/
protected function session(Session|array $session = null): Session
protected function session(Session|array|null $session = null): Session
{
// use passed session options or session object if set
if (is_array($session) === true) {

View File

@@ -54,7 +54,7 @@ class Blocks extends Items
* catch blocks from layouts
*/
public static function factory(
array $items = null,
array|null $items = null,
array $params = []
): static {
$items = static::extractFromLayouts($items);

View File

@@ -39,7 +39,7 @@ class Blueprint
/**
* Magic getter/caller for any blueprint prop
*/
public function __call(string $key, array $arguments = null): mixed
public function __call(string $key, array|null $arguments = null): mixed
{
return $this->props[$key] ?? null;
}
@@ -102,7 +102,7 @@ class Blueprint
* Gathers what file templates are allowed in
* this model based on the blueprint
*/
public function acceptedFileTemplates(string $inSection = null): array
public function acceptedFileTemplates(string|null $inSection = null): array
{
// get cached results for the current file model
// (except when collecting for a specific section)
@@ -320,7 +320,7 @@ class Blueprint
*/
public static function factory(
string $name,
string $fallback = null,
string|null $fallback,
ModelWithContent $model
): static|null {
try {

View File

@@ -365,7 +365,7 @@ class Collection extends BaseCollection
* Searches the collection
*/
public function search(
string $query = null,
string|null $query = null,
string|array $params = []
): static {
return Search::collection($this, $query, $params);
@@ -376,7 +376,7 @@ class Collection extends BaseCollection
* to an array. This can also take a callback
* function to further modify the array result.
*/
public function toArray(Closure $map = null): array
public function toArray(Closure|null $map = null): array
{
return parent::toArray($map ?? fn ($object) => $object->toArray());
}

View File

@@ -173,7 +173,7 @@ class ContentLocks
) {
unset($this->data[$file][$id]);
// there is empty unlock data, but still lock data
// there is empty unlock data, but still lock data
} elseif (
isset($data['unlock']) === true &&
count($data['unlock']) === 0

View File

@@ -113,7 +113,7 @@ class Email
$this->props['body']['text'] = $text->render($data);
}
// fallback to single email text template
// fallback to single email text template
} elseif ($text->exists()) {
$this->props['body'] = $text->render($data);
} else {
@@ -125,7 +125,7 @@ class Email
/**
* Returns an email template by name and type
*/
protected function getTemplate(string $name, string $type = null): Template
protected function getTemplate(string $name, string|null $type = null): Template
{
return App::instance()->template('emails/' . $name, $type, 'text');
}
@@ -163,7 +163,7 @@ class Email
string $prop,
string $class,
string $contentValue,
string $contentKey = null
string|null $contentKey = null
): array {
$value = $this->props[$prop] ?? [];

View File

@@ -74,7 +74,7 @@ class Fieldsets extends Items
}
public static function factory(
array $items = null,
array|null $items = null,
array $params = []
): static {
$items ??= App::instance()->option('blocks.fieldsets', [

View File

@@ -155,7 +155,7 @@ class File extends ModelWithContent
* Returns an array with all blueprints that are available for the file
* by comparing files sections and files fields of the parent model
*/
public function blueprints(string $inSection = null): array
public function blueprints(string|null $inSection = null): array
{
// get cached results for the current file model
// (except when collecting for a specific section)
@@ -227,7 +227,7 @@ class File extends ModelWithContent
*/
public function contentFileData(
array $data,
string $languageCode = null
string|null $languageCode = null
): array {
// only add the template in, if the $data array
// doesn't explicitly unsets it
@@ -443,7 +443,7 @@ class File extends ModelWithContent
* Timestamp of the last modification
* of the content file
*/
protected function modifiedContent(string $languageCode = null): int
protected function modifiedContent(string|null $languageCode = null): int
{
return $this->storage()->modified('published', $languageCode) ?? 0;
}
@@ -548,7 +548,7 @@ class File extends ModelWithContent
*
* @return $this
*/
protected function setBlueprint(array $blueprint = null): static
protected function setBlueprint(array|null $blueprint = null): static
{
if ($blueprint !== null) {
$blueprint['model'] = $this;

View File

@@ -404,8 +404,8 @@ trait FileActions
* @internal
*/
public function save(
array $data = null,
string $languageCode = null,
array|null $data = null,
string|null $languageCode = null,
bool $overwrite = false
): static {
$file = parent::save($data, $languageCode, $overwrite);
@@ -444,8 +444,8 @@ trait FileActions
* @throws \Kirby\Exception\InvalidArgumentException If the input array contains invalid values
*/
public function update(
array $input = null,
string $languageCode = null,
array|null $input = null,
string|null $languageCode = null,
bool $validate = false
): static {
// delete all public media versions when focus field gets changed

View File

@@ -38,7 +38,7 @@ trait FileModifications
*/
public function crop(
int $width,
int $height = null,
int|null $height = null,
$options = null
): FileVersion|File|Asset {
$quality = null;
@@ -94,9 +94,9 @@ trait FileModifications
* @throws \Kirby\Exception\InvalidArgumentException
*/
public function resize(
int $width = null,
int $height = null,
int $quality = null
int|null $width = null,
int|null $height = null,
int|null $quality = null
): FileVersion|File|Asset {
return $this->thumb([
'width' => $width,

View File

@@ -252,7 +252,7 @@ class FileRules
* Validates the extension, MIME type and filename
*
* @param $mime If not passed, the MIME type is detected from the file,
* if `false`, the MIME type is not validated for performance reasons
* if `false`, the MIME type is not validated for performance reasons
* @throws \Kirby\Exception\InvalidArgumentException If the extension, MIME type or filename is missing or forbidden
*/
public static function validFile(
@@ -312,7 +312,7 @@ class FileRules
*
* @throws \Kirby\Exception\InvalidArgumentException If the MIME type is missing or forbidden
*/
public static function validMime(File $file, string $mime = null): bool
public static function validMime(File $file, string|null $mime = null): bool
{
// make it easier to compare the mime
$mime = strtolower($mime ?? '');

View File

@@ -44,19 +44,19 @@ class Files extends Collection
if ($object instanceof self) {
$this->data = array_merge($this->data, $object->data);
// add a file by id
// add a file by id
} elseif (
is_string($object) === true &&
$file = App::instance()->file($object)
) {
$this->__set($file->id(), $file);
// add a file object
// add a file object
} elseif ($object instanceof File) {
$this->__set($object->id(), $object);
// give a useful error message on invalid input;
// silently ignore "empty" values for compatibility with existing setups
// give a useful error message on invalid input;
// silently ignore "empty" values for compatibility with existing setups
} elseif (in_array($object, [null, false, true], true) !== true) {
throw new InvalidArgumentException('You must pass a Files or File object or an ID of an existing file to the Files collection');
}

View File

@@ -142,7 +142,7 @@ class Find
* @param string|null $id User's id
* @throws \Kirby\Exception\NotFoundException if the user for the given id cannot be found
*/
public static function user(string $id = null): User|null
public static function user(string|null $id = null): User|null
{
// account is a reserved word to find the current
// user. It's used in various API and area routes.

View File

@@ -176,7 +176,7 @@ trait HasChildren
*
* @return $this
*/
protected function setChildren(array $children = null): static
protected function setChildren(array|null $children = null): static
{
if ($children !== null) {
$this->children = Pages::factory($children, $this);
@@ -190,7 +190,7 @@ trait HasChildren
*
* @return $this
*/
protected function setDrafts(array $drafts = null): static
protected function setDrafts(array|null $drafts = null): static
{
if ($drafts !== null) {
$this->drafts = Pages::factory($drafts, $this, true);

View File

@@ -63,7 +63,7 @@ trait HasFiles
* Returns a specific file by filename or the first one
*/
public function file(
string $filename = null,
string|null $filename = null,
string $in = 'files'
): File|null {
if ($filename === null) {
@@ -152,7 +152,7 @@ trait HasFiles
/**
* Returns a specific image by filename or the first one
*/
public function image(string $filename = null): File|null
public function image(string|null $filename = null): File|null
{
return $this->file($filename, 'images');
}
@@ -170,7 +170,7 @@ trait HasFiles
*
* @return $this
*/
protected function setFiles(array $files = null): static
protected function setFiles(array|null $files = null): static
{
if ($files !== null) {
$this->files = Files::factory($files, $this);

View File

@@ -81,7 +81,7 @@ class Html extends \Kirby\Toolkit\Html
*/
public static function link(
string|null $href = null,
string|array $text = null,
string|array|null $text = null,
array $attr = []
): string {
return parent::link(Url::to($href), $text, $attr);

View File

@@ -34,7 +34,7 @@ class Ingredients
/**
* Magic getter for single ingredients
*/
public function __call(string $method, array $args = null): mixed
public function __call(string $method, array|null $args = null): mixed
{
return $this->ingredients[$method] ?? null;
}

View File

@@ -48,7 +48,7 @@ class Items extends Collection
* an array of item props
*/
public static function factory(
array $items = null,
array|null $items = null,
array $params = []
): static {
if (empty($items) === true || is_array($items) === false) {
@@ -93,7 +93,7 @@ class Items extends Collection
/**
* Convert the items to an array
*/
public function toArray(Closure $map = null): array
public function toArray(Closure|null $map = null): array
{
return array_values(parent::toArray($map));
}

View File

@@ -344,7 +344,7 @@ class Language
*
* @param int $category If passed, returns the locale for the specified category (e.g. LC_ALL) as string
*/
public function locale(int $category = null): array|string|null
public function locale(int|null $category = null): array|string|null
{
if ($category !== null) {
return $this->locale[$category] ?? $this->locale[LC_ALL] ?? null;
@@ -513,7 +513,7 @@ class Language
* Update language properties and save them
* @internal
*/
public function update(array $props = null): static
public function update(array|null $props = null): static
{
$kirby = App::instance();
$user = $kirby->user();

View File

@@ -26,7 +26,7 @@ class Layouts extends Items
public static array $methods = [];
public static function factory(
array $items = null,
array|null $items = null,
array $params = []
): static {
// convert single layout to layouts array

View File

@@ -27,7 +27,7 @@ class Media
* and to copy it to the media folder.
*/
public static function link(
Page|Site|User $model = null,
Page|Site|User|null $model,
string $hash,
string $filename
): Response|false {

View File

@@ -86,7 +86,7 @@ abstract class Model
* @param \Kirby\Cms\App|null $kirby
* @return $this
*/
protected function setKirby(App $kirby = null)
protected function setKirby(App|null $kirby = null)
{
static::$kirby = $kirby;
return $this;
@@ -99,7 +99,7 @@ abstract class Model
* @param \Kirby\Cms\Site|null $site
* @return $this
*/
public function setSite(Site $site = null)
public function setSite(Site|null $site = null)
{
$this->site = $site;
return $this;

View File

@@ -71,7 +71,7 @@ abstract class ModelWithContent implements Identifiable
/**
* Returns an array with all blueprints that are available
*/
public function blueprints(string $inSection = null): array
public function blueprints(string|null $inSection = null): array
{
// helper function
$toBlueprints = function (array $sections): array {
@@ -176,7 +176,7 @@ abstract class ModelWithContent implements Identifiable
* @throws \Kirby\Exception\InvalidArgumentException If the language for the given code does not exist
*/
public function contentFile(
string $languageCode = null,
string|null $languageCode = null,
bool $force = false
): string {
Helpers::deprecated('The internal $model->contentFile() method has been deprecated. You can use $model->storage()->contentFile() instead, however please note that this method is also internal and may be removed in the future.', 'model-content-file');
@@ -212,7 +212,7 @@ abstract class ModelWithContent implements Identifiable
*/
public function contentFileData(
array $data,
string $languageCode = null
string|null $languageCode = null
): array {
return $data;
}
@@ -371,7 +371,7 @@ abstract class ModelWithContent implements Identifiable
public function increment(
string $field,
int $by = 1,
int $max = null
int|null $max = null
): static {
$value = (int)$this->content()->get($field)->value() + $by;
@@ -462,8 +462,8 @@ abstract class ModelWithContent implements Identifiable
* @internal
*/
public function query(
string $query = null,
string $expect = null
string|null $query = null,
string|null $expect = null
): mixed {
if ($query === null) {
return null;
@@ -491,7 +491,7 @@ abstract class ModelWithContent implements Identifiable
* Read the content from the content file
* @internal
*/
public function readContent(string $languageCode = null): array
public function readContent(string|null $languageCode = null): array
{
try {
return $this->storage()->read(
@@ -531,7 +531,7 @@ abstract class ModelWithContent implements Identifiable
* Save the single language content
*/
protected function saveContent(
array $data = null,
array|null $data = null,
bool $overwrite = false
): static {
// create a clone to avoid modifying the original
@@ -552,8 +552,8 @@ abstract class ModelWithContent implements Identifiable
* @throws \Kirby\Exception\InvalidArgumentException If the language for the given code does not exist
*/
protected function saveTranslation(
array $data = null,
string $languageCode = null,
array|null $data = null,
string|null $languageCode = null,
bool $overwrite = false
): static {
// create a clone to not touch the original
@@ -603,7 +603,7 @@ abstract class ModelWithContent implements Identifiable
*
* @return $this
*/
protected function setContent(array $content = null): static
protected function setContent(array|null $content = null): static
{
if ($content !== null) {
$content = new Content($content, $this);
@@ -618,7 +618,7 @@ abstract class ModelWithContent implements Identifiable
*
* @return $this
*/
protected function setTranslations(array $translations = null): static
protected function setTranslations(array|null $translations = null): static
{
if ($translations !== null) {
$this->translations = new Collection();
@@ -675,7 +675,7 @@ abstract class ModelWithContent implements Identifiable
* (`null` to keep the original token)
*/
public function toSafeString(
string $template = null,
string|null $template = null,
array $data = [],
string|null $fallback = ''
): string {
@@ -691,7 +691,7 @@ abstract class ModelWithContent implements Identifiable
* @param string $handler For internal use
*/
public function toString(
string $template = null,
string|null $template = null,
array $data = [],
string|null $fallback = '',
string $handler = 'template'
@@ -728,7 +728,7 @@ abstract class ModelWithContent implements Identifiable
* If no code is specified the current translation is returned
*/
public function translation(
string $languageCode = null
string|null $languageCode = null
): ContentTranslation|null {
if ($language = $this->kirby()->language($languageCode)) {
return $this->translations()->find($language->code());
@@ -766,8 +766,8 @@ abstract class ModelWithContent implements Identifiable
* @throws \Kirby\Exception\InvalidArgumentException If the input array contains invalid values
*/
public function update(
array $input = null,
string $languageCode = null,
array|null $input = null,
string|null $languageCode = null,
bool $validate = false
): static {
$form = Form::for($this, [
@@ -811,7 +811,7 @@ abstract class ModelWithContent implements Identifiable
* to store the given data on disk or anywhere else
* @internal
*/
public function writeContent(array $data, string $languageCode = null): bool
public function writeContent(array $data, string|null $languageCode = null): bool
{
$data = $this->contentFileData($data, $languageCode);
$id = $this->storage()->defaultVersion();

View File

@@ -21,7 +21,7 @@ class NestCollection extends BaseCollection
* to an array. This can also take a callback
* function to further modify the array result.
*/
public function toArray(Closure $map = null): array
public function toArray(Closure|null $map = null): array
{
return parent::toArray($map ?? fn ($object) => $object->toArray());
}

View File

@@ -776,7 +776,7 @@ class Page extends ModelWithContent
* This is only used for drafts so far.
* @internal
*/
public function isVerified(string $token = null): bool
public function isVerified(string|null $token = null): bool
{
if (
$this->isPublished() === true &&
@@ -1091,7 +1091,7 @@ class Page extends ModelWithContent
*
* @return $this
*/
protected function setBlueprint(array $blueprint = null): static
protected function setBlueprint(array|null $blueprint = null): static
{
if ($blueprint !== null) {
$blueprint['model'] = $this;
@@ -1106,7 +1106,7 @@ class Page extends ModelWithContent
*
* @return $this
*/
protected function setTemplate(string $template = null): static
protected function setTemplate(string|null $template = null): static
{
if ($template !== null) {
$this->intendedTemplate = $this->kirby()->template($template);
@@ -1120,7 +1120,7 @@ class Page extends ModelWithContent
*
* @return $this
*/
protected function setUrl(string $url = null): static
protected function setUrl(string|null $url = null): static
{
if (is_string($url) === true) {
$url = rtrim($url, '/');
@@ -1133,7 +1133,7 @@ class Page extends ModelWithContent
/**
* Returns the slug of the page
*/
public function slug(string $languageCode = null): string
public function slug(string|null $languageCode = null): string
{
if ($this->kirby()->multilang() === true) {
$languageCode ??= $this->kirby()->languageCode();
@@ -1245,7 +1245,7 @@ class Page extends ModelWithContent
* The uri is the same as the id, except
* that it will be translated in multi-language setups
*/
public function uri(string $languageCode = null): string
public function uri(string|null $languageCode = null): string
{
// set the id, depending on the parent
if ($parent = $this->parent()) {
@@ -1301,7 +1301,7 @@ class Page extends ModelWithContent
*/
public function urlForLanguage(
$language = null,
array $options = null
array|null $options = null
): string {
if ($options !== null) {
return Url::to($this->urlForLanguage($language), $options);

View File

@@ -578,7 +578,7 @@ trait PageActions
* Create the sorting number for the page
* depending on the blueprint settings
*/
public function createNum(int $num = null): int
public function createNum(int|null $num = null): int
{
$mode = $this->blueprint()->num();
@@ -827,7 +827,7 @@ trait PageActions
/**
* @throws \Kirby\Exception\LogicException If the page is not included in the siblings collection
*/
protected function resortSiblingsAfterListing(int $position = null): bool
protected function resortSiblingsAfterListing(int|null $position = null): bool
{
// get all siblings including the current page
$siblings = $this

View File

@@ -79,7 +79,7 @@ class PagePicker extends Picker
* parent model that is currently selected
* in the page picker.
*/
public function modelToArray(Page|Site $model = null): array|null
public function modelToArray(Page|Site|null $model = null): array|null
{
if ($model === null) {
return null;
@@ -126,13 +126,13 @@ class PagePicker extends Picker
if (empty($this->options['query']) === true) {
$items = $this->itemsForParent();
// when subpage navigation is enabled, a parent
// might be passed in addition to the query.
// The parent then takes priority.
// when subpage navigation is enabled, a parent
// might be passed in addition to the query.
// The parent then takes priority.
} elseif ($this->options['subpages'] === true && empty($this->options['parent']) === false) {
$items = $this->itemsForParent();
// search by query
// search by query
} else {
$items = $this->itemsForQuery();
}

View File

@@ -25,7 +25,7 @@ class PageRules
*
* @throws \Kirby\Exception\InvalidArgumentException If the given number is invalid
*/
public static function changeNum(Page $page, int $num = null): bool
public static function changeNum(Page $page, int|null $num = null): bool
{
if ($num !== null && $num < 0) {
throw new InvalidArgumentException(['key' => 'page.num.invalid']);
@@ -86,7 +86,7 @@ class PageRules
public static function changeStatus(
Page $page,
string $status,
int $position = null
int|null $position = null
): bool {
if (isset($page->blueprint()->status()[$status]) === false) {
throw new InvalidArgumentException(['key' => 'page.status.invalid']);

View File

@@ -61,19 +61,19 @@ class Pages extends Collection
if ($object instanceof self) {
$this->data = array_merge($this->data, $object->data);
// add a page by id
// add a page by id
} elseif (
is_string($object) === true &&
$page = $site->find($object)
) {
$this->__set($page->id(), $page);
// add a page object
// add a page object
} elseif ($object instanceof Page) {
$this->__set($object->id(), $object);
// give a useful error message on invalid input;
// silently ignore "empty" values for compatibility with existing setups
// give a useful error message on invalid input;
// silently ignore "empty" values for compatibility with existing setups
} elseif (in_array($object, [null, false, true], true) !== true) {
throw new InvalidArgumentException('You must pass a Pages or Page object or an ID of an existing page to the Pages collection');
}
@@ -142,8 +142,8 @@ class Pages extends Collection
*/
public static function factory(
array $pages,
Page|Site $model = null,
bool $draft = null
Page|Site|null $model = null,
bool|null $draft = null
): static {
$model ??= App::instance()->site();
$children = new static([], $model);
@@ -248,7 +248,7 @@ class Pages extends Collection
*/
protected function findByKeyRecursive(
string $id,
string $startAt = null,
string|null $startAt = null,
bool $multiLang = false
) {
$path = explode('/', $id);

View File

@@ -125,7 +125,7 @@ class Pagination extends BasePagination
* If the `$page` variable is set, the URL
* for that page will be returned.
*/
public function pageUrl(int $page = null): string|null
public function pageUrl(int|null $page = null): string|null
{
if ($page === null) {
return $this->pageUrl($this->page());

View File

@@ -68,7 +68,7 @@ abstract class Picker
* array that is already optimized for the
* panel picker component.
*/
public function itemsToArray(Collection $items = null): array
public function itemsToArray(Collection|null $items = null): array
{
if ($items === null) {
return [];

View File

@@ -77,7 +77,7 @@ class Plugin
/**
* Allows access to any composer.json field by method call
*/
public function __call(string $key, array $arguments = null): mixed
public function __call(string $key, array|null $arguments = null): mixed
{
return $this->info()[$key] ?? null;
}

View File

@@ -75,7 +75,7 @@ class Responder
*
* @return $this|string|null
*/
public function body(string $body = null): static|string|null
public function body(string|null $body = null): static|string|null
{
if ($body === null) {
return $this->body;
@@ -210,7 +210,7 @@ class Responder
*
* @return int|$this
*/
public function code(int $code = null)
public function code(int|null $code = null)
{
if ($code === null) {
return $this->code;
@@ -266,7 +266,7 @@ class Responder
*
* @return array|$this
*/
public function headers(array $headers = null)
public function headers(array|null $headers = null)
{
if ($headers === null) {
$injectedHeaders = [];
@@ -305,7 +305,7 @@ class Responder
*
* @return string|$this
*/
public function json(array $json = null)
public function json(array|null $json = null)
{
if ($json !== null) {
$this->body(json_encode($json));
@@ -334,7 +334,7 @@ class Responder
/**
* Creates and returns the response object from the config
*/
public function send(string $body = null): Response
public function send(string|null $body = null): Response
{
if ($body !== null) {
$this->body($body);
@@ -365,7 +365,7 @@ class Responder
*
* @return string|$this
*/
public function type(string $type = null)
public function type(string|null $type = null)
{
if ($type === null) {
return $this->type;

View File

@@ -82,7 +82,11 @@ class Role
public static function factory(array $props, array $inject = []): static
{
return new static($props + $inject);
// ensure to properly extend the blueprint
$props = $props + $inject;
$props = Blueprint::extend($props);
return new static($props);
}
public function id(): string

View File

@@ -96,7 +96,7 @@ class Roles extends Collection
return $collection->sort('name', 'asc');
}
public static function load(string $root = null, array $inject = []): static
public static function load(string|null $root = null, array $inject = []): static
{
$kirby = App::instance();
$roles = new static();

View File

@@ -17,7 +17,7 @@ namespace Kirby\Cms;
class Search
{
public static function files(
string $query = null,
string|null $query = null,
array $params = []
): Files {
return App::instance()->site()->index()->files()->search($query, $params);
@@ -36,14 +36,14 @@ class Search
}
public static function pages(
string $query = null,
string|null $query = null,
array $params = []
): Pages {
return App::instance()->site()->index()->search($query, $params);
}
public static function users(
string $query = null,
string|null $query = null,
array $params = []
): Users {
return App::instance()->users()->search($query, $params);

View File

@@ -30,7 +30,7 @@ class Structure extends Items
* an array of item props
*/
public static function factory(
array $items = null,
array|null $items = null,
array $params = []
): static {
if (is_array($items) === true) {

View File

@@ -364,7 +364,7 @@ class System
{
return
version_compare(PHP_VERSION, '8.1.0', '>=') === true &&
version_compare(PHP_VERSION, '8.4.0', '<') === true;
version_compare(PHP_VERSION, '8.5.0', '<') === true;
}
/**
@@ -385,7 +385,7 @@ class System
* @throws \Kirby\Exception\Exception
* @throws \Kirby\Exception\InvalidArgumentException
*/
public function register(string $license = null, string $email = null): bool
public function register(string|null $license = null, string|null $email = null): bool
{
$license = new License(
code: $license,
@@ -405,6 +405,16 @@ class System
return $this->app->environment()->get('SERVER_SOFTWARE', '');
}
/**
* Returns the short version of the detected server software
* @since 4.6.0
*/
public function serverSoftwareShort(): string
{
$software = $this->serverSoftware();
return strtok($software, ' ');
}
/**
* Check for a writable sessions folder
*/

View File

@@ -87,7 +87,7 @@ class Translation
* Returns a single translation
* string by key
*/
public function get(string $key, string $default = null): string|null
public function get(string $key, string|null $default = null): string|null
{
return $this->data[$key] ?? $default;
}

View File

@@ -44,9 +44,9 @@ class Url extends BaseUrl
* @return string The safe string
*/
public static function slug(
string $string = null,
string $separator = null,
string $allowed = null,
string|null $string = null,
string|null $separator = null,
string|null $allowed = null,
): string {
$maxlength = App::instance()->option('slugs.maxlength', 255);
return Str::slug($string, $separator, $allowed, $maxlength);

View File

@@ -239,7 +239,7 @@ class User extends ModelWithContent
*/
public static function hashPassword(
#[SensitiveParameter]
string $password = null
string|null $password = null
): string|null {
if ($password !== null) {
$password = password_hash($password, PASSWORD_DEFAULT);
@@ -279,7 +279,7 @@ class User extends ModelWithContent
/**
* Compares the current object with the given user object
*/
public function is(User $user = null): bool
public function is(User|null $user = null): bool
{
if ($user === null) {
return false;
@@ -625,7 +625,7 @@ class User extends ModelWithContent
*
* @return $this
*/
protected function setBlueprint(array $blueprint = null): static
protected function setBlueprint(array|null $blueprint = null): static
{
if ($blueprint !== null) {
$blueprint['model'] = $this;
@@ -683,7 +683,7 @@ class User extends ModelWithContent
* (`null` to keep the original token)
*/
public function toString(
string $template = null,
string|null $template = null,
array $data = [],
string|null $fallback = '',
string $handler = 'template'
@@ -711,7 +711,7 @@ class User extends ModelWithContent
*/
public function validatePassword(
#[SensitiveParameter]
string $password = null
string|null $password = null
): bool {
if (empty($this->password()) === true) {
throw new NotFoundException(['key' => 'user.password.undefined']);

View File

@@ -209,7 +209,7 @@ trait UserActions
/**
* Creates a new User from the given props and returns a new User object
*/
public static function create(array $props = null): User
public static function create(array|null $props = null): User
{
$data = $props;
@@ -364,8 +364,8 @@ trait UserActions
* Updates the user data
*/
public function update(
array $input = null,
string $languageCode = null,
array|null $input = null,
string|null $languageCode = null,
bool $validate = false
): static {
$user = parent::update($input, $languageCode, $validate);
@@ -408,7 +408,7 @@ trait UserActions
*/
protected function writePassword(
#[SensitiveParameter]
string $password = null
string|null $password = null
): bool {
return $this->writeSecret('password', $password);
}

View File

@@ -49,19 +49,19 @@ class Users extends Collection
if ($object instanceof self) {
$this->data = array_merge($this->data, $object->data);
// add a user by id
// add a user by id
} elseif (
is_string($object) === true &&
$user = App::instance()->user($object)
) {
$this->__set($user->id(), $user);
// add a user object
// add a user object
} elseif ($object instanceof User) {
$this->__set($object->id(), $object);
// give a useful error message on invalid input;
// silently ignore "empty" values for compatibility with existing setups
// give a useful error message on invalid input;
// silently ignore "empty" values for compatibility with existing setups
} elseif (in_array($object, [null, false, true], true) !== true) {
throw new InvalidArgumentException('You must pass a Users or User object or an ID of an existing user to the Users collection');
}