Upgrade to 3.6.1
This commit is contained in:
6
kirby/.vscode/extensions.json
vendored
Executable file
6
kirby/.vscode/extensions.json
vendored
Executable file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"dbaeumer.vscode-eslint",
|
||||
"esbenp.prettier-vscode"
|
||||
]
|
||||
}
|
4
kirby/.vscode/settings.json
vendored
Executable file
4
kirby/.vscode/settings.json
vendored
Executable file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnSave": true
|
||||
}
|
@@ -6,7 +6,7 @@
|
||||
*/
|
||||
if (
|
||||
version_compare(PHP_VERSION, '7.4.0', '>=') === false ||
|
||||
version_compare(PHP_VERSION, '8.1.0', '<') === false
|
||||
version_compare(PHP_VERSION, '8.2.0', '<') === false
|
||||
) {
|
||||
die(include __DIR__ . '/views/php.php');
|
||||
}
|
||||
|
@@ -8,7 +8,7 @@
|
||||
"core"
|
||||
],
|
||||
"homepage": "https://getkirby.com",
|
||||
"version": "3.6.0",
|
||||
"version": "3.6.1",
|
||||
"license": "proprietary",
|
||||
"authors": [
|
||||
{
|
||||
@@ -21,7 +21,7 @@
|
||||
"php": ">=7.4.0 <8.1.0",
|
||||
"ext-ctype": "*",
|
||||
"ext-mbstring": "*",
|
||||
"claviska/simpleimage": "3.6.3",
|
||||
"claviska/simpleimage": "3.6.4",
|
||||
"filp/whoops": "2.14.4",
|
||||
"getkirby/composer-installer": "^1.2.1",
|
||||
"laminas/laminas-escaper": "2.9.0",
|
||||
@@ -29,12 +29,21 @@
|
||||
"mustangostang/spyc": "0.6.3",
|
||||
"phpmailer/phpmailer": "6.5.1",
|
||||
"psr/log": "1.1.4",
|
||||
"true/punycode": "2.1.1"
|
||||
"symfony/polyfill-intl-idn": "1.23.0",
|
||||
"symfony/polyfill-mbstring": "1.23.1"
|
||||
},
|
||||
"replace": {
|
||||
"symfony/polyfill-php72": "*"
|
||||
},
|
||||
"config": {
|
||||
"optimize-autoloader": true,
|
||||
"platform-check": false
|
||||
},
|
||||
"extra": {
|
||||
"unused": [
|
||||
"symfony/polyfill-intl-idn"
|
||||
]
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Kirby\\": "src/"
|
||||
|
227
kirby/composer.lock
generated
227
kirby/composer.lock
generated
@@ -4,11 +4,11 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "8712d96f826f859411fec3cce4f16e63",
|
||||
"content-hash": "9327de85e3414653ef22b3a147bb676e",
|
||||
"packages": [
|
||||
{
|
||||
"name": "claviska/simpleimage",
|
||||
"version": "3.6.3",
|
||||
"version": "3.6.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/claviska/SimpleImage.git",
|
||||
@@ -45,7 +45,7 @@
|
||||
"description": "A PHP class that makes working with images as simple as possible.",
|
||||
"support": {
|
||||
"issues": "https://github.com/claviska/SimpleImage/issues",
|
||||
"source": "https://github.com/claviska/SimpleImage/tree/3.6.3"
|
||||
"source": "https://github.com/claviska/SimpleImage/tree/3.6.4"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -525,6 +525,177 @@
|
||||
},
|
||||
"time": "2021-05-03T11:20:27+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-idn",
|
||||
"version": "v1.23.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-intl-idn.git",
|
||||
"reference": "65bd267525e82759e7d8c4e8ceea44f398838e65"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/65bd267525e82759e7d8c4e8ceea44f398838e65",
|
||||
"reference": "65bd267525e82759e7d8c4e8ceea44f398838e65",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1",
|
||||
"symfony/polyfill-intl-normalizer": "^1.10",
|
||||
"symfony/polyfill-php72": "^1.10"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-intl": "For best performance"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.23-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Polyfill\\Intl\\Idn\\": ""
|
||||
},
|
||||
"files": [
|
||||
"bootstrap.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Laurent Bassin",
|
||||
"email": "laurent@bassin.info"
|
||||
},
|
||||
{
|
||||
"name": "Trevor Rowbotham",
|
||||
"email": "trevor.rowbotham@pm.me"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"compatibility",
|
||||
"idn",
|
||||
"intl",
|
||||
"polyfill",
|
||||
"portable",
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.23.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-05-27T09:27:20+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-normalizer",
|
||||
"version": "v1.23.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
|
||||
"reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8590a5f561694770bdcd3f9b5c69dde6945028e8",
|
||||
"reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-intl": "For best performance"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.23-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Polyfill\\Intl\\Normalizer\\": ""
|
||||
},
|
||||
"files": [
|
||||
"bootstrap.php"
|
||||
],
|
||||
"classmap": [
|
||||
"Resources/stubs"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nicolas Grekas",
|
||||
"email": "p@tchwork.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony polyfill for intl's Normalizer class and related functions",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"compatibility",
|
||||
"intl",
|
||||
"normalizer",
|
||||
"polyfill",
|
||||
"portable",
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.23.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-02-19T12:13:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-mbstring",
|
||||
"version": "v1.23.1",
|
||||
@@ -604,56 +775,6 @@
|
||||
}
|
||||
],
|
||||
"time": "2021-05-27T12:26:48+00:00"
|
||||
},
|
||||
{
|
||||
"name": "true/punycode",
|
||||
"version": "v2.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/true/php-punycode.git",
|
||||
"reference": "a4d0c11a36dd7f4e7cd7096076cab6d3378a071e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/true/php-punycode/zipball/a4d0c11a36dd7f4e7cd7096076cab6d3378a071e",
|
||||
"reference": "a4d0c11a36dd7f4e7cd7096076cab6d3378a071e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0",
|
||||
"symfony/polyfill-mbstring": "^1.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.7",
|
||||
"squizlabs/php_codesniffer": "~2.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"TrueBV\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Renan Gonçalves",
|
||||
"email": "renan.saddam@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "A Bootstring encoding of Unicode for Internationalized Domain Names in Applications (IDNA)",
|
||||
"homepage": "https://github.com/true/php-punycode",
|
||||
"keywords": [
|
||||
"idna",
|
||||
"punycode"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/true/php-punycode/issues",
|
||||
"source": "https://github.com/true/php-punycode/tree/master"
|
||||
},
|
||||
"time": "2016-11-16T10:37:54+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [],
|
||||
|
@@ -200,16 +200,20 @@ return [
|
||||
},
|
||||
'submit' => function (string $id) {
|
||||
$page = Find::page($id);
|
||||
$title = trim(get('title'));
|
||||
$slug = trim(get('slug'));
|
||||
$title = trim(get('title', ''));
|
||||
$slug = trim(get('slug', ''));
|
||||
|
||||
// basic input validation before we move on
|
||||
if (Str::length($title) === 0) {
|
||||
throw new InvalidArgumentException(['key' => 'page.changeTitle.empty']);
|
||||
throw new InvalidArgumentException([
|
||||
'key' => 'page.changeTitle.empty'
|
||||
]);
|
||||
}
|
||||
|
||||
if (Str::length($slug) === 0) {
|
||||
throw new InvalidArgumentException(['key' => 'page.slug.invalid']);
|
||||
throw new InvalidArgumentException([
|
||||
'key' => 'page.slug.invalid'
|
||||
]);
|
||||
}
|
||||
|
||||
// nothing changed
|
||||
@@ -318,7 +322,7 @@ return [
|
||||
];
|
||||
},
|
||||
'submit' => function () {
|
||||
$title = trim(get('title'));
|
||||
$title = trim(get('title', ''));
|
||||
|
||||
if (Str::length($title) === 0) {
|
||||
throw new InvalidArgumentException([
|
||||
|
@@ -37,7 +37,7 @@ return [
|
||||
'plugins' => $plugins,
|
||||
'php' => phpversion(),
|
||||
'server' => $system->serverSoftware(),
|
||||
'ssl' => Server::https(),
|
||||
'https' => Server::https(),
|
||||
'version' => $kirby->version(),
|
||||
]
|
||||
];
|
||||
|
@@ -28,9 +28,7 @@ return [
|
||||
* @param string $url Relative or absolute URL
|
||||
* @param string|array $options An array of attributes for the link tag or a media attribute string
|
||||
*/
|
||||
'css' => function (App $kirby, string $url, $options = null): string {
|
||||
return $url;
|
||||
},
|
||||
'css' => fn (App $kirby, string $url, $options = null): string => $url,
|
||||
|
||||
|
||||
/**
|
||||
@@ -84,9 +82,10 @@ return [
|
||||
* @param \Kirby\Cms\App $kirby Kirby instance
|
||||
* @param \Kirby\Cms\File|\Kirby\Filesystem\Asset $file The file object
|
||||
* @param array $options All thumb options (width, height, crop, blur, grayscale)
|
||||
* @return \Kirby\Cms\File|\Kirby\Cms\FileVersion
|
||||
* @return \Kirby\Cms\File|\Kirby\Cms\FileVersion|\Kirby\Filesystem\Asset
|
||||
*/
|
||||
'file::version' => function (App $kirby, $file, array $options = []) {
|
||||
// if file is not resizable, return
|
||||
if ($file->isResizable() === false) {
|
||||
return $file;
|
||||
}
|
||||
@@ -96,14 +95,20 @@ return [
|
||||
$template = $mediaRoot . '/{{ name }}{{ attributes }}.{{ extension }}';
|
||||
$thumbRoot = (new Filename($file->root(), $template, $options))->toString();
|
||||
$thumbName = basename($thumbRoot);
|
||||
$job = $mediaRoot . '/.jobs/' . $thumbName . '.json';
|
||||
|
||||
// check if the thumb already exists
|
||||
if (file_exists($thumbRoot) === false) {
|
||||
|
||||
// if not, create job file
|
||||
$job = $mediaRoot . '/.jobs/' . $thumbName . '.json';
|
||||
|
||||
try {
|
||||
Data::write($job, array_merge($options, [
|
||||
'filename' => $file->filename()
|
||||
]));
|
||||
} catch (Throwable $e) {
|
||||
// if thumb doesn't exist yet and job file cannot
|
||||
// be created, return
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
@@ -123,9 +128,7 @@ return [
|
||||
* @param string $url Relative or absolute URL
|
||||
* @param string|array $options An array of attributes for the link tag or a media attribute string
|
||||
*/
|
||||
'js' => function (App $kirby, string $url, $options = null): string {
|
||||
return $url;
|
||||
},
|
||||
'js' => fn (App $kirby, string $url, $options = null): string => $url,
|
||||
|
||||
/**
|
||||
* Add your own Markdown parser
|
||||
|
@@ -11,7 +11,7 @@ return [
|
||||
],
|
||||
'computed' => [
|
||||
'value' => function () {
|
||||
return trim($this->value);
|
||||
return trim($this->value ?? '');
|
||||
}
|
||||
]
|
||||
];
|
||||
|
@@ -27,7 +27,7 @@ return [
|
||||
* Sets the default text when a new page/file/user is created
|
||||
*/
|
||||
'default' => function (string $default = null) {
|
||||
return trim($default);
|
||||
return trim($default ?? '');
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -81,7 +81,7 @@ return [
|
||||
},
|
||||
|
||||
'value' => function (string $value = null) {
|
||||
return trim($value);
|
||||
return trim($value ?? '');
|
||||
}
|
||||
],
|
||||
'api' => function () {
|
||||
|
@@ -29,7 +29,8 @@ return [
|
||||
],
|
||||
'computed' => [
|
||||
'value' => function () {
|
||||
return Sane::sanitize(trim($this->value), 'html');
|
||||
$value = trim($this->value ?? '');
|
||||
return Sane::sanitize($value, 'html');
|
||||
}
|
||||
],
|
||||
];
|
||||
|
@@ -98,10 +98,7 @@ function csrf(?string $check = null)
|
||||
function css($url, $options = null): ?string
|
||||
{
|
||||
if (is_array($url) === true) {
|
||||
$links = array_map(function ($url) use ($options) {
|
||||
return css($url, $options);
|
||||
}, $url);
|
||||
|
||||
$links = A::map($url, fn ($url) => css($url, $options));
|
||||
return implode(PHP_EOL, $links);
|
||||
}
|
||||
|
||||
@@ -373,10 +370,7 @@ function invalid(array $data = [], array $rules = [], array $messages = []): arr
|
||||
function js($url, $options = null): ?string
|
||||
{
|
||||
if (is_array($url) === true) {
|
||||
$scripts = array_map(function ($url) use ($options) {
|
||||
return js($url, $options);
|
||||
}, $url);
|
||||
|
||||
$scripts = A::map($url, fn ($url) => js($url, $options));
|
||||
return implode(PHP_EOL, $scripts);
|
||||
}
|
||||
|
||||
@@ -584,7 +578,7 @@ function page(...$id)
|
||||
*/
|
||||
function pages(...$id)
|
||||
{
|
||||
if (count($id) === 1) {
|
||||
if (count($id) === 1 && is_array($id[0]) === false) {
|
||||
// @codeCoverageIgnoreStart
|
||||
deprecated('Passing a single id to the `pages()` helper will return a Kirby\Cms\Pages collection with a single element instead of the single Kirby\Cms\Page object itself - starting in 3.7.0.');
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
@@ -121,13 +121,14 @@ return function (App $app) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$time = empty($field->value) === true ? strtotime($fallback) : $field->toTimestamp();
|
||||
|
||||
if ($format === null) {
|
||||
return $time;
|
||||
if (empty($field->value) === false) {
|
||||
$time = $field->toTimestamp();
|
||||
} else {
|
||||
$time = strtotime($fallback);
|
||||
}
|
||||
|
||||
return ($app->option('date.handler', 'date'))($format, $time);
|
||||
$handler = $app->option('date.handler', 'date');
|
||||
return Str::date($time, $format, $handler);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -384,7 +385,7 @@ return function (App $app) {
|
||||
// Obsolete elements, script tags, image maps and form elements have
|
||||
// been excluded for safety reasons and as they are most likely not
|
||||
// needed in most cases.
|
||||
$field->value = strip_tags($field->value, '<b><i><small><abbr><cite><code><dfn><em><kbd><strong><samp><var><a><bdo><br><img><q><span><sub><sup>');
|
||||
$field->value = strip_tags($field->value, Html::$inlineList);
|
||||
return $field;
|
||||
},
|
||||
|
||||
|
@@ -247,7 +247,7 @@
|
||||
"field.blocks.image.caption": "Titulek",
|
||||
"field.blocks.image.crop": "Oříznout",
|
||||
"field.blocks.image.link": "Odkaz",
|
||||
"field.blocks.image.location": "Pozice",
|
||||
"field.blocks.image.location": "Umístění",
|
||||
"field.blocks.image.name": "Obrázek",
|
||||
"field.blocks.image.placeholder": "Vyberte obrázek",
|
||||
"field.blocks.image.ratio": "Poměr stran",
|
||||
|
@@ -1,20 +1,20 @@
|
||||
{
|
||||
"account.changeName": "Change your name",
|
||||
"account.delete": "Delete your account",
|
||||
"account.delete.confirm": "Do you really want to delete your account? You will be logged out immediately. Your account cannot be recovered.",
|
||||
"account.changeName": "Cambiar nombre",
|
||||
"account.delete": "Eliminar cuenta",
|
||||
"account.delete.confirm": "¿Realmente quieres eliminar tu cuenta? Tu sesión se cerrará inmediatamente. Tu cuenta no podrá ser recuperada. ",
|
||||
|
||||
"add": "Agregar",
|
||||
"author": "Author",
|
||||
"author": "Autor",
|
||||
"avatar": "Foto de perfil",
|
||||
"back": "Regresar",
|
||||
"cancel": "Cancelar",
|
||||
"change": "Cambiar",
|
||||
"close": "Cerrar",
|
||||
"confirm": "De acuerdo",
|
||||
"collapse": "Collapse",
|
||||
"collapse.all": "Collapse All",
|
||||
"collapse": "Colapsar",
|
||||
"collapse.all": "Colapsar todos",
|
||||
"copy": "Copiar",
|
||||
"copy.all": "Copy all",
|
||||
"copy.all": "Copiar todo",
|
||||
"create": "Crear",
|
||||
|
||||
"date": "Fecha",
|
||||
@@ -39,7 +39,7 @@
|
||||
"dialog.users.empty": "No has seleccionado ningún usuario",
|
||||
|
||||
"dimensions": "Dimensiones",
|
||||
"disabled": "Desabilitado",
|
||||
"disabled": "Deshabilitado",
|
||||
"discard": "Descartar",
|
||||
"download": "Descargar",
|
||||
"duplicate": "Duplicar",
|
||||
@@ -49,7 +49,7 @@
|
||||
"email": "Correo Electrónico",
|
||||
"email.placeholder": "correo@ejemplo.com",
|
||||
|
||||
"environment": "Environment",
|
||||
"environment": "Ambiente",
|
||||
|
||||
"error.access.code": "Código inválido",
|
||||
"error.access.login": "Ingreso inválido",
|
||||
@@ -63,11 +63,11 @@
|
||||
|
||||
"error.blueprint.notFound": "El blueprint \"{name}\" no se pudo cargar.",
|
||||
|
||||
"error.blocks.max.plural": "You must not add more than {max} blocks",
|
||||
"error.blocks.max.singular": "You must not add more than one block",
|
||||
"error.blocks.min.plural": "You must add at least {min} blocks",
|
||||
"error.blocks.min.singular": "You must add at least one block",
|
||||
"error.blocks.validation": "There's an error in block {index}",
|
||||
"error.blocks.max.plural": "No debes añadir más de {max} bloques",
|
||||
"error.blocks.max.singular": "No debes añadir más de un bloque",
|
||||
"error.blocks.min.plural": "Debes añadir al menos {min} bloques ",
|
||||
"error.blocks.min.singular": "Debes añadir al menos un bloque",
|
||||
"error.blocks.validation": "Hay un error en el bloque {index}",
|
||||
|
||||
"error.email.preset.notFound": "El preajuste de email \"{name}\" no se pudo encontrar.",
|
||||
|
||||
@@ -102,7 +102,7 @@
|
||||
"error.language.code": "Por favor introduce un código válido para el idioma",
|
||||
"error.language.duplicate": "El idioma ya existe",
|
||||
"error.language.name": "Por favor introduce un nombre válido para el idioma",
|
||||
"error.language.notFound": "The language could not be found",
|
||||
"error.language.notFound": "No se pudo encontrar el idioma",
|
||||
|
||||
"error.layout.validation.block": "There's an error in block {blockIndex} in layout {layoutIndex}",
|
||||
"error.layout.validation.settings": "There's an error in layout {index} settings",
|
||||
@@ -111,7 +111,7 @@
|
||||
"error.license.email": "Por favor ingresa un correo electrónico valido",
|
||||
"error.license.verification": "La licencia no pude ser verificada",
|
||||
|
||||
"error.offline": "The Panel is currently offline",
|
||||
"error.offline": "El Panel se encuentra fuera de linea ",
|
||||
|
||||
"error.page.changeSlug.permission": "No está permitido cambiar el apéndice de URL para \"{slug}\".",
|
||||
"error.page.changeStatus.incomplete": "La página tiene errores y no puede ser publicada.",
|
||||
@@ -176,7 +176,7 @@
|
||||
"error.user.password.invalid": "Por favor ingresa una contraseña valida. Las contraseñas deben tener al menos 8 caracteres de largo.",
|
||||
"error.user.password.notSame": "Por favor confirma la contrase\u00f1a",
|
||||
"error.user.password.undefined": "El usuario no tiene contraseña",
|
||||
"error.user.password.wrong": "Wrong password",
|
||||
"error.user.password.wrong": "Contraseña incorrecta",
|
||||
"error.user.role.invalid": "Por favor ingresa un rol valido",
|
||||
"error.user.undefined": "El usuario no pudo ser encontrado",
|
||||
"error.user.update.permission": "No tienes permiso para actualizar al usuario \"{name}\"",
|
||||
@@ -217,54 +217,54 @@
|
||||
"error.validation.size": "El tamaño del valor debe ser \"{size}\"",
|
||||
"error.validation.startswith": "El valor debe comenzar con \"{start}\"",
|
||||
"error.validation.time": "Por favor ingresa una hora válida",
|
||||
"error.validation.time.after": "Please enter a time after {time}",
|
||||
"error.validation.time.before": "Please enter a time before {time}",
|
||||
"error.validation.time.between": "Please enter a time between {min} and {max}",
|
||||
"error.validation.time.after": "Por favor ingresa una fecha después de {time}",
|
||||
"error.validation.time.before": "Por favor ingresa una fecha antes de {time}",
|
||||
"error.validation.time.between": "Por favor ingresa un fecha entre {min} y {max}",
|
||||
"error.validation.url": "Por favor ingresa un URL válido",
|
||||
|
||||
"expand": "Expandir",
|
||||
"expand.all": "Expandir todo",
|
||||
|
||||
"field.required": "Este campo es requerido",
|
||||
"field.blocks.changeType": "Change type",
|
||||
"field.blocks.changeType": "Cambiar tipo",
|
||||
"field.blocks.code.name": "Código",
|
||||
"field.blocks.code.language": "Idioma",
|
||||
"field.blocks.code.placeholder": "Your code …",
|
||||
"field.blocks.delete.confirm": "Do you really want to delete this block?",
|
||||
"field.blocks.delete.confirm.all": "Do you really want to delete all blocks?",
|
||||
"field.blocks.delete.confirm.selected": "Do you really want to delete the selected blocks?",
|
||||
"field.blocks.empty": "No blocks yet",
|
||||
"field.blocks.fieldsets.label": "Please select a block type …",
|
||||
"field.blocks.fieldsets.paste": "Press <kbd>{{ shortcut }}</kbd> to paste/import blocks from your clipboard",
|
||||
"field.blocks.gallery.name": "Gallery",
|
||||
"field.blocks.gallery.images.empty": "No images yet",
|
||||
"field.blocks.gallery.images.label": "Images",
|
||||
"field.blocks.heading.level": "Level",
|
||||
"field.blocks.heading.name": "Heading",
|
||||
"field.blocks.heading.text": "Text",
|
||||
"field.blocks.heading.placeholder": "Heading …",
|
||||
"field.blocks.image.alt": "Alternative text",
|
||||
"field.blocks.image.caption": "Caption",
|
||||
"field.blocks.image.crop": "Crop",
|
||||
"field.blocks.code.placeholder": "Tu código...",
|
||||
"field.blocks.delete.confirm": "¿Seguro que quieres eliminar este bloque?",
|
||||
"field.blocks.delete.confirm.all": "¿Seguro que quieres eliminar todos los bloques?",
|
||||
"field.blocks.delete.confirm.selected": "¿Seguro que quieres eliminar los bloques seleccionados?",
|
||||
"field.blocks.empty": "No hay bloques aún",
|
||||
"field.blocks.fieldsets.label": "Por favor selecciona un tipo de bloque...",
|
||||
"field.blocks.fieldsets.paste": "Presiona <kbd>{{ shortcut }}</kbd>para pegar/importar bloques en tu portapapeles ",
|
||||
"field.blocks.gallery.name": "Galería",
|
||||
"field.blocks.gallery.images.empty": "No hay imágenes aún",
|
||||
"field.blocks.gallery.images.label": "Imágenes",
|
||||
"field.blocks.heading.level": "Nivel",
|
||||
"field.blocks.heading.name": "Encabezado",
|
||||
"field.blocks.heading.text": "Texto",
|
||||
"field.blocks.heading.placeholder": "Encabezado...",
|
||||
"field.blocks.image.alt": "Texto alternativo",
|
||||
"field.blocks.image.caption": "Leyenda",
|
||||
"field.blocks.image.crop": "Cortar",
|
||||
"field.blocks.image.link": "Enlace",
|
||||
"field.blocks.image.location": "Location",
|
||||
"field.blocks.image.location": "Ubicación",
|
||||
"field.blocks.image.name": "Imágen",
|
||||
"field.blocks.image.placeholder": "Select an image",
|
||||
"field.blocks.image.ratio": "Ratio",
|
||||
"field.blocks.image.url": "Image URL",
|
||||
"field.blocks.line.name": "Line",
|
||||
"field.blocks.list.name": "List",
|
||||
"field.blocks.image.placeholder": "Selecciona una imagen",
|
||||
"field.blocks.image.ratio": "Proporción",
|
||||
"field.blocks.image.url": "URL de imágen",
|
||||
"field.blocks.line.name": "Linea",
|
||||
"field.blocks.list.name": "Lista",
|
||||
"field.blocks.markdown.name": "Markdown",
|
||||
"field.blocks.markdown.label": "Text",
|
||||
"field.blocks.markdown.placeholder": "Markdown …",
|
||||
"field.blocks.quote.name": "Quote",
|
||||
"field.blocks.quote.text.label": "Text",
|
||||
"field.blocks.quote.text.placeholder": "Quote …",
|
||||
"field.blocks.markdown.label": "Texto",
|
||||
"field.blocks.markdown.placeholder": "Markdown...",
|
||||
"field.blocks.quote.name": "Cita",
|
||||
"field.blocks.quote.text.label": "Texto",
|
||||
"field.blocks.quote.text.placeholder": "Cita...",
|
||||
"field.blocks.quote.citation.label": "Citation",
|
||||
"field.blocks.quote.citation.placeholder": "by …",
|
||||
"field.blocks.text.name": "Text",
|
||||
"field.blocks.quote.citation.placeholder": "Por ...",
|
||||
"field.blocks.text.name": "Texto",
|
||||
"field.blocks.text.placeholder": "Text …",
|
||||
"field.blocks.video.caption": "Caption",
|
||||
"field.blocks.video.caption": "Leyenda",
|
||||
"field.blocks.video.name": "Video",
|
||||
"field.blocks.video.placeholder": "Enter a video URL",
|
||||
"field.blocks.video.url.label": "Video-URL",
|
||||
|
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"account.changeName": "Change your name",
|
||||
"account.delete": "Delete your account",
|
||||
"account.delete.confirm": "Do you really want to delete your account? You will be logged out immediately. Your account cannot be recovered.",
|
||||
"account.changeName": "Cambia tu nombre",
|
||||
"account.delete": "Borrar tu cuenta",
|
||||
"account.delete.confirm": "¿Realmente quieres eliminar tu cuenta? Tu sesión se cerrará inmediatamente. La cuenta no podrá ser recuperada.",
|
||||
|
||||
"add": "Añadir",
|
||||
"author": "Author",
|
||||
"author": "Autor",
|
||||
"avatar": "Foto de perfil",
|
||||
"back": "Atrás",
|
||||
"cancel": "Cancelar",
|
||||
|
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"account.changeName": "Change your name",
|
||||
"account.delete": "Delete your account",
|
||||
"account.delete.confirm": "Do you really want to delete your account? You will be logged out immediately. Your account cannot be recovered.",
|
||||
"account.changeName": "Muuta nimesi",
|
||||
"account.delete": "Poista tilisi",
|
||||
"account.delete.confirm": "Haluatko varmasti poistaa tilisi? Sinut kirjataan ulos välittömästi, eikä tiliäsi voi palauttaa.",
|
||||
|
||||
"add": "Lis\u00e4\u00e4",
|
||||
"author": "Author",
|
||||
"author": "Tekijä",
|
||||
"avatar": "Profiilikuva",
|
||||
"back": "Takaisin",
|
||||
"cancel": "Peruuta",
|
||||
@@ -14,7 +14,7 @@
|
||||
"collapse": "Pienennä",
|
||||
"collapse.all": "Pienennä kaikki",
|
||||
"copy": "Kopioi",
|
||||
"copy.all": "Copy all",
|
||||
"copy.all": "Kopioi kaikki",
|
||||
"create": "Luo",
|
||||
|
||||
"date": "Päivämäärä",
|
||||
@@ -49,7 +49,7 @@
|
||||
"email": "S\u00e4hk\u00f6posti",
|
||||
"email.placeholder": "nimi@osoite.fi",
|
||||
|
||||
"environment": "Environment",
|
||||
"environment": "Ympäristö",
|
||||
|
||||
"error.access.code": "Väärä koodi",
|
||||
"error.access.login": "Kirjautumistiedot eivät kelpaa",
|
||||
@@ -102,7 +102,7 @@
|
||||
"error.language.code": "Anna kielen lyhenne",
|
||||
"error.language.duplicate": "Kieli on jo olemassa",
|
||||
"error.language.name": "Anna kielen nimi",
|
||||
"error.language.notFound": "The language could not be found",
|
||||
"error.language.notFound": "Kieltä ei löytynyt",
|
||||
|
||||
"error.layout.validation.block": "Lohkon {blockIndex} asetelmassa {layoutIndex} tapahtui virhe",
|
||||
"error.layout.validation.settings": "Virhe asetelman {index} asetuksissa",
|
||||
@@ -111,7 +111,7 @@
|
||||
"error.license.email": "Anna sähköpostiosoite",
|
||||
"error.license.verification": "Lisenssiä ei voitu vahvistaa",
|
||||
|
||||
"error.offline": "The Panel is currently offline",
|
||||
"error.offline": "Paneeli on offline-tilassa",
|
||||
|
||||
"error.page.changeSlug.permission": "Sinulla ei ole oikeutta muuttaa URL-liitettä sivulle \"{slug}\"",
|
||||
"error.page.changeStatus.incomplete": "Sivulla on virheitä eikä sitä voitu julkaista",
|
||||
@@ -235,7 +235,7 @@
|
||||
"field.blocks.delete.confirm.selected": "Haluatko varmasti poistaa valitut lohkot?",
|
||||
"field.blocks.empty": "Ei lohkoja",
|
||||
"field.blocks.fieldsets.label": "Valitse lohkon tyyppi …",
|
||||
"field.blocks.fieldsets.paste": "Press <kbd>{{ shortcut }}</kbd> to paste/import blocks from your clipboard",
|
||||
"field.blocks.fieldsets.paste": "Paina <kbd>{{ shortcut }}</kbd> liittääksesi tai tuodaksesi lohkoja leikepöydältä",
|
||||
"field.blocks.gallery.name": "Galleria",
|
||||
"field.blocks.gallery.images.empty": "Ei kuvia",
|
||||
"field.blocks.gallery.images.label": "Kuvat",
|
||||
@@ -282,7 +282,7 @@
|
||||
"field.structure.empty": "Rivejä ei ole vielä lisätty",
|
||||
"field.users.empty": "Käyttäjiä ei ole vielä valittu",
|
||||
|
||||
"file.blueprint": "This file has no blueprint yet. You can define the setup in <strong>/site/blueprints/files/{blueprint}.yml</strong>",
|
||||
"file.blueprint": "Tällä tiedostolla ei ole vielä suunnitelmaa. Voit määrittää suunnitelman tiedostoon <strong>/site/blueprints/files/{blueprint}.yml</strong>",
|
||||
"file.delete.confirm": "Haluatko varmasti poistaa tiedoston <br><strong>{filename}</strong>?",
|
||||
"file.sort": "Muuta järjestyspaikkaa",
|
||||
|
||||
@@ -291,7 +291,7 @@
|
||||
|
||||
"hide": "Piilota",
|
||||
"hour": "Tunti",
|
||||
"import": "Import",
|
||||
"import": "Tuo",
|
||||
"insert": "Lis\u00e4\u00e4",
|
||||
"insert.after": "Lisää eteen",
|
||||
"insert.before": "Lisää jälkeen",
|
||||
@@ -405,7 +405,7 @@
|
||||
"orientation.portrait": "Pystysuuntainen",
|
||||
"orientation.square": "Neliskulmainen",
|
||||
|
||||
"page.blueprint": "This page has no blueprint yet. You can define the setup in <strong>/site/blueprints/pages/{blueprint}.yml</strong>",
|
||||
"page.blueprint": "Tällä sivulla ei ole vielä suunnitelmaa. Voit määrittää suunnitelman tiedostoon <strong>/site/blueprints/pages/{blueprint}.yml</strong>",
|
||||
"page.changeSlug": "Vaihda URL-osoite",
|
||||
"page.changeSlug.fromTitle": "Luo nimen perusteella",
|
||||
"page.changeStatus": "Muuta tilaa",
|
||||
@@ -437,10 +437,10 @@
|
||||
"pagination.page": "Sivu",
|
||||
|
||||
"password": "Salasana",
|
||||
"paste": "Paste",
|
||||
"paste.after": "Paste after",
|
||||
"paste": "Liitä",
|
||||
"paste.after": "Liitä jälkeen",
|
||||
"pixel": "Pikseli",
|
||||
"plugins": "Plugins",
|
||||
"plugins": "Liitännäiset",
|
||||
"prev": "Edellinen",
|
||||
"preview": "Esikatselu",
|
||||
"remove": "Poista",
|
||||
@@ -477,7 +477,7 @@
|
||||
"template": "Sivupohja",
|
||||
"today": "Tänään",
|
||||
|
||||
"server": "Server",
|
||||
"server": "Palvelin",
|
||||
|
||||
"site.blueprint": "Tällä sivustolla ei ole vielä suunnitelmaa. Voit määrittää suunnitelman tiedostoon <strong>/site/blueprints/site.yml</strong>",
|
||||
|
||||
@@ -488,15 +488,15 @@
|
||||
"toolbar.button.heading.1": "Otsikko 1",
|
||||
"toolbar.button.heading.2": "Otsikko 2",
|
||||
"toolbar.button.heading.3": "Otsikko 3",
|
||||
"toolbar.button.heading.4": "Heading 4",
|
||||
"toolbar.button.heading.5": "Heading 5",
|
||||
"toolbar.button.heading.6": "Heading 6",
|
||||
"toolbar.button.heading.4": "Otsikko 4",
|
||||
"toolbar.button.heading.5": "Otsikko 5",
|
||||
"toolbar.button.heading.6": "Otsikko 6",
|
||||
"toolbar.button.italic": "Kursivointi",
|
||||
"toolbar.button.file": "Tiedosto",
|
||||
"toolbar.button.file.select": "Valitse tiedosto",
|
||||
"toolbar.button.file.upload": "Lähetä tiedosto",
|
||||
"toolbar.button.link": "Linkki",
|
||||
"toolbar.button.paragraph": "Paragraph",
|
||||
"toolbar.button.paragraph": "Kappale",
|
||||
"toolbar.button.strike": "Yliviivaus",
|
||||
"toolbar.button.ol": "Järjestetty lista",
|
||||
"toolbar.button.underline": "Alaviiva",
|
||||
@@ -526,7 +526,7 @@
|
||||
"url.placeholder": "https://esimerkki.fi",
|
||||
|
||||
"user": "Käyttäjä",
|
||||
"user.blueprint": "You can define additional sections and form fields for this user role in <strong>/site/blueprints/users/{blueprint}.yml</strong>",
|
||||
"user.blueprint": "Voit määrittää lisää osioita ja lomakekenttiä tälle käyttäjälle suunnitelmassa <strong>/site/blueprints/users/{blueprint}.yml</strong>",
|
||||
"user.changeEmail": "Muuta sähköpostiosoite",
|
||||
"user.changeLanguage": "Vaihda kieli",
|
||||
"user.changeName": "Nimeä uudelleen",
|
||||
@@ -548,7 +548,7 @@
|
||||
"view.languages": "Kielet",
|
||||
"view.resetPassword": "Aseta salasana",
|
||||
"view.site": "Sivusto",
|
||||
"view.system": "System",
|
||||
"view.system": "Järjestelmä",
|
||||
"view.users": "K\u00e4ytt\u00e4j\u00e4t",
|
||||
|
||||
"welcome": "Tervetuloa",
|
||||
|
@@ -235,7 +235,7 @@
|
||||
"field.blocks.delete.confirm.selected": "Viltu virkilega eyða völdum bálkum?",
|
||||
"field.blocks.empty": "Öngvir bálkar enn",
|
||||
"field.blocks.fieldsets.label": "Veldu bálkagerð …",
|
||||
"field.blocks.fieldsets.paste": "Notaðu 1{{ shortcut }}1 flýtilyklaaðgerðina til að setja blokkina hér.",
|
||||
"field.blocks.fieldsets.paste": "Notaðu<kbd> {{ shortcut }}</kbd> flýtilyklaaðgerðina til að setja blokkina hér.",
|
||||
"field.blocks.gallery.name": "Myndasafn",
|
||||
"field.blocks.gallery.images.empty": "Engar myndir enn",
|
||||
"field.blocks.gallery.images.label": "Myndir",
|
||||
|
@@ -6,7 +6,7 @@
|
||||
"add": "\ucd94\uac00",
|
||||
"author": "저자",
|
||||
"avatar": "프로필 이미지",
|
||||
"back": "복귀",
|
||||
"back": "뒤로",
|
||||
"cancel": "\ucde8\uc18c",
|
||||
"change": "\ubcc0\uacbd",
|
||||
"close": "\ub2eb\uae30",
|
||||
@@ -34,9 +34,9 @@
|
||||
"delete": "\uc0ad\uc81c",
|
||||
"delete.all": "모두 삭제",
|
||||
|
||||
"dialog.files.empty": "선택한 파일이 없습니다.",
|
||||
"dialog.pages.empty": "선택한 페이지가 없습니다.",
|
||||
"dialog.users.empty": "선택한 사용자가 없습니다.",
|
||||
"dialog.files.empty": "선택할 파일이 없습니다.",
|
||||
"dialog.pages.empty": "선택할 페이지가 없습니다.",
|
||||
"dialog.users.empty": "선택할 사용자가 없습니다.",
|
||||
|
||||
"dimensions": "크기",
|
||||
"disabled": "비활성화",
|
||||
@@ -49,7 +49,7 @@
|
||||
"email": "\uc774\uba54\uc77c \uc8fc\uc18c",
|
||||
"email.placeholder": "mail@example.com",
|
||||
|
||||
"environment": "환경",
|
||||
"environment": "구동 환경",
|
||||
|
||||
"error.access.code": "코드가 올바르지 않습니다.",
|
||||
"error.access.login": "로그인할 수 없습니다.",
|
||||
@@ -194,7 +194,7 @@
|
||||
"error.validation.denied": "취소하세요.",
|
||||
"error.validation.different": "{other}에 포함된 값은 입력할 수 없습니다.",
|
||||
"error.validation.email": "올바른 이메일 주소를 입력하세요.",
|
||||
"error.validation.endswith": "값은 다음으로 끝나야 합니다: {end}",
|
||||
"error.validation.endswith": "값은 다음({end})으로 끝나야 합니다.",
|
||||
"error.validation.filename": "올바른 파일명을 입력하세요.",
|
||||
"error.validation.in": "{in} 중 하나를 입력하세요.",
|
||||
"error.validation.integer": "올바른 정수를 입력하세요.",
|
||||
@@ -215,7 +215,7 @@
|
||||
"error.validation.required": "해당 항목을 확인하세요.",
|
||||
"error.validation.same": "이 값({other})을 입력하세요.",
|
||||
"error.validation.size": "값의 크기({size})를 확인하세요. ",
|
||||
"error.validation.startswith": "값은 다음으로 시작해야 합니다: {start}",
|
||||
"error.validation.startswith": "값은 다음({start})으로 시작해야 합니다.",
|
||||
"error.validation.time": "올바른 시각을 입력하세요.",
|
||||
"error.validation.time.after": "{time} 이후 시각을 입력하세요.",
|
||||
"error.validation.time.before": "{time} 이전 시각을 입력하세요.",
|
||||
@@ -274,7 +274,7 @@
|
||||
|
||||
"field.layout.delete": "레이아웃 삭제",
|
||||
"field.layout.delete.confirm": "레이아웃을 삭제할까요?",
|
||||
"field.layout.empty": "레이아웃이 없습니다.",
|
||||
"field.layout.empty": "행이 없습니다.",
|
||||
"field.layout.select": "레이아웃 선택",
|
||||
|
||||
"field.pages.empty": "선택한 페이지가 없습니다.",
|
||||
@@ -392,7 +392,7 @@
|
||||
"more": "더 보기",
|
||||
"name": "이름",
|
||||
"next": "다음",
|
||||
"no": "네",
|
||||
"no": "아니요",
|
||||
"off": "끔",
|
||||
"on": "켬",
|
||||
"open": "열기",
|
||||
@@ -482,7 +482,7 @@
|
||||
"site.blueprint": "블루프린트(<strong>/site/blueprints/site.yml</strong>)를 설정하세요.",
|
||||
|
||||
"toolbar.button.code": "코드",
|
||||
"toolbar.button.bold": "강조 1",
|
||||
"toolbar.button.bold": "강조",
|
||||
"toolbar.button.email": "이메일 주소",
|
||||
"toolbar.button.headings": "제목",
|
||||
"toolbar.button.heading.1": "제목 1",
|
||||
@@ -553,5 +553,5 @@
|
||||
|
||||
"welcome": "반갑습니다.",
|
||||
"year": "년",
|
||||
"yes": "아니요"
|
||||
"yes": "네"
|
||||
}
|
||||
|
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"account.changeName": "Change your name",
|
||||
"account.delete": "Delete your account",
|
||||
"account.delete.confirm": "Do you really want to delete your account? You will be logged out immediately. Your account cannot be recovered.",
|
||||
"account.changeName": "Ändra ditt namn",
|
||||
"account.delete": "Radera ditt konto",
|
||||
"account.delete.confirm": "Vill du verkligen radera ditt konto? Du kommer att loggas ut omedelbart. Ditt konto kan inte återställas.",
|
||||
|
||||
"add": "L\u00e4gg till",
|
||||
"author": "Author",
|
||||
"author": "Författare",
|
||||
"avatar": "Profilbild",
|
||||
"back": "Tillbaka",
|
||||
"cancel": "Avbryt",
|
||||
@@ -29,7 +29,7 @@
|
||||
"days.tue": "Tis",
|
||||
"days.wed": "Ons",
|
||||
|
||||
"debugging": "Debugging",
|
||||
"debugging": "Felsökning",
|
||||
|
||||
"delete": "Radera",
|
||||
"delete.all": "Radera allt",
|
||||
@@ -49,7 +49,7 @@
|
||||
"email": "E-postadress",
|
||||
"email.placeholder": "namn@exempel.se",
|
||||
|
||||
"environment": "Environment",
|
||||
"environment": "Miljö",
|
||||
|
||||
"error.access.code": "Ogiltig kod",
|
||||
"error.access.login": "Ogiltig inloggning",
|
||||
@@ -111,7 +111,7 @@
|
||||
"error.license.email": "Ange en giltig e-postadress",
|
||||
"error.license.verification": "Licensen kunde inte verifieras",
|
||||
|
||||
"error.offline": "The Panel is currently offline",
|
||||
"error.offline": "Panelen är för närvarande offline",
|
||||
|
||||
"error.page.changeSlug.permission": "Du har inte behörighet att ändra URL-appendixen för \"{slug}\"",
|
||||
"error.page.changeStatus.incomplete": "Sidan innehåller fel och kan inte publiceras",
|
||||
@@ -440,7 +440,7 @@
|
||||
"paste": "Klistra in",
|
||||
"paste.after": "Klistra in efter",
|
||||
"pixel": "Pixel",
|
||||
"plugins": "Plugins",
|
||||
"plugins": "Tillägg",
|
||||
"prev": "Föregående",
|
||||
"preview": "Förhandsgranska",
|
||||
"remove": "Ta bort",
|
||||
|
@@ -2,29 +2,21 @@ module.exports = {
|
||||
extends: [
|
||||
"eslint:recommended",
|
||||
"plugin:cypress/recommended",
|
||||
"plugin:vue/recommended"
|
||||
"plugin:vue/recommended",
|
||||
"prettier"
|
||||
],
|
||||
rules: {
|
||||
"vue/component-definition-name-casing": "off",
|
||||
"vue/require-default-prop": "off",
|
||||
"vue/attributes-order": "error",
|
||||
"vue/require-prop-types": "error",
|
||||
"vue/max-attributes-per-line": [
|
||||
"error",
|
||||
{
|
||||
"singleline": 3,
|
||||
"multiline": {
|
||||
"max": 1,
|
||||
"allowFirstLine": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"vue/component-definition-name-casing": "off",
|
||||
"vue/html-closing-bracket-newline": [
|
||||
"error",
|
||||
{
|
||||
"singleline": "never",
|
||||
"multiline": "always"
|
||||
singleline: "never",
|
||||
multiline: "always"
|
||||
}
|
||||
]
|
||||
],
|
||||
"vue/multi-word-component-names": "off",
|
||||
"vue/require-default-prop": "off",
|
||||
"vue/require-prop-types": "error"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
3
kirby/panel/.prettierrc.json
Executable file
3
kirby/panel/.prettierrc.json
Executable file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"trailingComma": "none"
|
||||
}
|
2
kirby/panel/dist/css/style.css
vendored
2
kirby/panel/dist/css/style.css
vendored
File diff suppressed because one or more lines are too long
2
kirby/panel/dist/js/index.js
vendored
2
kirby/panel/dist/js/index.js
vendored
File diff suppressed because one or more lines are too long
34
kirby/panel/dist/js/plugins.js
vendored
34
kirby/panel/dist/js/plugins.js
vendored
@@ -1,4 +1,3 @@
|
||||
|
||||
window.panel = window.panel || {};
|
||||
window.panel.plugins = {
|
||||
components: {},
|
||||
@@ -17,7 +16,7 @@ window.panel.plugin = function (plugin, parts) {
|
||||
options = { template: options };
|
||||
}
|
||||
|
||||
window.panel.plugins["components"][`k-block-type-${name}`] = {
|
||||
window.panel.plugins.components[`k-block-type-${name}`] = {
|
||||
extends: "k-block-type",
|
||||
...options
|
||||
};
|
||||
@@ -25,35 +24,35 @@ window.panel.plugin = function (plugin, parts) {
|
||||
|
||||
// Components
|
||||
resolve(parts, "components", function (name, options) {
|
||||
window.panel.plugins["components"][name] = options;
|
||||
window.panel.plugins.components[name] = options;
|
||||
});
|
||||
|
||||
// Fields
|
||||
resolve(parts, "fields", function (name, options) {
|
||||
window.panel.plugins["components"][`k-${name}-field`] = options;
|
||||
window.panel.plugins.components[`k-${name}-field`] = options;
|
||||
});
|
||||
|
||||
// Icons
|
||||
resolve(parts, "icons", function (name, options) {
|
||||
window.panel.plugins["icons"][name] = options;
|
||||
window.panel.plugins.icons[name] = options;
|
||||
});
|
||||
|
||||
// Sections
|
||||
resolve(parts, "sections", function (name, options) {
|
||||
window.panel.plugins["components"][`k-${name}-section`] = {
|
||||
window.panel.plugins.components[`k-${name}-section`] = {
|
||||
...options,
|
||||
mixins: ["section"].concat(options.mixins || [])
|
||||
mixins: ["section", ...(options.mixins || [])]
|
||||
};
|
||||
});
|
||||
|
||||
// Vue.use
|
||||
// `Vue.use`
|
||||
resolve(parts, "use", function (name, options) {
|
||||
window.panel.plugins["use"].push(options);
|
||||
window.panel.plugins.use.push(options);
|
||||
});
|
||||
|
||||
// created callback
|
||||
// Vue `created` callback
|
||||
if (parts["created"]) {
|
||||
window.panel.plugins["created"].push(parts["created"]);
|
||||
window.panel.plugins.created.push(parts["created"]);
|
||||
}
|
||||
|
||||
// Login
|
||||
@@ -62,20 +61,15 @@ window.panel.plugin = function (plugin, parts) {
|
||||
}
|
||||
|
||||
// Third-party plugins
|
||||
resolve(parts, "thirdParty", function(name, options) {
|
||||
window.panel.plugins["thirdParty"][name] = options;
|
||||
resolve(parts, "thirdParty", function (name, options) {
|
||||
window.panel.plugins.thirdParty[name] = options;
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
function resolve(object, type, callback) {
|
||||
if (object[type]) {
|
||||
|
||||
if (Object.entries) {
|
||||
Object.entries(object[type]).forEach(function ([name, options]) {
|
||||
callback(name, options);
|
||||
});
|
||||
for (const [name, options] of Object.entries(object[type])) {
|
||||
callback(name, options);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -1,3 +1,4 @@
|
||||
/* eslint-env node */
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import { defineConfig } from "vite";
|
||||
@@ -24,7 +25,7 @@ export default defineConfig(({ command }) => {
|
||||
|
||||
// Delete the flag file on any kind of exit
|
||||
for (const eventType of ["exit", "SIGINT", "uncaughtException"]) {
|
||||
process.on(eventType, function(err) {
|
||||
process.on(eventType, function (err) {
|
||||
if (fs.existsSync(runningPath) === true) {
|
||||
fs.unlinkSync(runningPath);
|
||||
}
|
||||
|
@@ -1,12 +1,14 @@
|
||||
<?php
|
||||
|
||||
$root = dirname(__DIR__);
|
||||
$uri = urldecode(
|
||||
parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH)
|
||||
);
|
||||
|
||||
// https://yourdomain.com/media/super/nice.jpg
|
||||
if (file_exists($root . '/' . $_SERVER['SCRIPT_NAME'])) {
|
||||
return false; // serve the requested resource as-is.
|
||||
// Emulate Apache's `mod_rewrite` functionality
|
||||
if ($uri !== '/' && file_exists($_SERVER['DOCUMENT_ROOT'] . '/' . $uri)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$_SERVER['SCRIPT_NAME'] = str_replace($_SERVER['DOCUMENT_ROOT'], '', $index = $root . '/index.php');
|
||||
$_SERVER['SCRIPT_NAME'] = '/index.php';
|
||||
|
||||
include $index;
|
||||
require $_SERVER['DOCUMENT_ROOT'] . '/' . $_SERVER['SCRIPT_NAME'];
|
||||
|
@@ -162,7 +162,7 @@ class Api
|
||||
*/
|
||||
public function call(string $path = null, string $method = 'GET', array $requestData = [])
|
||||
{
|
||||
$path = rtrim($path, '/');
|
||||
$path = rtrim($path ?? '', '/');
|
||||
|
||||
$this->setRequestMethod($method);
|
||||
$this->setRequestData($requestData);
|
||||
|
@@ -330,6 +330,10 @@ class App
|
||||
{
|
||||
$router = $this->router();
|
||||
|
||||
/**
|
||||
* @todo Closures should not defined statically but
|
||||
* for each instance to avoid this constant setting and unsetting
|
||||
*/
|
||||
$router::$beforeEach = function ($route, $path, $method) {
|
||||
$this->trigger('route:before', compact('route', 'path', 'method'));
|
||||
};
|
||||
@@ -338,7 +342,12 @@ class App
|
||||
return $this->apply('route:after', compact('route', 'path', 'method', 'result', 'final'), 'result');
|
||||
};
|
||||
|
||||
return $router->call($path ?? $this->path(), $method ?? $this->request()->method());
|
||||
$result = $router->call($path ?? $this->path(), $method ?? $this->request()->method());
|
||||
|
||||
$router::$beforeEach = null;
|
||||
$router::$afterEach = null;
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -128,7 +128,7 @@ trait AppErrors
|
||||
'code' => $code,
|
||||
'message' => $exception->getMessage(),
|
||||
'details' => $details,
|
||||
'file' => ltrim($exception->getFile(), $_SERVER['DOCUMENT_ROOT'] ?? null),
|
||||
'file' => ltrim($exception->getFile(), $_SERVER['DOCUMENT_ROOT'] ?? ''),
|
||||
'line' => $exception->getLine(),
|
||||
], $httpCode);
|
||||
} else {
|
||||
@@ -158,9 +158,23 @@ trait AppErrors
|
||||
$whoops = $this->whoops();
|
||||
$whoops->clearHandlers();
|
||||
$whoops->pushHandler($handler);
|
||||
$whoops->pushHandler($this->getExceptionHookWhoopsHandler());
|
||||
$whoops->register(); // will only do something if not already registered
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes a callback handler for triggering the `system.exception` hook
|
||||
*
|
||||
* @return \Whoops\Handler\CallbackHandler
|
||||
*/
|
||||
protected function getExceptionHookWhoopsHandler(): CallbackHandler
|
||||
{
|
||||
return new CallbackHandler(function ($exception, $inspector, $run) {
|
||||
$this->trigger('system.exception', compact('exception'));
|
||||
return Handler::DONE;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the Whoops handlers and disables Whoops
|
||||
*
|
||||
|
@@ -605,9 +605,10 @@ class Auth
|
||||
$originalLog = $log;
|
||||
$time = time() - $this->kirby->option('auth.timeout', 3600);
|
||||
foreach ($log as $category => $entries) {
|
||||
$log[$category] = array_filter($entries, function ($entry) use ($time) {
|
||||
return $entry['time'] > $time;
|
||||
});
|
||||
$log[$category] = array_filter(
|
||||
$entries,
|
||||
fn ($entry) => $entry['time'] > $time
|
||||
);
|
||||
}
|
||||
|
||||
// write new log to the file system if it changed
|
||||
|
@@ -74,7 +74,7 @@ class Blueprint
|
||||
$props = $this->preset($props);
|
||||
|
||||
// normalize the name
|
||||
$props['name'] = $props['name'] ?? 'default';
|
||||
$props['name'] ??= 'default';
|
||||
|
||||
// normalize and translate the title
|
||||
$props['title'] = $this->i18n($props['title'] ?? ucfirst($props['name']));
|
||||
@@ -337,7 +337,7 @@ class Blueprint
|
||||
|
||||
$normalize = function ($props) use ($name) {
|
||||
// inject the filename as name if no name is set
|
||||
$props['name'] = $props['name'] ?? $name;
|
||||
$props['name'] ??= $name;
|
||||
|
||||
// normalize the title
|
||||
$title = $props['title'] ?? ucfirst($props['name']);
|
||||
@@ -567,9 +567,7 @@ class Blueprint
|
||||
|
||||
// set all options to false
|
||||
if ($options === false) {
|
||||
return array_map(function () {
|
||||
return false;
|
||||
}, $defaults);
|
||||
return array_map(fn () => false, $defaults);
|
||||
}
|
||||
|
||||
// extend options if possible
|
||||
@@ -579,7 +577,7 @@ class Blueprint
|
||||
$alias = $aliases[$key] ?? null;
|
||||
|
||||
if ($alias !== null) {
|
||||
$options[$alias] = $options[$alias] ?? $value;
|
||||
$options[$alias] ??= $value;
|
||||
unset($options[$key]);
|
||||
}
|
||||
}
|
||||
@@ -765,9 +763,10 @@ class Blueprint
|
||||
*/
|
||||
public function sections(): array
|
||||
{
|
||||
return array_map(function ($section) {
|
||||
return $this->section($section['name']);
|
||||
}, $this->sections);
|
||||
return A::map(
|
||||
$this->sections,
|
||||
fn ($section) => $this->section($section['name'])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -208,7 +208,7 @@ class ContentLock
|
||||
}
|
||||
|
||||
// add lock user to unlocked data
|
||||
$this->data['unlock'] = $this->data['unlock'] ?? [];
|
||||
$this->data['unlock'] ??= [];
|
||||
$this->data['unlock'][] = $this->data['lock']['user'];
|
||||
|
||||
return $this->clearLock();
|
||||
|
@@ -208,7 +208,7 @@ class ContentTranslation
|
||||
*/
|
||||
public function slug(): ?string
|
||||
{
|
||||
return $this->slug = $this->slug ?? ($this->content()['slug'] ?? null);
|
||||
return $this->slug ??= ($this->content()['slug'] ?? null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -167,7 +167,7 @@ class Core
|
||||
*/
|
||||
public function components(): array
|
||||
{
|
||||
return $this->cache['components'] ?? $this->cache['components'] = include $this->root . '/components.php';
|
||||
return $this->cache['components'] ??= include $this->root . '/components.php';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -203,7 +203,7 @@ class Core
|
||||
*/
|
||||
public function fieldMethods(): array
|
||||
{
|
||||
return $this->cache['fieldMethods'] ?? $this->cache['fieldMethods'] = (include $this->root . '/methods.php')($this->kirby);
|
||||
return $this->cache['fieldMethods'] ??= (include $this->root . '/methods.php')($this->kirby);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -295,7 +295,7 @@ class Core
|
||||
*/
|
||||
public function kirbyTags(): array
|
||||
{
|
||||
return $this->cache['kirbytags'] ?? $this->cache['kirbytags'] = include $this->root . '/tags.php';
|
||||
return $this->cache['kirbytags'] ??= include $this->root . '/tags.php';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -321,7 +321,7 @@ class Core
|
||||
*/
|
||||
public function roots(): array
|
||||
{
|
||||
return $this->cache['roots'] ?? $this->cache['roots'] = [
|
||||
return $this->cache['roots'] ??= [
|
||||
// kirby
|
||||
'kirby' => function (array $roots) {
|
||||
return dirname(__DIR__, 2);
|
||||
@@ -428,7 +428,7 @@ class Core
|
||||
*/
|
||||
public function routes(): array
|
||||
{
|
||||
return $this->cache['routes'] ?? $this->cache['routes'] = (include $this->root . '/routes.php')($this->kirby);
|
||||
return $this->cache['routes'] ??= (include $this->root . '/routes.php')($this->kirby);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -517,7 +517,7 @@ class Core
|
||||
*/
|
||||
public function urls(): array
|
||||
{
|
||||
return $this->cache['urls'] ?? $this->cache['urls'] = [
|
||||
return $this->cache['urls'] ??= [
|
||||
'index' => function () {
|
||||
return Url::index();
|
||||
},
|
||||
|
@@ -3,6 +3,7 @@
|
||||
namespace Kirby\Cms;
|
||||
|
||||
use Closure;
|
||||
use Kirby\Toolkit\A;
|
||||
use Kirby\Toolkit\I18n;
|
||||
use Kirby\Toolkit\Str;
|
||||
|
||||
@@ -42,7 +43,7 @@ class Fieldsets extends Items
|
||||
$fieldset = Blueprint::extend($fieldset);
|
||||
|
||||
// make sure the type is always set
|
||||
$fieldset['type'] = $fieldset['type'] ?? $type;
|
||||
$fieldset['type'] ??= $type;
|
||||
|
||||
// extract groups
|
||||
if ($fieldset['type'] === 'group') {
|
||||
@@ -69,7 +70,7 @@ class Fieldsets extends Items
|
||||
|
||||
public static function factory(array $items = null, array $params = [])
|
||||
{
|
||||
$items = $items ?? option('blocks.fieldsets', [
|
||||
$items ??= option('blocks.fieldsets', [
|
||||
'code' => 'blocks/code',
|
||||
'gallery' => 'blocks/gallery',
|
||||
'heading' => 'blocks/heading',
|
||||
@@ -94,8 +95,9 @@ class Fieldsets extends Items
|
||||
|
||||
public function toArray(?Closure $map = null): array
|
||||
{
|
||||
return array_map($map ?? function ($fieldset) {
|
||||
return $fieldset->toArray();
|
||||
}, $this->data);
|
||||
return A::map(
|
||||
$this->data,
|
||||
$map ?? fn ($fieldset) => $fieldset->toArray()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -6,6 +6,7 @@ use Kirby\Filesystem\F;
|
||||
use Kirby\Filesystem\IsFile;
|
||||
use Kirby\Panel\File as Panel;
|
||||
use Kirby\Toolkit\A;
|
||||
use Kirby\Toolkit\Str;
|
||||
|
||||
/**
|
||||
* The `$file` object provides a set
|
||||
@@ -362,14 +363,9 @@ class File extends ModelWithContent
|
||||
$file = $this->modifiedFile();
|
||||
$content = $this->modifiedContent($languageCode);
|
||||
$modified = max($file, $content);
|
||||
$handler ??= $this->kirby()->option('date.handler', 'date');
|
||||
|
||||
if (is_null($format) === true) {
|
||||
return $modified;
|
||||
}
|
||||
|
||||
$handler = $handler ?? $this->kirby()->option('date.handler', 'date');
|
||||
|
||||
return $handler($format, $modified);
|
||||
return Str::date($modified, $format, $handler);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -422,7 +418,7 @@ class File extends ModelWithContent
|
||||
*/
|
||||
public function parent()
|
||||
{
|
||||
return $this->parent = $this->parent ?? $this->kirby()->site();
|
||||
return $this->parent ??= $this->kirby()->site();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -472,7 +468,7 @@ class File extends ModelWithContent
|
||||
*/
|
||||
public function root(): ?string
|
||||
{
|
||||
return $this->root = $this->root ?? $this->parent()->root() . '/' . $this->filename();
|
||||
return $this->root ??= $this->parent()->root() . '/' . $this->filename();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -598,7 +594,7 @@ class File extends ModelWithContent
|
||||
*/
|
||||
public function template(): ?string
|
||||
{
|
||||
return $this->template = $this->template ?? $this->content()->get('template')->value();
|
||||
return $this->template ??= $this->content()->get('template')->value();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -631,7 +627,7 @@ class File extends ModelWithContent
|
||||
*/
|
||||
public function url(): string
|
||||
{
|
||||
return $this->url ?? $this->url = ($this->kirby()->component('file::url'))($this->kirby(), $this);
|
||||
return $this->url ??= ($this->kirby()->component('file::url'))($this->kirby(), $this);
|
||||
}
|
||||
|
||||
|
||||
|
@@ -163,17 +163,24 @@ class FileBlueprint extends Blueprint
|
||||
|
||||
// normalize the MIME, extension and type from strings into arrays
|
||||
if (is_string($accept['mime']) === true) {
|
||||
$accept['mime'] = array_map(function ($mime) {
|
||||
return $mime['value'];
|
||||
}, Str::accepted($accept['mime']));
|
||||
$accept['mime'] = array_map(
|
||||
fn ($mime) => $mime['value'],
|
||||
Str::accepted($accept['mime'])
|
||||
);
|
||||
}
|
||||
|
||||
if (is_string($accept['extension']) === true) {
|
||||
$accept['extension'] = array_map('trim', explode(',', $accept['extension']));
|
||||
$accept['extension'] = array_map(
|
||||
'trim',
|
||||
explode(',', $accept['extension'])
|
||||
);
|
||||
}
|
||||
|
||||
if (is_string($accept['type']) === true) {
|
||||
$accept['type'] = array_map('trim', explode(',', $accept['type']));
|
||||
$accept['type'] = array_map(
|
||||
'trim',
|
||||
explode(',', $accept['type'])
|
||||
);
|
||||
}
|
||||
|
||||
return $accept;
|
||||
|
@@ -203,9 +203,10 @@ trait FileModifications
|
||||
|
||||
if (
|
||||
is_a($result, 'Kirby\Cms\FileVersion') === false &&
|
||||
is_a($result, 'Kirby\Cms\File') === false
|
||||
is_a($result, 'Kirby\Cms\File') === false &&
|
||||
is_a($result, 'Kirby\Filesystem\Asset') === false
|
||||
) {
|
||||
throw new InvalidArgumentException('The file::version component must return a File or FileVersion object');
|
||||
throw new InvalidArgumentException('The file::version component must return a File, FileVersion or Asset object');
|
||||
}
|
||||
|
||||
return $result;
|
||||
|
@@ -87,9 +87,10 @@ class LanguageRouter
|
||||
$patterns = A::wrap($route['pattern']);
|
||||
|
||||
// prefix all patterns with the page slug
|
||||
$patterns = array_map(function ($pattern) use ($page, $language) {
|
||||
return $page->uri($language) . '/' . $pattern;
|
||||
}, $patterns);
|
||||
$patterns = A::map(
|
||||
$patterns,
|
||||
fn ($pattern) => $page->uri($language) . '/' . $pattern
|
||||
);
|
||||
|
||||
// re-inject the pattern and the full page object
|
||||
$routes[$index]['pattern'] = $patterns;
|
||||
|
@@ -25,9 +25,10 @@ class Languages extends Collection
|
||||
*/
|
||||
public function __construct($objects = [], $parent = null)
|
||||
{
|
||||
$defaults = array_filter($objects, function ($language) {
|
||||
return $language->isDefault() === true;
|
||||
});
|
||||
$defaults = array_filter(
|
||||
$objects,
|
||||
fn ($language) => $language->isDefault() === true
|
||||
);
|
||||
|
||||
if (count($defaults) > 1) {
|
||||
throw new DuplicateException('You cannot have multiple default languages. Please check your language config files.');
|
||||
@@ -87,8 +88,9 @@ class Languages extends Collection
|
||||
$props = F::load($file);
|
||||
|
||||
if (is_array($props) === true) {
|
||||
// inject the language code from the filename if it does not exist
|
||||
$props['code'] = $props['code'] ?? F::name($file);
|
||||
// inject the language code from the filename
|
||||
// if it does not exist
|
||||
$props['code'] ??= F::name($file);
|
||||
|
||||
$languages[] = new Language($props);
|
||||
}
|
||||
|
@@ -67,7 +67,7 @@ abstract class Model
|
||||
*/
|
||||
public function kirby()
|
||||
{
|
||||
return static::$kirby = static::$kirby ?? App::instance();
|
||||
return static::$kirby ??= App::instance();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,7 +77,7 @@ abstract class Model
|
||||
*/
|
||||
public function site()
|
||||
{
|
||||
return $this->site = $this->site ?? $this->kirby()->site();
|
||||
return $this->site ??= $this->kirby()->site();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -382,7 +382,7 @@ class Page extends ModelWithContent
|
||||
*/
|
||||
public function depth(): int
|
||||
{
|
||||
return $this->depth = $this->depth ?? (substr_count($this->id(), '/') + 1);
|
||||
return $this->depth ??= (substr_count($this->id(), '/') + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1102,7 +1102,7 @@ class Page extends ModelWithContent
|
||||
*/
|
||||
public function root(): string
|
||||
{
|
||||
return $this->root = $this->root ?? $this->kirby()->root('content') . '/' . $this->diruri();
|
||||
return $this->root ??= $this->kirby()->root('content') . '/' . $this->diruri();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -151,7 +151,7 @@ class Pages extends Collection
|
||||
*/
|
||||
public static function factory(array $pages, Model $model = null, bool $draft = false)
|
||||
{
|
||||
$model = $model ?? App::instance()->site();
|
||||
$model ??= App::instance()->site();
|
||||
$children = new static([], $model);
|
||||
$kirby = $model->kirby();
|
||||
|
||||
|
@@ -69,9 +69,9 @@ class Pagination extends BasePagination
|
||||
$config = $kirby->option('pagination', []);
|
||||
$request = $kirby->request();
|
||||
|
||||
$params['limit'] = $params['limit'] ?? $config['limit'] ?? 20;
|
||||
$params['method'] = $params['method'] ?? $config['method'] ?? 'param';
|
||||
$params['variable'] = $params['variable'] ?? $config['variable'] ?? 'page';
|
||||
$params['limit'] ??= $config['limit'] ?? 20;
|
||||
$params['method'] ??= $config['method'] ?? 'param';
|
||||
$params['variable'] ??= $config['variable'] ?? 'page';
|
||||
|
||||
if (empty($params['url']) === true) {
|
||||
$params['url'] = new Uri($kirby->url('current'), [
|
||||
@@ -81,9 +81,9 @@ class Pagination extends BasePagination
|
||||
}
|
||||
|
||||
if ($params['method'] === 'query') {
|
||||
$params['page'] = $params['page'] ?? $params['url']->query()->get($params['variable']);
|
||||
$params['page'] ??= $params['url']->query()->get($params['variable']);
|
||||
} elseif ($params['method'] === 'param') {
|
||||
$params['page'] = $params['page'] ?? $params['url']->params()->get($params['variable']);
|
||||
$params['page'] ??= $params['url']->params()->get($params['variable']);
|
||||
}
|
||||
|
||||
parent::__construct($params);
|
||||
|
@@ -210,7 +210,7 @@ class Role extends Model
|
||||
*/
|
||||
public function title(): string
|
||||
{
|
||||
return $this->title = $this->title ?? ucfirst($this->name());
|
||||
return $this->title ??= ucfirst($this->name());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -49,8 +49,8 @@ class Section extends Component
|
||||
}
|
||||
|
||||
// use the type as fallback for the name
|
||||
$attrs['name'] = $attrs['name'] ?? $type;
|
||||
$attrs['type'] = $type;
|
||||
$attrs['name'] ??= $type;
|
||||
$attrs['type'] = $type;
|
||||
|
||||
parent::__construct($type, $attrs);
|
||||
}
|
||||
|
@@ -463,7 +463,7 @@ class Site extends ModelWithContent
|
||||
*/
|
||||
public function root(): string
|
||||
{
|
||||
return $this->root = $this->root ?? $this->kirby()->root('content');
|
||||
return $this->root ??= $this->kirby()->root('content');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -405,7 +405,7 @@ class System
|
||||
{
|
||||
return
|
||||
version_compare(PHP_VERSION, '7.4.0', '>=') === true &&
|
||||
version_compare(PHP_VERSION, '8.1.0', '<') === true;
|
||||
version_compare(PHP_VERSION, '8.2.0', '<') === true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -508,7 +508,7 @@ class System
|
||||
];
|
||||
}
|
||||
|
||||
$software = $_SERVER['SERVER_SOFTWARE'] ?? null;
|
||||
$software = $_SERVER['SERVER_SOFTWARE'] ?? '';
|
||||
|
||||
preg_match('!(' . implode('|', $servers) . ')!i', $software, $matches);
|
||||
|
||||
|
@@ -78,7 +78,11 @@ class Template
|
||||
*/
|
||||
public function exists(): bool
|
||||
{
|
||||
return file_exists($this->file());
|
||||
if ($file = $this->file()) {
|
||||
return file_exists($file);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -228,7 +228,7 @@ class User extends ModelWithContent
|
||||
|
||||
protected function credentials(): array
|
||||
{
|
||||
return $this->credentials = $this->credentials ?? $this->readCredentials();
|
||||
return $this->credentials ??= $this->readCredentials();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -238,7 +238,7 @@ class User extends ModelWithContent
|
||||
*/
|
||||
public function email(): ?string
|
||||
{
|
||||
return $this->email = $this->email ?? $this->credentials()['email'] ?? null;
|
||||
return $this->email ??= $this->credentials()['email'] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -403,7 +403,7 @@ class User extends ModelWithContent
|
||||
*/
|
||||
public function language(): string
|
||||
{
|
||||
return $this->language ?? $this->language = $this->credentials()['language'] ?? $this->kirby()->panelLanguage();
|
||||
return $this->language ??= $this->credentials()['language'] ?? $this->kirby()->panelLanguage();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -530,9 +530,9 @@ class User extends ModelWithContent
|
||||
$modifiedContent = F::modified($this->contentFile($languageCode));
|
||||
$modifiedIndex = F::modified($this->root() . '/index.php');
|
||||
$modifiedTotal = max([$modifiedContent, $modifiedIndex]);
|
||||
$handler = $handler ?? $this->kirby()->option('date.handler', 'date');
|
||||
$handler ??= $this->kirby()->option('date.handler', 'date');
|
||||
|
||||
return $handler($format, $modifiedTotal);
|
||||
return Str::date($modifiedTotal, $format, $handler);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -65,7 +65,7 @@ class Data
|
||||
static::$handlers[static::$aliases[$type] ?? null] ??
|
||||
null;
|
||||
|
||||
if (class_exists($handler)) {
|
||||
if ($handler !== null && class_exists($handler)) {
|
||||
return new $handler();
|
||||
}
|
||||
|
||||
|
@@ -212,6 +212,12 @@ class Database
|
||||
$this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
$this->connection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
|
||||
|
||||
// TODO: behavior without this attribute would be preferrable
|
||||
// (actual types instead of all strings) but would be a breaking change
|
||||
if ($this->type === 'sqlite') {
|
||||
$this->connection->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true);
|
||||
}
|
||||
|
||||
// store the connection
|
||||
static::$connections[$this->id] = $this;
|
||||
|
||||
|
@@ -45,7 +45,7 @@ class Db
|
||||
|
||||
// try to connect with the default
|
||||
// connection settings if no params are set
|
||||
$defaults = [
|
||||
$params ??= [
|
||||
'type' => Config::get('db.type', 'mysql'),
|
||||
'host' => Config::get('db.host', 'localhost'),
|
||||
'user' => Config::get('db.user', 'root'),
|
||||
@@ -54,7 +54,6 @@ class Db
|
||||
'prefix' => Config::get('db.prefix', ''),
|
||||
'port' => Config::get('db.port', '')
|
||||
];
|
||||
$params = $params ?? $defaults;
|
||||
|
||||
return static::$connection = new Database($params);
|
||||
}
|
||||
|
@@ -290,9 +290,10 @@ abstract class Sql
|
||||
// add keys
|
||||
foreach ($inner['keys'] as $key => $columns) {
|
||||
// quote each column name and make a list string out of the column names
|
||||
$columns = implode(', ', array_map(function ($name) {
|
||||
return $this->quoteIdentifier($name);
|
||||
}, $columns));
|
||||
$columns = implode(', ', array_map(
|
||||
fn ($name) => $this->quoteIdentifier($name),
|
||||
$columns
|
||||
));
|
||||
|
||||
if ($key === 'primary') {
|
||||
$key = 'PRIMARY KEY';
|
||||
@@ -526,7 +527,7 @@ abstract class Sql
|
||||
];
|
||||
}
|
||||
|
||||
$limit = $limit ?? '18446744073709551615';
|
||||
$limit ??= '18446744073709551615';
|
||||
|
||||
$offsetBinding = $this->bindingName('offset');
|
||||
$limitBinding = $this->bindingName('limit');
|
||||
|
@@ -82,9 +82,10 @@ class Sqlite extends Sql
|
||||
$keys = [];
|
||||
foreach ($inner['keys'] as $key => $columns) {
|
||||
// quote each column name and make a list string out of the column names
|
||||
$columns = implode(', ', array_map(function ($name) {
|
||||
return $this->quoteIdentifier($name);
|
||||
}, $columns));
|
||||
$columns = implode(', ', array_map(
|
||||
fn ($name) => $this->quoteIdentifier($name),
|
||||
$columns
|
||||
));
|
||||
|
||||
if ($key === 'primary') {
|
||||
$inner['query'] .= ',' . PHP_EOL . 'PRIMARY KEY (' . $columns . ')';
|
||||
|
@@ -128,7 +128,7 @@ class Exception extends \Exception
|
||||
]);
|
||||
|
||||
// handover to Exception parent class constructor
|
||||
parent::__construct($message, null, $args['previous'] ?? null);
|
||||
parent::__construct($message, 0, $args['previous'] ?? null);
|
||||
}
|
||||
|
||||
// set the Exception code to the key
|
||||
|
@@ -5,6 +5,7 @@ namespace Kirby\Filesystem;
|
||||
use Exception;
|
||||
use Kirby\Cms\App;
|
||||
use Kirby\Cms\Page;
|
||||
use Kirby\Toolkit\Str;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
@@ -450,7 +451,7 @@ class Dir
|
||||
$modified = ($newModified > $modified) ? $newModified : $modified;
|
||||
}
|
||||
|
||||
return $format !== null ? $handler($format, $modified) : $modified;
|
||||
return Str::date($modified, $format, $handler);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -504,8 +505,8 @@ class Dir
|
||||
}
|
||||
|
||||
// create the ignore pattern
|
||||
$ignore = $ignore ?? static::$ignore;
|
||||
$ignore = array_merge($ignore, ['.', '..']);
|
||||
$ignore ??= static::$ignore;
|
||||
$ignore = array_merge($ignore, ['.', '..']);
|
||||
|
||||
// scan for all files and dirs
|
||||
$result = array_values((array)array_diff(scandir($dir), $ignore));
|
||||
|
@@ -475,11 +475,7 @@ class F
|
||||
|
||||
$modified = filemtime($file);
|
||||
|
||||
if (is_null($format) === true) {
|
||||
return $modified;
|
||||
}
|
||||
|
||||
return $handler($format, $modified);
|
||||
return Str::date($modified, $format, $handler);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -109,9 +109,10 @@ class Filename
|
||||
'q' => $this->quality(),
|
||||
];
|
||||
|
||||
$array = array_filter($array, function ($item) {
|
||||
return $item !== null && $item !== false && $item !== '';
|
||||
});
|
||||
$array = array_filter(
|
||||
$array,
|
||||
fn ($item) => $item !== null && $item !== false && $item !== ''
|
||||
);
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
@@ -320,7 +320,7 @@ class Mime
|
||||
}
|
||||
|
||||
// get the extension or extract it from the filename
|
||||
$extension = $extension ?? F::extension($file);
|
||||
$extension ??= F::extension($file);
|
||||
|
||||
// try to guess the mime type at least
|
||||
if ($mime === false) {
|
||||
|
@@ -71,8 +71,8 @@ class Field extends Component
|
||||
$this->formFields = $formFields;
|
||||
|
||||
// use the type as fallback for the name
|
||||
$attrs['name'] = $attrs['name'] ?? $type;
|
||||
$attrs['type'] = $type;
|
||||
$attrs['name'] ??= $type;
|
||||
$attrs['type'] = $type;
|
||||
|
||||
parent::__construct($type, $attrs);
|
||||
}
|
||||
@@ -440,9 +440,10 @@ class Field extends Component
|
||||
|
||||
ksort($array);
|
||||
|
||||
return array_filter($array, function ($item) {
|
||||
return $item !== null && is_object($item) === false;
|
||||
});
|
||||
return array_filter(
|
||||
$array,
|
||||
fn ($item) => $item !== null && is_object($item) === false
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -49,7 +49,7 @@ class BlocksField extends FieldClass
|
||||
$type = $block['type'];
|
||||
|
||||
// get and cache fields at the same time
|
||||
$fields[$type] = $fields[$type] ?? $this->fields($block['type']);
|
||||
$fields[$type] ??= $this->fields($block['type']);
|
||||
|
||||
// overwrite the block content with form values
|
||||
$block['content'] = $this->form($fields[$type], $block['content'])->$to();
|
||||
|
@@ -116,9 +116,10 @@ class LayoutField extends BlocksField
|
||||
|
||||
protected function setLayouts(array $layouts = [])
|
||||
{
|
||||
$this->layouts = array_map(function ($layout) {
|
||||
return Str::split($layout);
|
||||
}, $layouts);
|
||||
$this->layouts = array_map(
|
||||
fn ($layout) => Str::split($layout),
|
||||
$layouts
|
||||
);
|
||||
}
|
||||
|
||||
protected function setSettings($settings = null)
|
||||
|
@@ -726,9 +726,7 @@ abstract class FieldClass
|
||||
|
||||
ksort($props);
|
||||
|
||||
return array_filter($props, function ($item) {
|
||||
return $item !== null;
|
||||
});
|
||||
return array_filter($props, fn ($item) => $item !== null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -29,7 +29,7 @@ class Fields extends Collection
|
||||
{
|
||||
if (is_array($field) === true) {
|
||||
// use the array key as name if the name is not set
|
||||
$field['name'] = $field['name'] ?? $name;
|
||||
$field['name'] ??= $name;
|
||||
$field = Field::factory($field['type'], $field, $this);
|
||||
}
|
||||
|
||||
|
@@ -268,9 +268,9 @@ class Form
|
||||
}
|
||||
|
||||
// set a few defaults
|
||||
$props['values'] = array_merge($original, $values);
|
||||
$props['fields'] = $props['fields'] ?? [];
|
||||
$props['model'] = $model;
|
||||
$props['values'] = array_merge($original, $values);
|
||||
$props['fields'] ??= [];
|
||||
$props['model'] = $model;
|
||||
|
||||
// search for the blueprint
|
||||
if (method_exists($model, 'blueprint') === true && $blueprint = $model->blueprint()) {
|
||||
|
@@ -45,10 +45,10 @@ class Options
|
||||
*/
|
||||
public static function api($api, $model = null): array
|
||||
{
|
||||
$model = $model ?? App::instance()->site();
|
||||
$fetch = null;
|
||||
$text = null;
|
||||
$value = null;
|
||||
$model ??= App::instance()->site();
|
||||
$fetch = null;
|
||||
$text = null;
|
||||
$value = null;
|
||||
|
||||
if (is_array($api) === true) {
|
||||
$fetch = $api['fetch'] ?? null;
|
||||
@@ -165,7 +165,7 @@ class Options
|
||||
*/
|
||||
public static function query($query, $model = null): array
|
||||
{
|
||||
$model = $model ?? App::instance()->site();
|
||||
$model ??= App::instance()->site();
|
||||
|
||||
// default text setup
|
||||
$text = [
|
||||
|
@@ -3,7 +3,6 @@
|
||||
namespace Kirby\Http;
|
||||
|
||||
use Kirby\Toolkit\Str;
|
||||
use TrueBV\Punycode;
|
||||
|
||||
/**
|
||||
* Handles Internationalized Domain Names
|
||||
@@ -16,14 +15,26 @@ use TrueBV\Punycode;
|
||||
*/
|
||||
class Idn
|
||||
{
|
||||
/**
|
||||
* Convert domain name from IDNA ASCII to Unicode
|
||||
*
|
||||
* @param string $domain
|
||||
* @return string|false
|
||||
*/
|
||||
public static function decode(string $domain)
|
||||
{
|
||||
return (new Punycode())->decode($domain);
|
||||
return idn_to_utf8($domain);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert domain name to IDNA ASCII form
|
||||
*
|
||||
* @param string $domain
|
||||
* @return string|false
|
||||
*/
|
||||
public static function encode(string $domain)
|
||||
{
|
||||
return (new Punycode())->encode($domain);
|
||||
return idn_to_ascii($domain);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -43,7 +43,7 @@ class Query extends Obj
|
||||
|
||||
public function toString($questionMark = false): string
|
||||
{
|
||||
$query = http_build_query($this, null, '&', PHP_QUERY_RFC3986);
|
||||
$query = http_build_query($this, '', '&', PHP_QUERY_RFC3986);
|
||||
|
||||
if (empty($query) === true) {
|
||||
return '';
|
||||
|
@@ -174,7 +174,7 @@ class Request
|
||||
*/
|
||||
public function body()
|
||||
{
|
||||
return $this->body = $this->body ?? new Body();
|
||||
return $this->body ??= new Body();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -220,7 +220,7 @@ class Request
|
||||
$methods = ['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'CONNECT', 'OPTIONS', 'TRACE', 'PATCH'];
|
||||
|
||||
// the request method can be overwritten with a header
|
||||
$methodOverride = strtoupper($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'] ?? null);
|
||||
$methodOverride = strtoupper($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'] ?? '');
|
||||
|
||||
if ($method === null && in_array($methodOverride, $methods) === true) {
|
||||
$method = $methodOverride;
|
||||
@@ -269,7 +269,7 @@ class Request
|
||||
*/
|
||||
public function files()
|
||||
{
|
||||
return $this->files = $this->files ?? new Files();
|
||||
return $this->files ??= new Files();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -379,7 +379,7 @@ class Request
|
||||
*/
|
||||
public function query()
|
||||
{
|
||||
return $this->query = $this->query ?? new Query();
|
||||
return $this->query ??= new Query();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -407,6 +407,6 @@ class Request
|
||||
return $this->url()->clone($props);
|
||||
}
|
||||
|
||||
return $this->url = $this->url ?? Uri::current();
|
||||
return $this->url ??= Uri::current();
|
||||
}
|
||||
}
|
||||
|
@@ -160,14 +160,14 @@ class Response
|
||||
throw new Exception('The file could not be found');
|
||||
}
|
||||
|
||||
$filename = $filename ?? basename($file);
|
||||
$modified = filemtime($file);
|
||||
$body = file_get_contents($file);
|
||||
$size = strlen($body);
|
||||
$filename ??= basename($file);
|
||||
$modified = filemtime($file);
|
||||
$body = file_get_contents($file);
|
||||
$size = strlen($body);
|
||||
|
||||
$props = array_replace_recursive([
|
||||
'body' => $body,
|
||||
'type' => 'application/force-download',
|
||||
'type' => F::mime($file),
|
||||
'headers' => [
|
||||
'Pragma' => 'public',
|
||||
'Cache-Control' => 'no-cache, no-store, must-revalidate',
|
||||
@@ -234,7 +234,7 @@ class Response
|
||||
public static function json($body = '', ?int $code = null, ?bool $pretty = null, array $headers = [])
|
||||
{
|
||||
if (is_array($body) === true) {
|
||||
$body = json_encode($body, $pretty === true ? JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES : null);
|
||||
$body = json_encode($body, $pretty === true ? JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES : 0);
|
||||
}
|
||||
|
||||
return new static([
|
||||
|
@@ -5,6 +5,7 @@ namespace Kirby\Http;
|
||||
use Closure;
|
||||
use Exception;
|
||||
use InvalidArgumentException;
|
||||
use Kirby\Toolkit\A;
|
||||
|
||||
/**
|
||||
* @package Kirby Http
|
||||
@@ -59,8 +60,11 @@ class Router
|
||||
throw new InvalidArgumentException('Invalid route parameters');
|
||||
}
|
||||
|
||||
$methods = array_map('trim', explode('|', strtoupper($props['method'] ?? 'GET')));
|
||||
$patterns = is_array($props['pattern']) === false ? [$props['pattern']] : $props['pattern'];
|
||||
$patterns = A::wrap($props['pattern']);
|
||||
$methods = A::map(
|
||||
explode('|', strtoupper($props['method'] ?? 'GET')),
|
||||
'trim'
|
||||
);
|
||||
|
||||
if ($methods === ['ALL']) {
|
||||
$methods = array_keys($this->routes);
|
||||
@@ -88,7 +92,7 @@ class Router
|
||||
*/
|
||||
public function call(string $path = null, string $method = 'GET', Closure $callback = null)
|
||||
{
|
||||
$path = $path ?? '';
|
||||
$path ??= '';
|
||||
$ignore = [];
|
||||
$result = null;
|
||||
$loop = true;
|
||||
|
@@ -92,6 +92,9 @@ class Server
|
||||
*/
|
||||
public static function sanitize(string $key, $value)
|
||||
{
|
||||
// make sure $value is not null
|
||||
$value ??= '';
|
||||
|
||||
switch ($key) {
|
||||
case 'SERVER_ADDR':
|
||||
case 'SERVER_NAME':
|
||||
@@ -100,7 +103,7 @@ class Server
|
||||
$value = strip_tags($value);
|
||||
$value = preg_replace('![^\w.:-]+!iu', '', $value);
|
||||
$value = trim($value, '-');
|
||||
$value = htmlspecialchars($value);
|
||||
$value = htmlspecialchars($value, ENT_COMPAT);
|
||||
break;
|
||||
case 'SERVER_PORT':
|
||||
case 'HTTP_X_FORWARDED_PORT':
|
||||
|
@@ -144,10 +144,10 @@ class Uri
|
||||
|
||||
// parse the path and extract params
|
||||
if (empty($props['path']) === false) {
|
||||
$extract = Params::extract($props['path']);
|
||||
$props['params'] = $props['params'] ?? $extract['params'];
|
||||
$props['path'] = $extract['path'];
|
||||
$props['slash'] = $props['slash'] ?? $extract['slash'];
|
||||
$extract = Params::extract($props['path']);
|
||||
$props['params'] ??= $extract['params'];
|
||||
$props['path'] = $extract['path'];
|
||||
$props['slash'] ??= $extract['slash'];
|
||||
}
|
||||
|
||||
$this->setProperties($this->props = $props);
|
||||
@@ -246,8 +246,12 @@ class Uri
|
||||
return static::$current;
|
||||
}
|
||||
|
||||
$uri = Server::get('REQUEST_URI');
|
||||
$uri = preg_replace('!^(http|https)\:\/\/' . Server::get('HTTP_HOST') . '!', '', $uri);
|
||||
$uri = Server::get('REQUEST_URI') ?? '';
|
||||
$uri = preg_replace(
|
||||
'!^(http|https)\:\/\/' . Server::get('HTTP_HOST') . '!',
|
||||
'',
|
||||
$uri
|
||||
);
|
||||
$uri = parse_url('http://getkirby.com' . $uri);
|
||||
|
||||
$url = new static(array_merge([
|
||||
|
@@ -145,8 +145,8 @@ class Url
|
||||
}
|
||||
|
||||
// build the full url
|
||||
$path = ltrim($path, '/');
|
||||
$home = $home ?? static::home();
|
||||
$path = ltrim($path, '/');
|
||||
$home ??= static::home();
|
||||
|
||||
if (empty($path) === true) {
|
||||
return $home;
|
||||
@@ -260,6 +260,9 @@ class Url
|
||||
*/
|
||||
public static function to(string $path = null, $options = null): string
|
||||
{
|
||||
// make sure $path is string
|
||||
$path ??= '';
|
||||
|
||||
// keep relative urls
|
||||
if (substr($path, 0, 2) === './' || substr($path, 0, 3) === '../') {
|
||||
return $path;
|
||||
|
@@ -177,7 +177,7 @@ class ImageMagick extends Darkroom
|
||||
{
|
||||
// simple resize
|
||||
if ($options['crop'] === false) {
|
||||
return sprintf('-resize %sx%s!', $options['width'], $options['height']);
|
||||
return sprintf('-thumbnail %sx%s!', $options['width'], $options['height']);
|
||||
}
|
||||
|
||||
$gravities = [
|
||||
@@ -195,7 +195,7 @@ class ImageMagick extends Darkroom
|
||||
// translate the gravity option into something imagemagick understands
|
||||
$gravity = $gravities[$options['crop']] ?? 'Center';
|
||||
|
||||
$command = sprintf('-resize %sx%s^', $options['width'], $options['height']);
|
||||
$command = sprintf('-thumbnail %sx%s^', $options['width'], $options['height']);
|
||||
$command .= sprintf(' -gravity %s -crop %sx%s+0+0', $gravity, $options['width'], $options['height']);
|
||||
|
||||
return $command;
|
||||
@@ -227,6 +227,14 @@ class ImageMagick extends Darkroom
|
||||
*/
|
||||
protected function strip(string $file, array $options): string
|
||||
{
|
||||
return '-strip';
|
||||
if (F::extension($file) === 'png') {
|
||||
// ImageMagick does not support keeping ICC profiles while
|
||||
// stripping other privacy- and security-related information,
|
||||
// such as GPS data; so discard all color profiles for PNG files
|
||||
// (tested with ImageMagick 7.0.11-14 Q16 x86_64 2021-05-31)
|
||||
return '-strip';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
@@ -116,7 +116,7 @@ class Image extends File
|
||||
*/
|
||||
public function exif()
|
||||
{
|
||||
return $this->exif = $this->exif ?? new Exif($this);
|
||||
return $this->exif ??= new Exif($this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -130,9 +130,10 @@ class Document
|
||||
|
||||
// remove missing files
|
||||
$assets['css'] = array_filter($assets['css']);
|
||||
$assets['js'] = array_filter($assets['js'], function ($js) {
|
||||
return empty($js['src']) === false;
|
||||
});
|
||||
$assets['js'] = array_filter(
|
||||
$assets['js'],
|
||||
fn ($js) => empty($js['src']) === false
|
||||
);
|
||||
|
||||
return $assets;
|
||||
}
|
||||
|
@@ -316,7 +316,7 @@ class File extends Model
|
||||
$absolute = $parent !== $params['model'];
|
||||
}
|
||||
|
||||
$params['text'] = $params['text'] ?? '{{ file.filename }}';
|
||||
$params['text'] ??= '{{ file.filename }}';
|
||||
|
||||
return array_merge(parent::pickerData($params), [
|
||||
'filename' => $name,
|
||||
|
@@ -68,7 +68,7 @@ abstract class Json
|
||||
}
|
||||
|
||||
// always inject the response code
|
||||
$data['code'] = $data['code'] ?? 200;
|
||||
$data['code'] ??= 200;
|
||||
$data['path'] = $options['path'] ?? null;
|
||||
$data['referrer'] = Panel::referrer();
|
||||
|
||||
|
@@ -77,7 +77,7 @@ abstract class Model
|
||||
*/
|
||||
public function dragTextType(string $type = null): string
|
||||
{
|
||||
$type = $type ?? 'auto';
|
||||
$type ??= 'auto';
|
||||
|
||||
if ($type === 'auto') {
|
||||
$type = option('panel.kirbytext', true) ? 'kirbytext' : 'markdown';
|
||||
@@ -141,8 +141,8 @@ abstract class Model
|
||||
// main url
|
||||
$settings['url'] = $image->url();
|
||||
|
||||
// only create srcsets for actual File objects
|
||||
if (is_a($image, 'Kirby\Cms\File') === true) {
|
||||
// only create srcsets for resizable files
|
||||
if ($image->isResizable() === true) {
|
||||
$settings['src'] = static::imagePlaceholder();
|
||||
|
||||
switch ($layout) {
|
||||
@@ -174,6 +174,8 @@ abstract class Model
|
||||
]
|
||||
]);
|
||||
}
|
||||
} elseif ($image->isViewable() === true) {
|
||||
$settings['src'] = $image->url();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -231,7 +231,7 @@ class Page extends Model
|
||||
*/
|
||||
public function pickerData(array $params = []): array
|
||||
{
|
||||
$params['text'] = $params['text'] ?? '{{ page.title }}';
|
||||
$params['text'] ??= '{{ page.title }}';
|
||||
|
||||
return array_merge(parent::pickerData($params), [
|
||||
'dragText' => $this->dragText(),
|
||||
|
@@ -36,14 +36,14 @@ class Panel
|
||||
*/
|
||||
public static function area(string $id, $area): array
|
||||
{
|
||||
$area['id'] = $id;
|
||||
$area['label'] = $area['label'] ?? $id;
|
||||
$area['breadcrumb'] = $area['breadcrumb'] ?? [];
|
||||
$area['breadcrumbLabel'] = $area['breadcrumbLabel'] ?? $area['label'];
|
||||
$area['title'] = $area['label'];
|
||||
$area['menu'] = $area['menu'] ?? false;
|
||||
$area['link'] = $area['link'] ?? $id;
|
||||
$area['search'] = $area['search'] ?? null;
|
||||
$area['id'] = $id;
|
||||
$area['label'] ??= $id;
|
||||
$area['breadcrumb'] ??= [];
|
||||
$area['breadcrumbLabel'] ??= $area['label'];
|
||||
$area['title'] = $area['label'];
|
||||
$area['menu'] ??= false;
|
||||
$area['link'] ??= $id;
|
||||
$area['search'] ??= null;
|
||||
|
||||
return $area;
|
||||
}
|
||||
@@ -229,11 +229,14 @@ class Panel
|
||||
/**
|
||||
* Returns the referrer path if present
|
||||
*
|
||||
* @return string|null
|
||||
* @return string
|
||||
*/
|
||||
public static function referrer(): ?string
|
||||
public static function referrer(): string
|
||||
{
|
||||
$referrer = kirby()->request()->header('X-Fiber-Referrer') ?? get('_referrer');
|
||||
$referrer = kirby()->request()->header('X-Fiber-Referrer')
|
||||
?? get('_referrer')
|
||||
?? '';
|
||||
|
||||
return '/' . trim($referrer, '/');
|
||||
}
|
||||
|
||||
@@ -302,9 +305,6 @@ class Panel
|
||||
// create a micro-router for the Panel
|
||||
return router($path, $method = $kirby->request()->method(), $routes, function ($route) use ($areas, $kirby, $method, $path) {
|
||||
|
||||
// trigger hook
|
||||
$route = $kirby->apply('panel.route:before', compact('route', 'path', 'method'), 'route');
|
||||
|
||||
// route needs authentication?
|
||||
$auth = $route->attributes()['auth'] ?? true;
|
||||
$areaId = $route->attributes()['area'] ?? null;
|
||||
@@ -313,6 +313,9 @@ class Panel
|
||||
|
||||
// call the route action to check the result
|
||||
try {
|
||||
// trigger hook
|
||||
$route = $kirby->apply('panel.route:before', compact('route', 'path', 'method'), 'route');
|
||||
|
||||
// check for access before executing area routes
|
||||
if ($auth !== false) {
|
||||
static::firewall($kirby->user(), $areaId);
|
||||
@@ -450,6 +453,15 @@ class Panel
|
||||
$routes = [];
|
||||
|
||||
foreach ($dropdowns as $name => $dropdown) {
|
||||
// Handle shortcuts for dropdowns. The name is the pattern
|
||||
// and options are defined in a Closure
|
||||
if (is_a($dropdown, 'Closure') === true) {
|
||||
$dropdown = [
|
||||
'pattern' => $name,
|
||||
'action' => $dropdown
|
||||
];
|
||||
}
|
||||
|
||||
// create the full pattern with dropdowns prefix
|
||||
$pattern = 'dropdowns/' . trim(($dropdown['pattern'] ?? $name), '/');
|
||||
|
||||
|
@@ -172,7 +172,7 @@ class User extends Model
|
||||
*/
|
||||
public function pickerData(array $params = null): array
|
||||
{
|
||||
$params['text'] = $params['text'] ?? '{{ user.username }}';
|
||||
$params['text'] ??= '{{ user.username }}';
|
||||
|
||||
return array_merge(parent::pickerData($params), [
|
||||
'email' => $this->model->email(),
|
||||
|
@@ -47,22 +47,25 @@ class Svg extends Xml
|
||||
* @var array
|
||||
*/
|
||||
public static $allowedAttrs = [
|
||||
'accent-height',
|
||||
'accumulate',
|
||||
'additive',
|
||||
'alignment-baseline',
|
||||
'ascent',
|
||||
'attributeName',
|
||||
'attributeType',
|
||||
'azimuth',
|
||||
'baseFrequency',
|
||||
'baseline-shift',
|
||||
'begin',
|
||||
'bias',
|
||||
'by',
|
||||
// core attributes
|
||||
'id',
|
||||
'lang',
|
||||
'tabindex',
|
||||
'xml:id',
|
||||
'xml:lang',
|
||||
'xml:space',
|
||||
|
||||
// styling attributes
|
||||
'class',
|
||||
'style',
|
||||
|
||||
// conditional processing attributes
|
||||
'systemLanguage',
|
||||
|
||||
// presentation attributes
|
||||
'alignment-baseline',
|
||||
'baseline-shift',
|
||||
'clip',
|
||||
'clipPathUnits',
|
||||
'clip-path',
|
||||
'clip-rule',
|
||||
'color',
|
||||
@@ -70,24 +73,15 @@ class Svg extends Xml
|
||||
'color-interpolation-filters',
|
||||
'color-profile',
|
||||
'color-rendering',
|
||||
'cx',
|
||||
'cy',
|
||||
'd',
|
||||
'dx',
|
||||
'dy',
|
||||
'diffuseConstant',
|
||||
'direction',
|
||||
'display',
|
||||
'divisor',
|
||||
'dur',
|
||||
'edgeMode',
|
||||
'elevation',
|
||||
'end',
|
||||
'dominant-baseline',
|
||||
'enable-background',
|
||||
'fill',
|
||||
'fill-opacity',
|
||||
'fill-rule',
|
||||
'filter',
|
||||
'filterUnits',
|
||||
'flood-color',
|
||||
'flood-opacity',
|
||||
'font-family',
|
||||
@@ -97,18 +91,103 @@ class Svg extends Xml
|
||||
'font-style',
|
||||
'font-variant',
|
||||
'font-weight',
|
||||
'image-rendering',
|
||||
'kerning',
|
||||
'letter-spacing',
|
||||
'lighting-color',
|
||||
'marker-end',
|
||||
'marker-mid',
|
||||
'marker-start',
|
||||
'mask',
|
||||
'opacity',
|
||||
'overflow',
|
||||
'paint-order',
|
||||
'shape-rendering',
|
||||
'stop-color',
|
||||
'stop-opacity',
|
||||
'stroke',
|
||||
'stroke-dasharray',
|
||||
'stroke-dashoffset',
|
||||
'stroke-linecap',
|
||||
'stroke-linejoin',
|
||||
'stroke-miterlimit',
|
||||
'stroke-opacity',
|
||||
'stroke-width',
|
||||
'text-anchor',
|
||||
'text-decoration',
|
||||
'text-rendering',
|
||||
'transform',
|
||||
'visibility',
|
||||
'word-spacing',
|
||||
'writing-mode',
|
||||
|
||||
// animation attribute target attributes
|
||||
'attributeName',
|
||||
'attributeType',
|
||||
|
||||
// animation timing attributes
|
||||
'begin',
|
||||
'dur',
|
||||
'end',
|
||||
'max',
|
||||
'min',
|
||||
'repeatCount',
|
||||
'repeatDur',
|
||||
'restart',
|
||||
|
||||
// animation value attributes
|
||||
'by',
|
||||
'from',
|
||||
'keySplines',
|
||||
'keyTimes',
|
||||
'to',
|
||||
'values',
|
||||
|
||||
// animation addition attributes
|
||||
'accumulate',
|
||||
'additive',
|
||||
|
||||
// filter primitive attributes
|
||||
'height',
|
||||
'result',
|
||||
'width',
|
||||
'x',
|
||||
'y',
|
||||
|
||||
// transfer function attributes
|
||||
'amplitude',
|
||||
'exponent',
|
||||
'intercept',
|
||||
'offset',
|
||||
'slope',
|
||||
'tableValues',
|
||||
'type',
|
||||
|
||||
// other attributes specific to one or multiple elements
|
||||
'azimuth',
|
||||
'baseFrequency',
|
||||
'bias',
|
||||
'clipPathUnits',
|
||||
'cx',
|
||||
'cy',
|
||||
'diffuseConstant',
|
||||
'divisor',
|
||||
'dx',
|
||||
'dy',
|
||||
'edgeMode',
|
||||
'elevation',
|
||||
'filterUnits',
|
||||
'fr',
|
||||
'fx',
|
||||
'fy',
|
||||
'g1',
|
||||
'g2',
|
||||
'glyph-name',
|
||||
'glyphRef',
|
||||
'gradientUnits',
|
||||
'gradientTransform',
|
||||
'height',
|
||||
'gradientUnits',
|
||||
'href',
|
||||
'id',
|
||||
'image-rendering',
|
||||
'hreflang',
|
||||
'in',
|
||||
'in2',
|
||||
'k',
|
||||
@@ -116,116 +195,73 @@ class Svg extends Xml
|
||||
'k2',
|
||||
'k3',
|
||||
'k4',
|
||||
'kerning',
|
||||
'keyPoints',
|
||||
'keySplines',
|
||||
'keyTimes',
|
||||
'lang',
|
||||
'lengthAdjust',
|
||||
'letter-spacing',
|
||||
'kernelMatrix',
|
||||
'kernelUnitLength',
|
||||
'lighting-color',
|
||||
'local',
|
||||
'marker-end',
|
||||
'marker-mid',
|
||||
'marker-start',
|
||||
'keyPoints',
|
||||
'lengthAdjust',
|
||||
'limitingConeAngle',
|
||||
'markerHeight',
|
||||
'markerUnits',
|
||||
'markerWidth',
|
||||
'maskContentUnits',
|
||||
'maskUnits',
|
||||
'max',
|
||||
'mask',
|
||||
'media',
|
||||
'method',
|
||||
'mode',
|
||||
'min',
|
||||
'name',
|
||||
'numOctaves',
|
||||
'offset',
|
||||
'operator',
|
||||
'opacity',
|
||||
'order',
|
||||
'orient',
|
||||
'orientation',
|
||||
'origin',
|
||||
'overflow',
|
||||
'paint-order',
|
||||
'path',
|
||||
'pathLength',
|
||||
'patternContentUnits',
|
||||
'patternTransform',
|
||||
'patternUnits',
|
||||
'points',
|
||||
'pointsAtX',
|
||||
'pointsAtY',
|
||||
'pointsAtZ',
|
||||
'preserveAlpha',
|
||||
'preserveAspectRatio',
|
||||
'primitiveUnits',
|
||||
'r',
|
||||
'rx',
|
||||
'ry',
|
||||
'radius',
|
||||
'refX',
|
||||
'refY',
|
||||
'repeatCount',
|
||||
'repeatDur',
|
||||
'restart',
|
||||
'result',
|
||||
'rotate',
|
||||
'rx',
|
||||
'ry',
|
||||
'scale',
|
||||
'seed',
|
||||
'shape-rendering',
|
||||
'side',
|
||||
'spacing',
|
||||
'specularConstant',
|
||||
'specularExponent',
|
||||
'spreadMethod',
|
||||
'startOffset',
|
||||
'stdDeviation',
|
||||
'stitchTiles',
|
||||
'stop-color',
|
||||
'stop-opacity',
|
||||
'stroke-dasharray',
|
||||
'stroke-dashoffset',
|
||||
'stroke-linecap',
|
||||
'stroke-linejoin',
|
||||
'stroke-miterlimit',
|
||||
'stroke-opacity',
|
||||
'stroke',
|
||||
'stroke-width',
|
||||
'style',
|
||||
'surfaceScale',
|
||||
'systemLanguage',
|
||||
'tabindex',
|
||||
'targetX',
|
||||
'targetY',
|
||||
'transform',
|
||||
'text-anchor',
|
||||
'text-decoration',
|
||||
'text-rendering',
|
||||
'textLength',
|
||||
'type',
|
||||
'u1',
|
||||
'u2',
|
||||
'unicode',
|
||||
'values',
|
||||
'viewBox',
|
||||
'visibility',
|
||||
'version',
|
||||
'vert-adv-y',
|
||||
'vert-origin-x',
|
||||
'vert-origin-y',
|
||||
'width',
|
||||
'word-spacing',
|
||||
'wrap',
|
||||
'writing-mode',
|
||||
'xChannelSelector',
|
||||
'yChannelSelector',
|
||||
'x',
|
||||
'viewBox',
|
||||
'x1',
|
||||
'x2',
|
||||
'xChannelSelector',
|
||||
'xlink:href',
|
||||
'y',
|
||||
'xlink:title',
|
||||
'y1',
|
||||
'y2',
|
||||
'yChannelSelector',
|
||||
'z',
|
||||
'zoomAndPan',
|
||||
];
|
||||
@@ -247,12 +283,9 @@ class Svg extends Xml
|
||||
* `allowedAttrs` list or `false` to allow the tag without
|
||||
* any attributes
|
||||
*
|
||||
* @todo Move attributes from the global list to their tags
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $allowedTags = [
|
||||
'svg' => true,
|
||||
'a' => true,
|
||||
'altGlyph' => true,
|
||||
'altGlyphDef' => true,
|
||||
@@ -265,39 +298,6 @@ class Svg extends Xml
|
||||
'defs' => true,
|
||||
'desc' => true,
|
||||
'ellipse' => true,
|
||||
'filter' => true,
|
||||
'font' => true,
|
||||
'g' => true,
|
||||
'glyph' => true,
|
||||
'glyphRef' => true,
|
||||
'hkern' => true,
|
||||
'image' => true,
|
||||
'line' => true,
|
||||
'linearGradient' => true,
|
||||
'marker' => true,
|
||||
'mask' => true,
|
||||
'metadata' => true,
|
||||
'mpath' => true,
|
||||
'path' => true,
|
||||
'pattern' => true,
|
||||
'polygon' => true,
|
||||
'polyline' => true,
|
||||
'radialGradient' => true,
|
||||
'rect' => true,
|
||||
'stop' => true,
|
||||
'style' => true,
|
||||
'switch' => true,
|
||||
'symbol' => true,
|
||||
'text' => true,
|
||||
'textPath' => true,
|
||||
'title' => true,
|
||||
'tref' => true,
|
||||
'tspan' => true,
|
||||
'use' => true,
|
||||
'view' => true,
|
||||
'vkern' => true,
|
||||
|
||||
// filters
|
||||
'feBlend' => true,
|
||||
'feColorMatrix' => true,
|
||||
'feComponentTransfer' => true,
|
||||
@@ -321,6 +321,38 @@ class Svg extends Xml
|
||||
'feSpotLight' => true,
|
||||
'feTile' => true,
|
||||
'feTurbulence' => true,
|
||||
'filter' => true,
|
||||
'font' => true,
|
||||
'g' => true,
|
||||
'glyph' => true,
|
||||
'glyphRef' => true,
|
||||
'hkern' => true,
|
||||
'image' => true,
|
||||
'line' => true,
|
||||
'linearGradient' => true,
|
||||
'marker' => true,
|
||||
'mask' => true,
|
||||
'metadata' => true,
|
||||
'mpath' => true,
|
||||
'path' => true,
|
||||
'pattern' => true,
|
||||
'polygon' => true,
|
||||
'polyline' => true,
|
||||
'radialGradient' => true,
|
||||
'rect' => true,
|
||||
'stop' => true,
|
||||
'style' => true,
|
||||
'svg' => true,
|
||||
'switch' => true,
|
||||
'symbol' => true,
|
||||
'text' => true,
|
||||
'textPath' => true,
|
||||
'title' => true,
|
||||
'tref' => true,
|
||||
'tspan' => true,
|
||||
'use' => true,
|
||||
'view' => true,
|
||||
'vkern' => true,
|
||||
];
|
||||
|
||||
/**
|
||||
|
@@ -467,10 +467,7 @@ class A
|
||||
{
|
||||
// convert a simple ignore list to a nested $key => true array
|
||||
if (isset($ignore[0]) === true) {
|
||||
$ignore = array_map(function () {
|
||||
return true;
|
||||
}, array_flip($ignore));
|
||||
|
||||
$ignore = array_map(fn () => true, array_flip($ignore));
|
||||
$ignore = A::nest($ignore);
|
||||
}
|
||||
|
||||
|
@@ -138,7 +138,7 @@ class Dom
|
||||
*/
|
||||
public function body()
|
||||
{
|
||||
return $this->body = $this->body ?? $this->query('/html/body')[0] ?? null;
|
||||
return $this->body ??= $this->query('/html/body')[0] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -455,11 +455,20 @@ class Dom
|
||||
};
|
||||
}
|
||||
|
||||
if ($allowedNamespaces === true) {
|
||||
// take the list as it is and only consider
|
||||
// if the configuration does not define namespace URIs or if the
|
||||
// currently checked node is from the special `xml:` namespace
|
||||
// that has a fixed namespace according to the XML spec...
|
||||
if ($allowedNamespaces === true || $node->namespaceURI === 'http://www.w3.org/XML/1998/namespace') {
|
||||
// ...take the list as it is and only consider
|
||||
// exact matches of the local name (which will
|
||||
// contain a namespace if that namespace name
|
||||
// is not defined in the document)
|
||||
|
||||
// the list contains the `xml:` prefix, so add it to the name as well
|
||||
if ($node->namespaceURI === 'http://www.w3.org/XML/1998/namespace') {
|
||||
$localName = 'xml:' . $localName;
|
||||
}
|
||||
|
||||
foreach ($list as $item) {
|
||||
if ($compare($item, $localName) === true) {
|
||||
return $item;
|
||||
|
@@ -81,7 +81,7 @@ class Escape
|
||||
*/
|
||||
protected static function escaper()
|
||||
{
|
||||
return static::$escaper = static::$escaper ?? new Escaper('utf-8');
|
||||
return static::$escaper ??= new Escaper('utf-8');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -24,6 +24,34 @@ class Html extends Xml
|
||||
*/
|
||||
public static $entities;
|
||||
|
||||
/**
|
||||
* List of HTML tags that can be used inline
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $inlineList = [
|
||||
'b',
|
||||
'i',
|
||||
'small',
|
||||
'abbr',
|
||||
'cite',
|
||||
'code',
|
||||
'dfn',
|
||||
'em',
|
||||
'kbd',
|
||||
'strong',
|
||||
'samp',
|
||||
'var',
|
||||
'a',
|
||||
'bdo',
|
||||
'br',
|
||||
'img',
|
||||
'q',
|
||||
'span',
|
||||
'sub',
|
||||
'sup'
|
||||
];
|
||||
|
||||
/**
|
||||
* Closing string for void tags;
|
||||
* can be used to switch to trailing slashes if required
|
||||
@@ -117,6 +145,10 @@ class Html extends Xml
|
||||
// all other cases can share the XML variant
|
||||
$attr = parent::attr($name, $value);
|
||||
|
||||
if ($attr === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// HTML supports named entities
|
||||
$entities = parent::entities();
|
||||
$html = array_keys($entities);
|
||||
@@ -205,7 +237,7 @@ class Html extends Xml
|
||||
*/
|
||||
public static function entities(): array
|
||||
{
|
||||
return self::$entities = self::$entities ?? get_html_translation_table(HTML_ENTITIES);
|
||||
return self::$entities ??= get_html_translation_table(HTML_ENTITIES);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -325,7 +357,7 @@ class Html extends Xml
|
||||
*/
|
||||
public static function rel(?string $rel = null, ?string $target = null): ?string
|
||||
{
|
||||
$rel = trim($rel);
|
||||
$rel = trim($rel ?? '');
|
||||
|
||||
if ($target === '_blank') {
|
||||
if (empty($rel) === false) {
|
||||
|
@@ -115,7 +115,7 @@ class I18n
|
||||
*/
|
||||
public static function formatNumber($number, string $locale = null): string
|
||||
{
|
||||
$locale = $locale ?? static::locale();
|
||||
$locale ??= static::locale();
|
||||
|
||||
$formatter = static::decimalNumberFormatter($locale);
|
||||
if ($formatter !== null) {
|
||||
@@ -154,7 +154,7 @@ class I18n
|
||||
*/
|
||||
public static function translate($key, $fallback = null, string $locale = null)
|
||||
{
|
||||
$locale = $locale ?? static::locale();
|
||||
$locale ??= static::locale();
|
||||
|
||||
if (is_array($key) === true) {
|
||||
if (isset($key[$locale])) {
|
||||
@@ -224,7 +224,7 @@ class I18n
|
||||
*/
|
||||
public static function translation(string $locale = null): array
|
||||
{
|
||||
$locale = $locale ?? static::locale();
|
||||
$locale ??= static::locale();
|
||||
|
||||
if (isset(static::$translations[$locale]) === true) {
|
||||
return static::$translations[$locale];
|
||||
@@ -283,8 +283,7 @@ class I18n
|
||||
*/
|
||||
public static function translateCount(string $key, int $count, string $locale = null, bool $formatNumber = true)
|
||||
{
|
||||
$locale = $locale ?? static::locale();
|
||||
|
||||
$locale ??= static::locale();
|
||||
$translation = static::translate($key, null, $locale);
|
||||
|
||||
if ($translation === null) {
|
||||
|
@@ -40,7 +40,7 @@ class Iterator implements IteratorAggregate
|
||||
*
|
||||
* @return \ArrayIterator
|
||||
*/
|
||||
public function getIterator()
|
||||
public function getIterator(): ArrayIterator
|
||||
{
|
||||
return new ArrayIterator($this->data);
|
||||
}
|
||||
|
@@ -115,7 +115,7 @@ trait Properties
|
||||
}
|
||||
|
||||
// fetch the default value from the property
|
||||
$value = $value ?? $this->$name ?? null;
|
||||
$value ??= $this->$name ?? null;
|
||||
|
||||
// store all original properties, to be able to clone them later
|
||||
$this->propertyData[$name] = $value;
|
||||
|
@@ -3,6 +3,7 @@
|
||||
namespace Kirby\Toolkit;
|
||||
|
||||
use Exception;
|
||||
use Kirby\Exception\InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* The String class provides a set
|
||||
@@ -180,9 +181,9 @@ class Str
|
||||
|
||||
if ($position === false) {
|
||||
return '';
|
||||
} else {
|
||||
return static::substr($string, $position + static::length($needle));
|
||||
}
|
||||
|
||||
return static::substr($string, $position + static::length($needle));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -222,9 +223,9 @@ class Str
|
||||
|
||||
if ($position === false) {
|
||||
return '';
|
||||
} else {
|
||||
return static::substr($string, 0, $position);
|
||||
}
|
||||
|
||||
return static::substr($string, 0, $position);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -250,7 +251,40 @@ class Str
|
||||
*/
|
||||
public static function contains(string $string = null, string $needle, bool $caseInsensitive = false): bool
|
||||
{
|
||||
return call_user_func($caseInsensitive === true ? 'stripos' : 'strpos', $string, $needle) !== false;
|
||||
if ($needle === '') {
|
||||
return true;
|
||||
}
|
||||
|
||||
$method = $caseInsensitive === true ? 'stripos' : 'strpos';
|
||||
return call_user_func($method, $string, $needle) !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert timestamp to date string
|
||||
* according to locale settings
|
||||
*
|
||||
* @param int|null $time
|
||||
* @param string|null $format
|
||||
* @param string $handler date or strftime
|
||||
* @return string|int
|
||||
*/
|
||||
public static function date(?int $time = null, ?string $format = null, string $handler = 'date')
|
||||
{
|
||||
if (is_null($format) === true) {
|
||||
return $time;
|
||||
}
|
||||
|
||||
// separately handle strftime to be able
|
||||
// to suppress deprecation warning
|
||||
// TODO: remove strftime support for PHP 9.0
|
||||
if ($handler === 'strftime') {
|
||||
// make sure timezone is set correctly
|
||||
date_default_timezone_get();
|
||||
|
||||
return @strftime($format, $time);
|
||||
}
|
||||
|
||||
return $handler($format, $time);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -373,6 +407,9 @@ class Str
|
||||
*/
|
||||
public static function float($value): string
|
||||
{
|
||||
// make sure $value is not null
|
||||
$value ??= '';
|
||||
|
||||
// Convert exponential to decimal, 1e-8 as 0.00000001
|
||||
if (strpos(strtolower($value), 'e') !== false) {
|
||||
$value = rtrim(sprintf('%.16f', (float)$value), '0');
|
||||
@@ -397,9 +434,9 @@ class Str
|
||||
|
||||
if ($position === false) {
|
||||
return '';
|
||||
} else {
|
||||
return static::substr($string, $position);
|
||||
}
|
||||
|
||||
return static::substr($string, $position);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -436,7 +473,7 @@ class Str
|
||||
*/
|
||||
public static function length(string $string = null): int
|
||||
{
|
||||
return mb_strlen($string, 'UTF-8');
|
||||
return mb_strlen($string ?? '', 'UTF-8');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -512,6 +549,10 @@ class Str
|
||||
*/
|
||||
public static function position(string $string = null, string $needle, bool $caseInsensitive = false)
|
||||
{
|
||||
if ($needle === '') {
|
||||
throw new InvalidArgumentException('The needle must not be empty');
|
||||
}
|
||||
|
||||
if ($caseInsensitive === true) {
|
||||
$string = static::lower($string);
|
||||
$needle = static::lower($needle);
|
||||
@@ -899,10 +940,10 @@ class Str
|
||||
*/
|
||||
public static function slug(string $string = null, string $separator = null, string $allowed = null, int $maxlength = 128): string
|
||||
{
|
||||
$separator = $separator ?? static::$defaults['slug']['separator'];
|
||||
$allowed = $allowed ?? static::$defaults['slug']['allowed'];
|
||||
$separator ??= static::$defaults['slug']['separator'];
|
||||
$allowed ??= static::$defaults['slug']['allowed'];
|
||||
|
||||
$string = trim($string);
|
||||
$string = trim($string ?? '');
|
||||
$string = static::lower($string);
|
||||
$string = static::ascii($string);
|
||||
|
||||
@@ -958,8 +999,11 @@ class Str
|
||||
return $string;
|
||||
}
|
||||
|
||||
$parts = explode($separator, $string);
|
||||
$out = [];
|
||||
// make sure $string is string
|
||||
$string ??= '';
|
||||
|
||||
$parts = explode($separator, $string);
|
||||
$out = [];
|
||||
|
||||
foreach ($parts as $p) {
|
||||
$p = trim($p);
|
||||
@@ -1046,6 +1090,9 @@ class Str
|
||||
$start = (string)($options['start'] ?? $start);
|
||||
$end = (string)($options['end'] ?? $end);
|
||||
|
||||
// make sure $string is string
|
||||
$string ??= '';
|
||||
|
||||
return preg_replace_callback('!' . $start . '(.*?)' . $end . '!', function ($match) use ($data, $fallback, $callback) {
|
||||
$query = trim($match[1]);
|
||||
|
||||
@@ -1084,8 +1131,12 @@ class Str
|
||||
*/
|
||||
public static function toBytes($size): int
|
||||
{
|
||||
// TODO: remove in 3.7.0
|
||||
// in favor of strict parameter type hint
|
||||
$size ??= '';
|
||||
|
||||
$size = trim($size);
|
||||
$last = strtolower($size[strlen($size)-1] ?? null);
|
||||
$last = strtolower($size[strlen($size)-1] ?? '');
|
||||
$size = (int)$size;
|
||||
|
||||
switch ($last) {
|
||||
@@ -1198,9 +1249,9 @@ class Str
|
||||
|
||||
if ($position === false) {
|
||||
return '';
|
||||
} else {
|
||||
return static::substr($string, 0, $position + static::length($needle));
|
||||
}
|
||||
|
||||
return static::substr($string, 0, $position + static::length($needle));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1224,6 +1275,9 @@ class Str
|
||||
*/
|
||||
public static function widont(string $string = null): string
|
||||
{
|
||||
// make sure $string is string
|
||||
$string ??= '';
|
||||
|
||||
// Replace space between last word and punctuation
|
||||
$string = preg_replace_callback('|(\S)\s(\S?)$|u', function ($matches) {
|
||||
return $matches[1] . ' ' . $matches[2];
|
||||
|
@@ -249,6 +249,9 @@ V::$validators = [
|
||||
* third argument to compare them.
|
||||
*/
|
||||
'date' => function (?string $value, string $operator = null, string $test = null): bool {
|
||||
// make sure $value is a string
|
||||
$value ??= '';
|
||||
|
||||
$args = func_get_args();
|
||||
|
||||
// simple date validation
|
||||
@@ -522,6 +525,6 @@ V::$validators = [
|
||||
// In search for the perfect regular expression: https://mathiasbynens.be/demo/url-regex
|
||||
// Added localhost support and removed 127.*.*.* ip restriction
|
||||
$regex = '_^(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:localhost)|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?$_iu';
|
||||
return preg_match($regex, $value) !== 0;
|
||||
return preg_match($regex, $value ?? '') !== 0;
|
||||
}
|
||||
];
|
||||
|
@@ -106,9 +106,10 @@ class Xml
|
||||
if (isset($value['value'], $value['escape'])) {
|
||||
$value = $value['escape'] === true ? static::encode($value['value']) : $value['value'];
|
||||
} else {
|
||||
$value = implode(' ', array_filter($value, function ($value) {
|
||||
return !empty($value) || is_numeric($value);
|
||||
}));
|
||||
$value = implode(' ', array_filter(
|
||||
$value,
|
||||
fn ($value) => !empty($value) || is_numeric($value)
|
||||
));
|
||||
}
|
||||
} else {
|
||||
$value = static::encode($value);
|
||||
@@ -420,7 +421,8 @@ class Xml
|
||||
return $value;
|
||||
}
|
||||
|
||||
$encoded = htmlentities($value);
|
||||
// TODO: in 3.7.0 use ENT_NOQUOTES | ENT_XML1 instead
|
||||
$encoded = htmlentities($value, ENT_COMPAT);
|
||||
if ($encoded === $value) {
|
||||
// no CDATA block needed
|
||||
return $value;
|
||||
|
@@ -48,7 +48,7 @@ class SimpleImage {
|
||||
* @param string $image An image file or a data URI to load.
|
||||
* @throws \Exception Thrown if the GD library is not found; file|URI or image data is invalid.
|
||||
*/
|
||||
public function __construct($image = null) {
|
||||
public function __construct($image = '') {
|
||||
// Check for the required GD extension
|
||||
if(extension_loaded('gd')) {
|
||||
// Ignore JPEG warnings that cause imagecreatefromjpeg() to fail
|
||||
@@ -147,7 +147,7 @@ class SimpleImage {
|
||||
// workaround to prevent imagepalettetruecolor() from borking transparency.
|
||||
$width = imagesx($gif);
|
||||
$height = imagesy($gif);
|
||||
$this->image = imagecreatetruecolor($width, $height);
|
||||
$this->image = imagecreatetruecolor((int) $width, (int) $height);
|
||||
$transparentColor = imagecolorallocatealpha($this->image, 0, 0, 0, 127);
|
||||
imagecolortransparent($this->image, $transparentColor);
|
||||
imagefill($this->image, 0, 0, $transparentColor);
|
||||
@@ -194,7 +194,7 @@ class SimpleImage {
|
||||
* @return \claviska\SimpleImage
|
||||
*/
|
||||
public function fromNew($width, $height, $color = 'transparent') {
|
||||
$this->image = imagecreatetruecolor($width, $height);
|
||||
$this->image = imagecreatetruecolor((int) $width, (int) $height);
|
||||
|
||||
// Use PNG for dynamically created images because it's lossless and supports transparency
|
||||
$this->mimeType = 'image/png';
|
||||
@@ -490,7 +490,7 @@ class SimpleImage {
|
||||
imagefilter($srcIm, IMG_FILTER_COLORIZE, 0, 0, 0, 127 * ((100 - $pct) / 100));
|
||||
}
|
||||
|
||||
imagecopy($dstIm, $srcIm, $dstX, $dstY, $srcX, $srcY, $srcW, $srcH);
|
||||
imagecopy($dstIm, $srcIm, (int) $dstX, (int) $dstY, (int) $srcX, (int) $srcY, (int) $srcW, (int) $srcH);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -593,7 +593,7 @@ class SimpleImage {
|
||||
// Avoid using native imagecrop() because of a bug with PNG transparency
|
||||
$dstW = abs($x2 - $x1);
|
||||
$dstH = abs($y2 - $y1);
|
||||
$newImage = imagecreatetruecolor($dstW, $dstH);
|
||||
$newImage = imagecreatetruecolor((int) $dstW, (int) $dstH);
|
||||
$transparentColor = imagecolorallocatealpha($newImage, 0, 0, 0, 127);
|
||||
imagecolortransparent($newImage, $transparentColor);
|
||||
imagefill($newImage, 0, 0, $transparentColor);
|
||||
@@ -603,10 +603,10 @@ class SimpleImage {
|
||||
$newImage,
|
||||
$this->image,
|
||||
0, 0, min($x1, $x2), min($y1, $y2),
|
||||
$dstW,
|
||||
$dstH,
|
||||
$dstW,
|
||||
$dstH
|
||||
(int) $dstW,
|
||||
(int) $dstH,
|
||||
(int) $dstW,
|
||||
(int) $dstH
|
||||
);
|
||||
|
||||
// Swap out the new image
|
||||
@@ -802,7 +802,7 @@ class SimpleImage {
|
||||
// We can't use imagescale because it doesn't seem to preserve transparency properly. The
|
||||
// workaround is to create a new truecolor image, allocate a transparent color, and copy the
|
||||
// image over to it using imagecopyresampled.
|
||||
$newImage = imagecreatetruecolor($width, $height);
|
||||
$newImage = imagecreatetruecolor((int) $width, (int) $height);
|
||||
$transparentColor = imagecolorallocatealpha($newImage, 0, 0, 0, 127);
|
||||
imagecolortransparent($newImage, $transparentColor);
|
||||
imagefill($newImage, 0, 0, $transparentColor);
|
||||
@@ -810,8 +810,8 @@ class SimpleImage {
|
||||
$newImage,
|
||||
$this->image,
|
||||
0, 0, 0, 0,
|
||||
$width,
|
||||
$height,
|
||||
(int) $width,
|
||||
(int) $height,
|
||||
$this->getWidth(),
|
||||
$this->getHeight()
|
||||
);
|
||||
@@ -1885,7 +1885,7 @@ class SimpleImage {
|
||||
$color['red'],
|
||||
$color['green'],
|
||||
$color['blue'],
|
||||
127 - ($color['alpha'] * 127)
|
||||
(int) (127 - ($color['alpha'] * 127))
|
||||
);
|
||||
if($index > -1) {
|
||||
// Yes, return this color index
|
||||
|
10
kirby/vendor/composer/autoload_classmap.php
vendored
10
kirby/vendor/composer/autoload_classmap.php
vendored
@@ -264,6 +264,7 @@ return array(
|
||||
'League\\ColorExtractor\\Palette' => $vendorDir . '/league/color-extractor/src/League/ColorExtractor/Palette.php',
|
||||
'Michelf\\SmartyPants' => $vendorDir . '/michelf/php-smartypants/Michelf/SmartyPants.php',
|
||||
'Michelf\\SmartyPantsTypographer' => $vendorDir . '/michelf/php-smartypants/Michelf/SmartyPantsTypographer.php',
|
||||
'Normalizer' => $vendorDir . '/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php',
|
||||
'PHPMailer\\PHPMailer\\Exception' => $vendorDir . '/phpmailer/phpmailer/src/Exception.php',
|
||||
'PHPMailer\\PHPMailer\\OAuth' => $vendorDir . '/phpmailer/phpmailer/src/OAuth.php',
|
||||
'PHPMailer\\PHPMailer\\PHPMailer' => $vendorDir . '/phpmailer/phpmailer/src/PHPMailer.php',
|
||||
@@ -279,11 +280,12 @@ return array(
|
||||
'Psr\\Log\\LoggerInterface' => $vendorDir . '/psr/log/Psr/Log/LoggerInterface.php',
|
||||
'Psr\\Log\\LoggerTrait' => $vendorDir . '/psr/log/Psr/Log/LoggerTrait.php',
|
||||
'Psr\\Log\\NullLogger' => $vendorDir . '/psr/log/Psr/Log/NullLogger.php',
|
||||
'Symfony\\Polyfill\\Intl\\Idn\\Idn' => $vendorDir . '/symfony/polyfill-intl-idn/Idn.php',
|
||||
'Symfony\\Polyfill\\Intl\\Idn\\Info' => $vendorDir . '/symfony/polyfill-intl-idn/Info.php',
|
||||
'Symfony\\Polyfill\\Intl\\Idn\\Resources\\unidata\\DisallowedRanges' => $vendorDir . '/symfony/polyfill-intl-idn/Resources/unidata/DisallowedRanges.php',
|
||||
'Symfony\\Polyfill\\Intl\\Idn\\Resources\\unidata\\Regex' => $vendorDir . '/symfony/polyfill-intl-idn/Resources/unidata/Regex.php',
|
||||
'Symfony\\Polyfill\\Intl\\Normalizer\\Normalizer' => $vendorDir . '/symfony/polyfill-intl-normalizer/Normalizer.php',
|
||||
'Symfony\\Polyfill\\Mbstring\\Mbstring' => $vendorDir . '/symfony/polyfill-mbstring/Mbstring.php',
|
||||
'TrueBV\\Exception\\DomainOutOfBoundsException' => $vendorDir . '/true/punycode/src/Exception/DomainOutOfBoundsException.php',
|
||||
'TrueBV\\Exception\\LabelOutOfBoundsException' => $vendorDir . '/true/punycode/src/Exception/LabelOutOfBoundsException.php',
|
||||
'TrueBV\\Exception\\OutOfBoundsException' => $vendorDir . '/true/punycode/src/Exception/OutOfBoundsException.php',
|
||||
'TrueBV\\Punycode' => $vendorDir . '/true/punycode/src/Punycode.php',
|
||||
'Whoops\\Exception\\ErrorException' => $vendorDir . '/filp/whoops/src/Whoops/Exception/ErrorException.php',
|
||||
'Whoops\\Exception\\Formatter' => $vendorDir . '/filp/whoops/src/Whoops/Exception/Formatter.php',
|
||||
'Whoops\\Exception\\Frame' => $vendorDir . '/filp/whoops/src/Whoops/Exception/Frame.php',
|
||||
|
4
kirby/vendor/composer/autoload_files.php
vendored
4
kirby/vendor/composer/autoload_files.php
vendored
@@ -6,8 +6,10 @@ $vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
|
||||
'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php',
|
||||
'04c6c5c2f7095ccf6c481d3e53e1776f' => $vendorDir . '/mustangostang/spyc/Spyc.php',
|
||||
'f598d06aa772fa33d905e87be6398fb1' => $vendorDir . '/symfony/polyfill-intl-idn/bootstrap.php',
|
||||
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
|
||||
'f864ae44e8154e5ff6f4eec32f46d37f' => $baseDir . '/config/setup.php',
|
||||
'87988fc7b1c1f093da22a1a3de972f3a' => $baseDir . '/config/helpers.php',
|
||||
);
|
||||
|
3
kirby/vendor/composer/autoload_psr4.php
vendored
3
kirby/vendor/composer/autoload_psr4.php
vendored
@@ -7,8 +7,9 @@ $baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'Whoops\\' => array($vendorDir . '/filp/whoops/src/Whoops'),
|
||||
'TrueBV\\' => array($vendorDir . '/true/punycode/src'),
|
||||
'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
|
||||
'Symfony\\Polyfill\\Intl\\Normalizer\\' => array($vendorDir . '/symfony/polyfill-intl-normalizer'),
|
||||
'Symfony\\Polyfill\\Intl\\Idn\\' => array($vendorDir . '/symfony/polyfill-intl-idn'),
|
||||
'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
|
||||
'PHPMailer\\PHPMailer\\' => array($vendorDir . '/phpmailer/phpmailer/src'),
|
||||
'Laminas\\Escaper\\' => array($vendorDir . '/laminas/laminas-escaper/src'),
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user