Upgrade to 3.8.0

This commit is contained in:
Bastian Allgeier
2022-10-06 10:11:54 +02:00
parent a9ed4e45ca
commit 7d168aae58
332 changed files with 26337 additions and 21977 deletions
+1 -1
View File
@@ -5,7 +5,7 @@
* stop at older or too recent versions
*/
if (
version_compare(PHP_VERSION, '7.4.0', '>=') === false ||
version_compare(PHP_VERSION, '8.0.0', '>=') === false ||
version_compare(PHP_VERSION, '8.2.0', '<') === false
) {
die(include __DIR__ . '/views/php.php');
+4 -3
View File
@@ -3,7 +3,7 @@
"description": "The Kirby 3 core",
"license": "proprietary",
"type": "kirby-cms",
"version": "3.7.5",
"version": "3.8.0",
"keywords": [
"kirby",
"cms",
@@ -24,7 +24,7 @@
"source": "https://github.com/getkirby/kirby"
},
"require": {
"php": ">=7.4.0 <8.2.0",
"php": ">=8.0.0 <8.2.0",
"ext-SimpleXML": "*",
"ext-ctype": "*",
"ext-curl": "*",
@@ -37,6 +37,7 @@
"ext-mbstring": "*",
"ext-openssl": "*",
"claviska/simpleimage": "3.7.0",
"composer/semver": "3.3.2",
"filp/whoops": "2.14.5",
"getkirby/composer-installer": "^1.2.1",
"laminas/laminas-escaper": "2.10.0",
@@ -76,7 +77,7 @@
},
"optimize-autoloader": true,
"platform": {
"php": "7.4.0"
"php": "8.0.0"
},
"platform-check": false
},
+93 -12
View File
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "fb087946fb5ac5910e25a4d263905d99",
"content-hash": "1ee4c8241ce2584bc60acda5c8a62771",
"packages": [
{
"name": "claviska/simpleimage",
@@ -55,6 +55,87 @@
],
"time": "2022-07-05T13:18:44+00:00"
},
{
"name": "composer/semver",
"version": "3.3.2",
"source": {
"type": "git",
"url": "https://github.com/composer/semver.git",
"reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/semver/zipball/3953f23262f2bff1919fc82183ad9acb13ff62c9",
"reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9",
"shasum": ""
},
"require": {
"php": "^5.3.2 || ^7.0 || ^8.0"
},
"require-dev": {
"phpstan/phpstan": "^1.4",
"symfony/phpunit-bridge": "^4.2 || ^5"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "3.x-dev"
}
},
"autoload": {
"psr-4": {
"Composer\\Semver\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nils Adermann",
"email": "naderman@naderman.de",
"homepage": "http://www.naderman.de"
},
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be",
"homepage": "http://seld.be"
},
{
"name": "Rob Bast",
"email": "rob.bast@gmail.com",
"homepage": "http://robbast.nl"
}
],
"description": "Semver library that offers utilities, version constraint parsing and validation.",
"keywords": [
"semantic",
"semver",
"validation",
"versioning"
],
"support": {
"irc": "irc://irc.freenode.org/composer",
"issues": "https://github.com/composer/semver/issues",
"source": "https://github.com/composer/semver/tree/3.3.2"
},
"funding": [
{
"url": "https://packagist.com",
"type": "custom"
},
{
"url": "https://github.com/composer",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/composer/composer",
"type": "tidelift"
}
],
"time": "2022-04-01T19:23:25+00:00"
},
{
"name": "filp/whoops",
"version": "2.14.5",
@@ -427,30 +508,30 @@
},
{
"name": "psr/log",
"version": "1.1.4",
"version": "3.0.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/log.git",
"reference": "d49695b909c3b7628b6289db5479a1c204601f11"
"reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11",
"reference": "d49695b909c3b7628b6289db5479a1c204601f11",
"url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001",
"reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
"php": ">=8.0.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.1.x-dev"
"dev-master": "3.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Log\\": "Psr/Log/"
"Psr\\Log\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -471,9 +552,9 @@
"psr-3"
],
"support": {
"source": "https://github.com/php-fig/log/tree/1.1.4"
"source": "https://github.com/php-fig/log/tree/3.0.0"
},
"time": "2021-05-03T11:20:27+00:00"
"time": "2021-07-14T16:46:02+00:00"
},
{
"name": "symfony/polyfill-intl-idn",
@@ -737,7 +818,7 @@
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": ">=7.4.0 <8.2.0",
"php": ">=8.0.0 <8.2.0",
"ext-simplexml": "*",
"ext-ctype": "*",
"ext-curl": "*",
@@ -752,7 +833,7 @@
},
"platform-dev": [],
"platform-overrides": {
"php": "7.4.0"
"php": "8.0.0"
},
"plugin-api-version": "2.3.0"
}
-1
View File
@@ -46,7 +46,6 @@ return [
'cookie' => 'Kirby\Http\Cookie',
'header' => 'Kirby\Http\Header',
'remote' => 'Kirby\Http\Remote',
'server' => 'Kirby\Http\Server',
// image classes
'dimensions' => 'Kirby\Image\Dimensions',
-31
View File
@@ -1,6 +1,5 @@
<?php
use Kirby\Cms\Helpers;
use Kirby\Cms\Page;
use Kirby\Form\Form;
@@ -21,41 +20,11 @@ return [
'hasFiles' => fn (Page $page) => $page->hasFiles(),
'id' => fn (Page $page) => $page->id(),
'isSortable' => fn (Page $page) => $page->isSortable(),
/**
* @deprecated 3.6.0
* @todo Remove in 3.8.0
* @codeCoverageIgnore
*/
'next' => function (Page $page) {
Helpers::deprecated('The API field page.next has been deprecated and will be removed in 3.8.0.');
return $page
->nextAll()
->filter('intendedTemplate', $page->intendedTemplate())
->filter('status', $page->status())
->filter('isReadable', true)
->first();
},
'num' => fn (Page $page) => $page->num(),
'options' => fn (Page $page) => $page->panel()->options(['preview']),
'panelImage' => fn (Page $page) => $page->panel()->image(),
'parent' => fn (Page $page) => $page->parent(),
'parents' => fn (Page $page) => $page->parents()->flip(),
/**
* @deprecated 3.6.0
* @todo Remove in 3.8.0
* @codeCoverageIgnore
*/
'prev' => function (Page $page) {
Helpers::deprecated('The API field page.prev has been deprecated and will be removed in 3.8.0.');
return $page
->prevAll()
->filter('intendedTemplate', $page->intendedTemplate())
->filter('status', $page->status())
->filter('isReadable', true)
->last();
},
'previewUrl' => fn (Page $page) => $page->previewUrl(),
'siblings' => function (Page $page) {
if ($page->isDraft() === true) {
+8 -13
View File
@@ -32,28 +32,23 @@ return [
'slugs' => fn () => Str::$language,
'title' => fn () => $this->site()->title()->value(),
'translation' => function () {
if ($user = $this->user()) {
$translationCode = $user->language();
} else {
$translationCode = $this->kirby()->panelLanguage();
$code = $this->user()?->language() ??
$this->kirby()->panelLanguage();
if ($translation = $this->kirby()->translation($code)) {
return $translation;
}
if ($translation = $this->kirby()->translation($translationCode)) {
return $translation;
} else {
return $this->kirby()->translation('en');
}
},
'kirbytext' => fn () => $this->kirby()->option('panel.kirbytext') ?? true,
'user' => fn () => $this->user(),
'version' => function () {
$user = $this->user();
if ($user && $user->role()->permissions()->for('access', 'system') === true) {
if ($this->user()?->role()->permissions()->for('access', 'system') === true) {
return $this->kirby()->version();
} else {
return null;
}
return null;
}
],
'type' => 'Kirby\Cms\System',
+12 -2
View File
@@ -87,14 +87,14 @@ return [
'status' => 'ok',
'user' => $this->resolve($user)->view('auth')->toArray()
];
} else {
}
return [
'code' => 200,
'status' => 'ok',
'challenge' => $status->challenge()
];
}
}
],
[
'pattern' => 'auth/logout',
@@ -105,4 +105,14 @@ return [
return true;
}
],
[
'pattern' => 'auth/ping',
'method' => 'POST',
'auth' => false,
'action' => function () {
// refresh the session timeout
$this->kirby()->session();
return true;
}
],
];
+13 -11
View File
@@ -12,9 +12,7 @@ return [
'pattern' => $pattern . '/files/(:any)/sections/(:any)',
'method' => 'GET',
'action' => function (string $path, string $filename, string $sectionName) {
if ($section = $this->file($path, $filename)->blueprint()->section($sectionName)) {
return $section->toResponse();
}
return $this->file($path, $filename)->blueprint()->section($sectionName)?->toResponse();
}
],
[
@@ -60,9 +58,9 @@ return [
if ($this->requestMethod() === 'GET') {
return $files->search($this->requestQuery('q'));
} else {
return $files->query($this->requestBody());
}
return $files->query($this->requestBody());
}
],
[
@@ -86,16 +84,20 @@ return [
'pattern' => $pattern . '/files/(:any)',
'method' => 'PATCH',
'action' => function (string $path, string $filename) {
return $this->file($path, $filename)->update($this->requestBody(), $this->language(), true);
return $this->file($path, $filename)->update(
$this->requestBody(),
$this->language(),
true
);
}
],
[
'pattern' => $pattern . '/files/(:any)',
'method' => 'POST',
'action' => function (string $path, string $filename) {
return $this->upload(function ($source) use ($path, $filename) {
return $this->file($path, $filename)->replace($source);
});
return $this->upload(
fn ($source) => $this->file($path, $filename)->replace($source)
);
}
],
[
@@ -124,9 +126,9 @@ return [
if ($this->requestMethod() === 'GET') {
return $files->search($this->requestQuery('q'));
} else {
return $files->query($this->requestBody());
}
return $files->query($this->requestBody());
}
],
];
+2 -6
View File
@@ -29,18 +29,14 @@ return [
'pattern' => 'languages/(:any)',
'method' => 'PATCH',
'action' => function (string $code) {
if ($language = $this->kirby()->languages()->find($code)) {
return $language->update($this->requestBody());
}
return $this->kirby()->languages()->find($code)?->update($this->requestBody());
}
],
[
'pattern' => 'languages/(:any)',
'method' => 'DELETE',
'action' => function (string $code) {
if ($language = $this->kirby()->languages()->find($code)) {
return $language->delete();
}
return $this->kirby()->languages()->find($code)?->delete();
}
]
];
+13 -12
View File
@@ -5,40 +5,41 @@
* Content Lock Routes
*/
return [
[
'pattern' => '(:all)/lock',
'method' => 'GET',
'action' => function (string $path) {
return [
'lock' => $this->parent($path)->lock()?->toArray() ?? false
];
}
],
[
'pattern' => '(:all)/lock',
'method' => 'PATCH',
'action' => function (string $path) {
if ($lock = $this->parent($path)->lock()) {
return $lock->create();
}
return $this->parent($path)->lock()?->create();
}
],
[
'pattern' => '(:all)/lock',
'method' => 'DELETE',
'action' => function (string $path) {
if ($lock = $this->parent($path)->lock()) {
return $lock->remove();
}
return $this->parent($path)->lock()?->remove();
}
],
[
'pattern' => '(:all)/unlock',
'method' => 'PATCH',
'action' => function (string $path) {
if ($lock = $this->parent($path)->lock()) {
return $lock->unlock();
}
return $this->parent($path)->lock()?->unlock();
}
],
[
'pattern' => '(:all)/unlock',
'method' => 'DELETE',
'action' => function (string $path) {
if ($lock = $this->parent($path)->lock()) {
return $lock->resolve();
}
return $this->parent($path)->lock()?->resolve();
}
],
];
+1 -3
View File
@@ -104,9 +104,7 @@ return [
'pattern' => 'pages/(:any)/sections/(:any)',
'method' => 'GET',
'action' => function (string $id, string $sectionName) {
if ($section = $this->page($id)->blueprint()->section($sectionName)) {
return $section->toResponse();
}
return $this->page($id)->blueprint()->section($sectionName)?->toResponse();
}
],
[
+5 -8
View File
@@ -10,14 +10,11 @@ return [
'action' => function () {
$kirby = $this->kirby();
switch ($kirby->request()->get('canBe')) {
case 'changed':
return $kirby->roles()->canBeChanged();
case 'created':
return $kirby->roles()->canBeCreated();
default:
return $kirby->roles();
}
return match ($kirby->request()->get('canBe')) {
'changed' => $kirby->roles()->canBeChanged(),
'created' => $kirby->roles()->canBeCreated(),
default => $kirby->roles()
};
}
],
[
+3 -5
View File
@@ -79,18 +79,16 @@ return [
if ($this->requestMethod() === 'GET') {
return $pages->search($this->requestQuery('q'));
} else {
return $pages->query($this->requestBody());
}
return $pages->query($this->requestBody());
}
],
[
'pattern' => 'site/sections/(:any)',
'method' => 'GET',
'action' => function (string $sectionName) {
if ($section = $this->site()->blueprint()->section($sectionName)) {
return $section->toResponse();
}
return $this->site()->blueprint()->section($sectionName)?->toResponse();
}
],
[
+5 -6
View File
@@ -17,20 +17,19 @@ return [
if ($this->kirby()->user()) {
return $system;
} else {
if ($system->isOk() === true) {
$info = $this->resolve($system)->view('login')->toArray();
} else {
$info = $this->resolve($system)->view('troubleshooting')->toArray();
}
$info = match ($system->isOk()) {
true => $this->resolve($system)->view('login')->toArray(),
false => $this->resolve($system)->view('troubleshooting')->toArray()
};
return [
'status' => 'ok',
'data' => $info,
'type' => 'model'
];
}
}
],
[
'pattern' => 'system/register',
+8 -9
View File
@@ -26,9 +26,9 @@ return [
'action' => function () {
if ($this->requestMethod() === 'GET') {
return $this->users()->search($this->requestQuery('q'));
} else {
return $this->users()->query($this->requestBody());
}
return $this->users()->query($this->requestBody());
}
],
[
@@ -79,17 +79,16 @@ return [
],
'method' => 'POST',
'action' => function (string $id) {
if ($avatar = $this->user($id)->avatar()) {
$avatar->delete();
}
$this->user($id)->avatar()?->delete();
return $this->upload(function ($source, $filename) use ($id) {
return $this->user($id)->createFile([
return $this->upload(
fn ($source, $filename) => $this->user($id)->createFile([
'filename' => 'profile.' . F::extension($filename),
'template' => 'avatar',
'source' => $source
]);
}, $single = true);
]),
single: true
);
}
],
// @codeCoverageIgnoreEnd
+63 -19
View File
@@ -1,6 +1,7 @@
<?php
use Kirby\Cms\App;
use Kirby\Toolkit\I18n;
return [
'system' => [
@@ -8,40 +9,83 @@ return [
'action' => function () {
$kirby = App::instance();
$system = $kirby->system();
$updateStatus = $system->updateStatus();
$license = $system->license();
// @codeCoverageIgnoreStart
if ($license === true) {
// valid license, but user is not admin
$license = 'Kirby 3';
} elseif ($license === false) {
// no valid license
$license = null;
$environment = [
[
'label' => $license ? I18n::translate('license') : I18n::translate('license.register.label'),
'value' => $license ? 'Kirby 3' : I18n::translate('license.unregistered.label'),
'theme' => $license ? null : 'negative',
'dialog' => $license ? 'license' : 'registration'
],
[
'label' => $updateStatus?->label() ?? I18n::translate('version'),
'value' => $kirby->version(),
'link' => (
$updateStatus ?
$updateStatus->url() :
'https://github.com/getkirby/kirby/releases/tag/' . $kirby->version()
),
'theme' => $updateStatus?->theme()
],
[
'label' => 'PHP',
'value' => phpversion()
],
[
'label' => I18n::translate('server'),
'value' => $system->serverSoftware() ?? '?'
]
];
$exceptions = $updateStatus?->exceptionMessages() ?? [];
$plugins = $system->plugins()->values(function ($plugin) use (&$exceptions) {
$authors = $plugin->authorsNames();
$updateStatus = $plugin->updateStatus();
$version = $updateStatus?->toArray() ?? $plugin->version() ?? '–';
if ($updateStatus !== null) {
$exceptions = array_merge($exceptions, $updateStatus->exceptionMessages());
}
// @codeCoverageIgnoreEnd
$plugins = $system->plugins()->values(function ($plugin) {
return [
'author' => $plugin->authorsNames(),
'license' => $plugin->license(),
'author' => empty($authors) ? '–' : $authors,
'license' => $plugin->license() ?? '–',
'name' => [
'text' => $plugin->name(),
'text' => $plugin->name() ?? '–',
'href' => $plugin->link(),
],
'version' => $plugin->version(),
'version' => $version,
];
});
$security = $updateStatus?->messages() ?? [];
if ($kirby->option('debug', false) === true) {
$security[] = [
'id' => 'debug',
'text' => I18n::translate('system.issues.debug'),
'link' => 'https://getkirby.com/security/debug'
];
}
if ($kirby->environment()->https() !== true) {
$security[] = [
'id' => 'https',
'text' => I18n::translate('system.issues.https'),
'link' => 'https://getkirby.com/security/https'
];
}
return [
'component' => 'k-system-view',
'props' => [
'debug' => $kirby->option('debug', false),
'license' => $license,
'environment' => $environment,
'exceptions' => $kirby->option('debug') === true ? $exceptions : [],
'plugins' => $plugins,
'php' => phpversion(),
'server' => $system->serverSoftware(),
'https' => $kirby->environment()->https(),
'version' => $kirby->version(),
'security' => $security,
'urls' => [
'content' => $system->exposedFileUrl('content'),
'git' => $system->exposedFileUrl('git'),
+12 -2
View File
@@ -1,5 +1,10 @@
<?php /** @var \Kirby\Cms\Block $block */ ?>
<figure>
<?php
/** @var \Kirby\Cms\Block $block */
$caption = $block->caption();
$crop = $block->crop()->isTrue();
$ratio = $block->ratio()->or('auto');
?>
<figure<?= Html::attr(['data-ratio' => $ratio, 'data-crop' => $crop], null, ' ') ?>>
<ul>
<?php foreach ($block->images()->toFiles() as $image): ?>
<li>
@@ -7,4 +12,9 @@
</li>
<?php endforeach ?>
</ul>
<?php if ($caption->isNotEmpty()): ?>
<figcaption>
<?= $caption ?>
</figcaption>
<?php endif ?>
</figure>
+24
View File
@@ -14,3 +14,27 @@ fields:
template: blocks/image
image:
ratio: 1/1
caption:
label: field.blocks.image.caption
type: writer
icon: text
inline: true
ratio:
label: field.blocks.image.ratio
type: select
placeholder: Auto
width: 1/2
options:
1/1: "1:1"
16/9: "16:9"
10/8: "10:8"
21/9: "21:9"
7/5: "7:5"
4/3: "4:3"
5/3: "5:3"
3/2: "3:2"
3/1: "3:1"
crop:
label: field.blocks.image.crop
type: toggle
width: 1/2
+16 -46
View File
@@ -4,8 +4,9 @@ use Kirby\Cms\App;
use Kirby\Cms\Collection;
use Kirby\Cms\File;
use Kirby\Cms\FileVersion;
use Kirby\Cms\Helpers;
use Kirby\Cms\Page;
use Kirby\Cms\Template;
use Kirby\Cms\User;
use Kirby\Data\Data;
use Kirby\Email\PHPMailer as Emailer;
use Kirby\Filesystem\F;
@@ -30,33 +31,6 @@ return [
*/
'css' => fn (App $kirby, string $url, $options = null): string => $url,
/**
* Object and variable dumper
* to help with debugging.
*
* @param \Kirby\Cms\App $kirby Kirby instance
* @param mixed $variable
* @param bool $echo
* @return string
*
* @deprecated 3.7.0 Disable `dump()` via `KIRBY_HELPER_DUMP` instead and create your own function
* @todo move to `Helpers::dump()`, remove component in 3.8.0
*/
'dump' => function (App $kirby, $variable, bool $echo = true) {
if ($kirby->environment()->cli() === true) {
$output = print_r($variable, true) . PHP_EOL;
} else {
$output = '<pre>' . print_r($variable, true) . '</pre>';
}
if ($echo === true) {
echo $output;
}
return $output;
},
/**
* Add your own email provider
*
@@ -108,7 +82,7 @@ return [
Data::write($job, array_merge($options, [
'filename' => $file->filename()
]));
} catch (Throwable $e) {
} catch (Throwable) {
// if thumb doesn't exist yet and job file cannot
// be created, return
return $file;
@@ -138,24 +112,16 @@ return [
* @param \Kirby\Cms\App $kirby Kirby instance
* @param string $text Text to parse
* @param array $options Markdown options
* @param bool $inline Whether to wrap the text in `<p>` tags (deprecated: set via $options['inline'] instead)
* @return string
* @todo remove $inline parameter in in 3.8.0
*/
'markdown' => function (App $kirby, string $text = null, array $options = [], bool $inline = false): string {
'markdown' => function (
App $kirby,
string $text = null,
array $options = []
): string {
static $markdown;
static $config;
// warning for deprecated fourth parameter
if (func_num_args() === 4 && isset($options['inline']) === false) {
// @codeCoverageIgnoreStart
Helpers::deprecated('markdown component: the $inline parameter is deprecated and will be removed in Kirby 3.8.0. Use $options[\'inline\'] instead.');
// @codeCoverageIgnoreEnd
}
// support for the deprecated fourth argument
$options['inline'] ??= $inline;
// if the config options have changed or the component is called for the first time,
// (re-)initialize the parser object
if ($config !== $options) {
@@ -206,17 +172,22 @@ return [
return $options['words'] ? '\b' . preg_quote($value) . '\b' : preg_quote($value);
}, $searchWords);
// returns an empty collection if there is no search word
if (empty($searchWords) === true) {
return $collection->limit(0);
}
$preg = '!(' . implode('|', $searchWords) . ')!i';
$results = $collection->filter(function ($item) use ($query, $preg, $options, $lowerQuery, $exactQuery) {
$data = $item->content()->toArray();
$keys = array_keys($data);
$keys[] = 'id';
if (is_a($item, 'Kirby\Cms\User') === true) {
if ($item instanceof User) {
$keys[] = 'name';
$keys[] = 'email';
$keys[] = 'role';
} elseif (is_a($item, 'Kirby\Cms\Page') === true) {
} elseif ($item instanceof Page) {
// apply the default score for pages
$options['score'] = array_merge([
'id' => 64,
@@ -295,9 +266,8 @@ return [
* @param \Kirby\Cms\App $kirby Kirby instance
* @param string|array $name Snippet name
* @param array $data Data array for the snippet
* @return string|null
*/
'snippet' => function (App $kirby, $name, array $data = []): ?string {
'snippet' => function (App $kirby, $name, array $data = []): string {
$snippets = A::wrap($name);
foreach ($snippets as $name) {
+2 -2
View File
@@ -46,13 +46,13 @@ return [
/**
* Latest date, which can be selected/saved (Y-m-d)
*/
'max' => function (string $max = null): ?string {
'max' => function (string $max = null): string|null {
return Date::optional($max);
},
/**
* Earliest date, which can be selected/saved (Y-m-d)
*/
'min' => function (string $min = null): ?string {
'min' => function (string $min = null): string|null {
return Date::optional($min);
},
+10 -4
View File
@@ -34,7 +34,10 @@ return [
],
'computed' => [
'parentModel' => function () {
if (is_string($this->parent) === true && $model = $this->model()->query($this->parent, 'Kirby\Cms\Model')) {
if (
is_string($this->parent) === true &&
$model = $this->model()->query($this->parent, 'Kirby\Cms\Model')
) {
return $model;
}
@@ -68,10 +71,13 @@ return [
foreach (Data::decode($value, 'yaml') as $id) {
if (is_array($id) === true) {
$id = $id['id'] ?? null;
$id = $id['uuid'] ?? $id['id'] ?? null;
}
if ($id !== null && ($file = $this->kirby()->file($id, $this->model()))) {
if (
$id !== null &&
($file = $this->kirby()->file($id, $this->model()))
) {
$files[] = $this->fileResponse($file);
}
}
@@ -122,7 +128,7 @@ return [
];
},
'save' => function ($value = null) {
return A::pluck($value, 'uuid');
return A::pluck($value, $this->store);
},
'validations' => [
'max',
+10 -12
View File
@@ -1,6 +1,6 @@
<?php
use Kirby\Form\Options;
use Kirby\Field\FieldOptions;
return [
'props' => [
@@ -30,19 +30,17 @@ return [
],
'methods' => [
'getOptions' => function () {
return Options::factory(
$this->options(),
$this->props,
$this->model()
);
$props = FieldOptions::polyfill($this->props);
$options = FieldOptions::factory($props['options']);
return $options->render($this->model());
},
'sanitizeOption' => function ($option) {
$allowed = array_column($this->options(), 'value');
return in_array($option, $allowed, true) === true ? $option : null;
'sanitizeOption' => function ($value) {
$options = array_column($this->options(), 'value');
return in_array($value, $options, true) === true ? $value : null;
},
'sanitizeOptions' => function ($options) {
$allowed = array_column($this->options(), 'value');
return array_intersect($options, $allowed);
'sanitizeOptions' => function ($values) {
$options = array_column($this->options(), 'value');
return array_intersect($values, $options);
},
]
];
+10 -1
View File
@@ -67,12 +67,21 @@ return [
return $search;
},
/**
* Whether to store UUID or path in
* the content file
*
* @param string $store 'uuid'|'id'
*/
'store' => function (string $store = 'uuid') {
return $store;
},
/**
* Main text for each item
*/
'text' => function (string $text = null) {
return $text;
},
],
];
+2 -2
View File
@@ -51,7 +51,7 @@ return [
$parent = $this->model();
}
if (is_a($parent, 'Kirby\Cms\File') === true) {
if ($parent instanceof File) {
$parent = $parent->parent();
}
@@ -62,7 +62,7 @@ return [
'filename' => $filename,
]);
if (is_a($file, 'Kirby\Cms\File') === false) {
if ($file instanceof File === false) {
throw new Exception('The file could not be uploaded');
}
+16 -1
View File
@@ -1,5 +1,7 @@
<?php
use Kirby\Toolkit\Str;
return [
'extends' => 'tags',
'props' => [
@@ -28,5 +30,18 @@ return [
'sort' => function (bool $sort = false) {
return $sort;
},
]
],
'methods' => [
'toValues' => function ($value) {
if (is_null($value) === true) {
return [];
}
if (is_array($value) === false) {
$value = Str::split($value, $this->separator());
}
return $this->sanitizeOptions($value);
}
],
];
+104
View File
@@ -0,0 +1,104 @@
<?php
use Kirby\Data\Data;
use Kirby\Exception\InvalidArgumentException;
use Kirby\Form\Form;
use Kirby\Toolkit\I18n;
return [
'props' => [
/**
* Unset inherited props
*/
'after' => null,
'before' => null,
'autofocus' => null,
'icon' => null,
'placeholder' => null,
/**
* Set the default values for the object
*/
'default' => function ($default = null) {
return $default;
},
/**
* The placeholder text if no information has been added yet
*/
'empty' => function ($empty = null) {
return I18n::translate($empty, $empty);
},
/**
* Fields setup for the object form. Works just like fields in regular forms.
*/
'fields' => function (array $fields = []) {
return $fields;
}
],
'computed' => [
'default' => function () {
if (empty($this->default) === true) {
return '';
}
return $this->form($this->default)->values();
},
'fields' => function () {
if (empty($this->fields) === true) {
throw new Exception('Please provide some fields for the object');
}
return $this->form()->fields()->toArray();
},
'value' => function () {
$data = Data::decode($this->value, 'yaml');
if (empty($data) === true) {
return '';
}
return $this->form($data)->values();
}
],
'methods' => [
'form' => function (array $values = []) {
return new Form([
'fields' => $this->attrs['fields'],
'values' => $values,
'model' => $this->model
]);
},
],
'save' => function ($value) {
if (empty($value) === true) {
return '';
}
return $this->form($value)->content();
},
'validations' => [
'object' => function ($value) {
if (empty($value) === true) {
return true;
}
$errors = $this->form($value)->errors();
if (empty($errors) === false) {
// use the first error for details
$name = array_key_first($errors);
$error = $errors[$name];
throw new InvalidArgumentException([
'key' => 'object.validation',
'data' => [
'label' => $error['label'] ?? $name,
'message' => implode("\n", $error['message'])
]
]);
}
}
]
];
+2 -2
View File
@@ -67,7 +67,7 @@ return [
foreach (Data::decode($value, 'yaml') as $id) {
if (is_array($id) === true) {
$id = $id['id'] ?? null;
$id = $id['uuid'] ?? $id['id'] ?? null;
}
if ($id !== null && ($page = $kirby->page($id))) {
@@ -102,7 +102,7 @@ return [
];
},
'save' => function ($value = null) {
return A::pluck($value, 'id');
return A::pluck($value, $this->store);
},
'validations' => [
'max',
+7 -4
View File
@@ -108,7 +108,7 @@ return [
$columns = [];
$mobile = 0;
if (empty($this->columns)) {
if (empty($this->columns) === true) {
foreach ($this->fields as $field) {
// Skip hidden and unsaveable fields
// They should never be included as column
@@ -129,7 +129,10 @@ return [
$field = $this->fields[$columnName] ?? null;
if (empty($field) === true || $field['saveable'] === false) {
if (
empty($field) === true ||
$field['saveable'] === false
) {
continue;
}
@@ -137,10 +140,10 @@ return [
$mobile++;
}
$columns[$columnName] = array_merge($columnProps, [
$columns[$columnName] = array_merge([
'type' => $field['type'],
'label' => $field['label'] ?? $field['name']
]);
], $columnProps);
}
}
+10 -21
View File
@@ -31,7 +31,7 @@ return [
* Set to `list` to display each tag with 100% width,
* otherwise the tags are displayed inline
*/
'layout' => function (?string $layout = null) {
'layout' => function (string|null $layout = null) {
return $layout;
},
/**
@@ -55,43 +55,32 @@ return [
],
'computed' => [
'default' => function (): array {
return $this->toTags($this->default);
return $this->toValues($this->default);
},
'value' => function (): array {
return $this->toTags($this->value);
return $this->toValues($this->value);
}
],
'methods' => [
'toTags' => function ($value) {
'toValues' => function ($value) {
if (is_null($value) === true) {
return [];
}
$options = $this->options();
// transform into value-text objects
return array_map(function ($option) use ($options) {
// already a valid object
if (is_array($option) === true && isset($option['value'], $option['text']) === true) {
return $option;
if (is_array($value) === false) {
$value = Str::split($value, $this->separator());
}
$index = array_search($option, array_column($options, 'value'));
if ($index !== false) {
return $options[$index];
if ($this->accept === 'options') {
$value = $this->sanitizeOptions($value);
}
return [
'value' => $option,
'text' => $option,
];
}, Str::split($value, $this->separator()));
return $value;
}
],
'save' => function (array $value = null): string {
return A::join(
A::pluck($value, 'value'),
$value,
$this->separator() . ' '
);
},
+5 -5
View File
@@ -15,7 +15,7 @@ return [
/**
* Sets the default time when a new page/file/user is created
*/
'default' => function ($default = null): ?string {
'default' => function ($default = null): string|null {
return $default;
},
@@ -36,13 +36,13 @@ return [
/**
* Latest time, which can be selected/saved (H:i or H:i:s)
*/
'max' => function (string $max = null): ?string {
'max' => function (string $max = null): string|null {
return Date::optional($max);
},
/**
* Earliest time, which can be selected/saved (H:i or H:i:s)
*/
'min' => function (string $min = null): ?string {
'min' => function (string $min = null): string|null {
return Date::optional($min);
},
@@ -62,7 +62,7 @@ return [
'unit' => 'minute',
]);
},
'value' => function ($value = null): ?string {
'value' => function ($value = null): string|null {
return $value;
}
],
@@ -80,7 +80,7 @@ return [
'format' => function () {
return $this->props['format'] ?? 'H:i:s';
},
'value' => function (): ?string {
'value' => function (): string|null {
return $this->toDatetime($this->value, 'H:i:s') ?? '';
}
],
+1 -1
View File
@@ -96,7 +96,7 @@ return [
];
},
'save' => function ($value = null) {
return A::pluck($value, 'id');
return A::pluck($value, $this->store);
},
'validations' => [
'max',
+30 -29
View File
@@ -35,7 +35,7 @@ if (Helpers::hasOverride('attr') === false) { // @codeCoverageIgnore
* @param string|null $after An optional string that will be appended if the result is not empty
* @return string|null
*/
function attr(?array $attr = null, ?string $before = null, ?string $after = null): ?string
function attr(array|null $attr = null, string|null $before = null, string|null $after = null): string|null
{
return Html::attr($attr, null, $before, $after);
}
@@ -61,7 +61,7 @@ if (Helpers::hasOverride('csrf') === false) { // @codeCoverageIgnore
* @param string|null $check Pass a token here to compare it to the one in the session
* @return string|bool Either the token or a boolean check result
*/
function csrf(?string $check = null)
function csrf(string|null $check = null)
{
// check explicitly if there have been no arguments at all;
// checking for null introduces a security issue because null could come
@@ -82,7 +82,7 @@ if (Helpers::hasOverride('css') === false) { // @codeCoverageIgnore
* @param string|array $options Pass an array of attributes for the link tag or a media attribute string
* @return string|null
*/
function css($url, $options = null): ?string
function css($url, $options = null): string|null
{
return Html::css($url, $options);
}
@@ -167,7 +167,7 @@ if (Helpers::hasOverride('gist') === false) { // @codeCoverageIgnore
* @param string|null $file
* @return string
*/
function gist(string $url, ?string $file = null): string
function gist(string $url, string|null $file = null): string
{
return App::instance()->kirbytag([
'gist' => $url,
@@ -199,7 +199,7 @@ if (Helpers::hasOverride('h') === false) { // @codeCoverageIgnore
* @param bool $keepTags
* @return string
*/
function h(?string $string, bool $keepTags = false): string
function h(string|null $string, bool $keepTags = false): string
{
return Html::encode($string, $keepTags);
}
@@ -213,7 +213,7 @@ if (Helpers::hasOverride('html') === false) { // @codeCoverageIgnore
* @param bool $keepTags
* @return string
*/
function html(?string $string, bool $keepTags = false): string
function html(string|null $string, bool $keepTags = false): string
{
return Html::encode($string, $keepTags);
}
@@ -230,7 +230,7 @@ if (Helpers::hasOverride('image') === false) { // @codeCoverageIgnore
* @param string|null $path
* @return \Kirby\Cms\File|null
*/
function image(?string $path = null)
function image(string|null $path = null)
{
return App::instance()->image($path);
}
@@ -259,7 +259,7 @@ if (Helpers::hasOverride('js') === false) { // @codeCoverageIgnore
* @param string|array $options
* @return string|null
*/
function js($url, $options = null): ?string
function js($url, $options = null): string|null
{
return Html::js($url, $options);
}
@@ -287,7 +287,7 @@ if (Helpers::hasOverride('kirbytag') === false) { // @codeCoverageIgnore
* @param array $data
* @return string
*/
function kirbytag($type, ?string $value = null, array $attr = [], array $data = []): string
function kirbytag($type, string|null $value = null, array $attr = [], array $data = []): string
{
return App::instance()->kirbytag($type, $value, $attr, $data);
}
@@ -302,7 +302,7 @@ if (Helpers::hasOverride('kirbytags') === false) { // @codeCoverageIgnore
* @param array $data
* @return string
*/
function kirbytags(?string $text = null, array $data = []): string
function kirbytags(string|null $text = null, array $data = []): string
{
return App::instance()->kirbytags($text, $data);
}
@@ -317,7 +317,7 @@ if (Helpers::hasOverride('kirbytext') === false) { // @codeCoverageIgnore
* @param array $data
* @return string
*/
function kirbytext(?string $text = null, array $data = []): string
function kirbytext(string|null $text = null, array $data = []): string
{
return App::instance()->kirbytext($text, $data);
}
@@ -333,7 +333,7 @@ if (Helpers::hasOverride('kirbytextinline') === false) { // @codeCoverageIgnore
* @param array $options
* @return string
*/
function kirbytextinline(?string $text = null, array $options = []): string
function kirbytextinline(string|null $text = null, array $options = []): string
{
$options['markdown']['inline'] = true;
return App::instance()->kirbytext($text, $options);
@@ -348,7 +348,7 @@ if (Helpers::hasOverride('kt') === false) { // @codeCoverageIgnore
* @param array $data
* @return string
*/
function kt(?string $text = null, array $data = []): string
function kt(string|null $text = null, array $data = []): string
{
return App::instance()->kirbytext($text, $data);
}
@@ -363,7 +363,7 @@ if (Helpers::hasOverride('kti') === false) { // @codeCoverageIgnore
* @param array $options
* @return string
*/
function kti(?string $text = null, array $options = []): string
function kti(string|null $text = null, array $options = []): string
{
$options['markdown']['inline'] = true;
return App::instance()->kirbytext($text, $options);
@@ -378,7 +378,7 @@ if (Helpers::hasOverride('load') === false) { // @codeCoverageIgnore
* @param string|null $base
* @return void
*/
function load(array $classmap, ?string $base = null): void
function load(array $classmap, string|null $base = null): void
{
F::loadClasses($classmap, $base);
}
@@ -393,7 +393,7 @@ if (Helpers::hasOverride('markdown') === false) { // @codeCoverageIgnore
* @param array $options
* @return string
*/
function markdown(?string $text = null, array $options = []): string
function markdown(string|null $text = null, array $options = []): string
{
return App::instance()->markdown($text, $options);
}
@@ -421,7 +421,7 @@ if (Helpers::hasOverride('page') === false) { // @codeCoverageIgnore
* @param string|null $id
* @return \Kirby\Cms\Page|null
*/
function page(?string $id = null)
function page(string|null $id = null)
{
if (empty($id) === true) {
return App::instance()->site()->page();
@@ -459,8 +459,9 @@ if (Helpers::hasOverride('param') === false) { // @codeCoverageIgnore
* @param string $key
* @param string|null $fallback
* @return string|null
* @psalm-return ($fallback is string ? string : string|null)
*/
function param(string $key, ?string $fallback = null): ?string
function param(string $key, string|null $fallback = null): string|null
{
return App::instance()->request()->url()->params()->$key ?? $fallback;
}
@@ -505,7 +506,7 @@ if (Helpers::hasOverride('router') === false) { // @codeCoverageIgnore
* @param \Closure|null $callback
* @return mixed
*/
function router(?string $path = null, string $method = 'GET', array $routes = [], ?Closure $callback = null)
function router(string|null $path = null, string $method = 'GET', array $routes = [], Closure|null $callback = null)
{
return Router::execute($path, $method, $routes, $callback);
}
@@ -545,7 +546,7 @@ if (Helpers::hasOverride('smartypants') === false) { // @codeCoverageIgnore
* @param string|null $text
* @return string
*/
function smartypants(?string $text = null): string
function smartypants(string|null $text = null): string
{
return App::instance()->smartypants($text);
}
@@ -560,7 +561,7 @@ if (Helpers::hasOverride('snippet') === false) { // @codeCoverageIgnore
* @param bool $return
* @return string|null
*/
function snippet($name, $data = [], bool $return = false): ?string
function snippet($name, $data = [], bool $return = false): string|null
{
return App::instance()->snippet($name, $data, $return);
}
@@ -624,7 +625,7 @@ if (Helpers::hasOverride('timestamp') === false) { // @codeCoverageIgnore
* @param int|array|null $step array of `unit` and `size` to round to nearest
* @return int|null
*/
function timestamp(?string $date = null, $step = null): ?int
function timestamp(string|null $date = null, $step = null): int|null
{
return Date::roundedTimestamp($date, $step);
}
@@ -641,7 +642,7 @@ if (Helpers::hasOverride('tt') === false) { // @codeCoverageIgnore
* @param string|null $locale
* @return string
*/
function tt(string $key, $fallback = null, ?array $replace = null, ?string $locale = null): string
function tt(string $key, $fallback = null, array|null $replace = null, string|null $locale = null): string
{
return I18n::template($key, $fallback, $replace, $locale);
}
@@ -657,7 +658,7 @@ if (Helpers::hasOverride('twitter') === false) { // @codeCoverageIgnore
* @param string|null $class
* @return string
*/
function twitter(string $username, ?string $text = null, ?string $title = null, ?string $class = null): string
function twitter(string $username, string|null $text = null, string|null $title = null, string|null $class = null): string
{
return App::instance()->kirbytag([
'twitter' => $username,
@@ -676,7 +677,7 @@ if (Helpers::hasOverride('u') === false) { // @codeCoverageIgnore
* @param array|string|null $options
* @return string
*/
function u(?string $path = null, $options = null): string
function u(string|null $path = null, $options = null): string
{
return Url::to($path, $options);
}
@@ -690,7 +691,7 @@ if (Helpers::hasOverride('url') === false) { // @codeCoverageIgnore
* @param array|string|null $options
* @return string
*/
function url(?string $path = null, $options = null): string
function url(string|null $path = null, $options = null): string
{
return Url::to($path, $options);
}
@@ -719,7 +720,7 @@ if (Helpers::hasOverride('video') === false) { // @codeCoverageIgnore
* @param array $attr
* @return string|null
*/
function video(string $url, array $options = [], array $attr = []): ?string
function video(string $url, array $options = [], array $attr = []): string|null
{
return Html::video($url, $options, $attr);
}
@@ -734,7 +735,7 @@ if (Helpers::hasOverride('vimeo') === false) { // @codeCoverageIgnore
* @param array $attr
* @return string|null
*/
function vimeo(string $url, array $options = [], array $attr = []): ?string
function vimeo(string $url, array $options = [], array $attr = []): string|null
{
return Html::vimeo($url, $options, $attr);
}
@@ -764,7 +765,7 @@ if (Helpers::hasOverride('youtube') === false) { // @codeCoverageIgnore
* @param array $attr
* @return string|null
*/
function youtube(string $url, array $options = [], array $attr = []): ?string
function youtube(string $url, array $options = [], array $attr = []): string|null
{
return Html::youtube($url, $options, $attr);
}
+30 -20
View File
@@ -2,6 +2,7 @@
use Kirby\Cms\App;
use Kirby\Cms\Blocks;
use Kirby\Cms\Content;
use Kirby\Cms\Field;
use Kirby\Cms\Files;
use Kirby\Cms\Html;
@@ -63,16 +64,16 @@ return function (App $app) {
*/
'toBlocks' => function (Field $field) {
try {
$blocks = Blocks::factory(Blocks::parse($field->value()), [
'parent' => $field->parent(),
$blocks = Blocks::parse($field->value());
$blocks = Blocks::factory($blocks, [
'parent' => $field->parent()
]);
return $blocks->filter('isHidden', false);
} catch (Throwable $e) {
if ($field->parent() === null) {
} catch (Throwable) {
$message = 'Invalid blocks data for "' . $field->key() . '" field';
} else {
$message = 'Invalid blocks data for "' . $field->key() . '" field on parent "' . $field->parent()->title() . '"';
if ($parent = $field->parent()) {
$message .= ' on parent "' . $parent->title() . '"';
}
throw new InvalidArgumentException($message);
@@ -99,13 +100,10 @@ return function (App $app) {
* @return array
*/
'toData' => function (Field $field, string $method = ',') {
switch ($method) {
case 'yaml':
case 'json':
return Data::decode($field->value, $method);
default:
return $field->split($method);
}
return match ($method) {
'yaml', 'json' => Data::decode($field->value, $method),
default => $field->split($method)
};
},
/**
@@ -222,6 +220,17 @@ return function (App $app) {
return Html::a($href, $field->value, $attr ?? []);
},
/**
* Parse yaml data and convert it to a
* content object
*
* @param \Kirby\Cms\Field $field
* @return \Kirby\Cms\Content
*/
'toObject' => function (Field $field) {
return new Content($field->yaml(), $field->parent(), true);
},
/**
* Returns a page object from a page id in the field
*
@@ -252,11 +261,11 @@ return function (App $app) {
'toStructure' => function (Field $field) {
try {
return new Structure(Data::decode($field->value, 'yaml'), $field->parent());
} catch (Exception $e) {
if ($field->parent() === null) {
} catch (Exception) {
$message = 'Invalid structure data for "' . $field->key() . '" field';
} else {
$message = 'Invalid structure data for "' . $field->key() . '" field on parent "' . $field->parent()->title() . '"';
if ($parent = $field->parent()) {
$message .= ' on parent "' . $parent->title() . '"';
}
throw new InvalidArgumentException($message);
@@ -500,10 +509,11 @@ return function (App $app) {
*
* @param \Kirby\Cms\Field $field
* @param array $data
* @param string $fallback Fallback for tokens in the template that cannot be replaced
* @param string|null $fallback Fallback for tokens in the template that cannot be replaced
* (`null` to keep the original token)
* @return \Kirby\Cms\Field
*/
'replace' => function (Field $field, array $data = [], string $fallback = '') use ($app) {
'replace' => function (Field $field, array $data = [], string|null $fallback = '') use ($app) {
if ($parent = $field->parent()) {
// never pass `null` as the $template to avoid the fallback to the model ID
$field->value = $parent->toString($field->value ?? '', $data, $fallback);
+2 -1
View File
@@ -5,7 +5,7 @@ use Kirby\Toolkit\I18n;
return function (array $props) {
$props['sections'] = [
'files' => [
'headline' => $props['headline'] ?? I18n::translate('files'),
'label' => $props['label'] ?? $props['headline'] ?? I18n::translate('files'),
'type' => 'files',
'layout' => $props['layout'] ?? 'cards',
'template' => $props['template'] ?? null,
@@ -17,6 +17,7 @@ return function (array $props) {
// remove global options
unset(
$props['headline'],
$props['label'],
$props['layout'],
$props['template'],
$props['image']
+3 -3
View File
@@ -10,7 +10,7 @@ return function ($props) {
if (is_string($props) === true) {
$props = [
'headline' => $props
'label' => $props
];
}
@@ -27,7 +27,7 @@ return function ($props) {
if ($pages !== false) {
$sidebar['pages'] = $section([
'headline' => I18n::translate('pages'),
'label' => I18n::translate('pages'),
'type' => 'pages',
'status' => 'all',
'layout' => 'list',
@@ -36,7 +36,7 @@ return function ($props) {
if ($files !== false) {
$sidebar['files'] = $section([
'headline' => I18n::translate('files'),
'label' => I18n::translate('files'),
'type' => 'files',
'layout' => 'list'
], $files);
+3 -3
View File
@@ -6,9 +6,9 @@ return function (array $props) {
// load the general templates setting for all sections
$templates = $props['templates'] ?? null;
$section = function ($headline, $status, $props) use ($templates) {
$section = function ($label, $status, $props) use ($templates) {
$defaults = [
'headline' => $headline,
'label' => $label,
'type' => 'pages',
'layout' => 'list',
'status' => $status
@@ -20,7 +20,7 @@ return function (array $props) {
if (is_string($props) === true) {
$props = [
'headline' => $props
'label' => $props
];
}
+21
View File
@@ -6,6 +6,7 @@ use Kirby\Cms\PluginAssets;
use Kirby\Panel\Panel;
use Kirby\Panel\Plugins;
use Kirby\Toolkit\Str;
use Kirby\Uuid\Uuid;
return function ($kirby) {
$api = $kirby->option('api.slug', 'api');
@@ -101,6 +102,26 @@ return function ($kirby) {
return Panel::router($path);
}
],
// permalinks for page/file UUIDs
[
'pattern' => '@/(page|file)/(:all)',
'method' => 'ALL',
'env' => 'site',
'action' => function (string $type, string $id) use ($kirby) {
// try to resolve to model, but only from UUID cache;
// this ensures that only existing UUIDs can be queried
// and attackers can't force Kirby to go through the whole
// site index with a non-existing UUID
if ($model = Uuid::for($type . '://' . $id)->model(true)) {
return $kirby
->response()
->redirect($model->url());
}
// render the error page
return false;
}
],
];
// Multi-language setup
+6 -1
View File
@@ -1,5 +1,7 @@
<?php
use Kirby\Cms\Page;
use Kirby\Cms\Site;
use Kirby\Form\Form;
return [
@@ -31,7 +33,10 @@ return [
'fields' => function () {
$fields = $this->form->fields()->toArray();
if (is_a($this->model, 'Kirby\Cms\Page') === true || is_a($this->model, 'Kirby\Cms\Site') === true) {
if (
$this->model instanceof Page ||
$this->model instanceof Site
) {
// the title should never be updated directly via
// fields section to avoid conflicts with the rename dialog
unset($fields['title']);
+1 -1
View File
@@ -25,7 +25,7 @@ return [
],
'toArray' => function () {
return [
'headline' => $this->headline,
'label' => $this->headline,
'text' => $this->text,
'theme' => $this->theme
];
+5 -11
View File
@@ -1,20 +1,14 @@
<?php
use Kirby\Cms\Helpers;
use Kirby\Toolkit\I18n;
return [
'props' => [
/**
* The headline for the section. This can be a simple string or a template with additional info from the parent page.
* @todo remove in 3.9.0
* @deprecated 3.8.0 Use `label` instead
*/
'headline' => function ($headline = null) {
// TODO: add deprecation notive in 3.8.0
// if ($headline !== null) {
// Helpers::deprecated('`headline` prop for sections has been deprecated and will be removed in Kirby 3.9.0. Use `label` instead.');
// }
return I18n::translate($headline, $headline);
},
/**
@@ -28,14 +22,14 @@ return [
],
'computed' => [
'headline' => function () {
if ($this->headline) {
return $this->model()->toString($this->headline);
}
if ($this->label) {
return $this->model()->toString($this->label);
}
if ($this->headline) {
return $this->model()->toString($this->headline);
}
return ucfirst($this->name);
}
]
+8 -4
View File
@@ -1,5 +1,9 @@
<?php
use Kirby\Cms\File;
use Kirby\Cms\Page;
use Kirby\Cms\Site;
use Kirby\Cms\User;
use Kirby\Exception\Exception;
return [
@@ -24,10 +28,10 @@ return [
}
if (
is_a($parent, 'Kirby\Cms\Page') === false &&
is_a($parent, 'Kirby\Cms\Site') === false &&
is_a($parent, 'Kirby\Cms\File') === false &&
is_a($parent, 'Kirby\Cms\User') === false
$parent instanceof Page === false &&
$parent instanceof Site === false &&
$parent instanceof File === false &&
$parent instanceof User === false
) {
throw new Exception('The parent for the section "' . $this->name() . '" has to be a page, site or user object');
}
+1 -1
View File
@@ -12,7 +12,7 @@ return [
}
],
'methods' => [
'searchterm' => function (): ?string {
'searchterm' => function (): string|null {
return App::instance()->request()->get('searchterm');
}
]
+12 -19
View File
@@ -1,6 +1,8 @@
<?php
use Kirby\Cms\Blueprint;
use Kirby\Cms\Page;
use Kirby\Cms\Site;
use Kirby\Exception\InvalidArgumentException;
use Kirby\Toolkit\A;
use Kirby\Toolkit\I18n;
@@ -53,8 +55,8 @@ return [
$parent = $this->parentModel();
if (
is_a($parent, 'Kirby\Cms\Site') === false &&
is_a($parent, 'Kirby\Cms\Page') === false
$parent instanceof Site === false &&
$parent instanceof Page === false
) {
throw new InvalidArgumentException('The parent is invalid. You must choose the site or a page as parent.');
}
@@ -62,22 +64,13 @@ return [
return $parent;
},
'pages' => function () {
switch ($this->status) {
case 'draft':
$pages = $this->parent->drafts();
break;
case 'listed':
$pages = $this->parent->children()->listed();
break;
case 'published':
$pages = $this->parent->children();
break;
case 'unlisted':
$pages = $this->parent->children()->unlisted();
break;
default:
$pages = $this->parent->childrenAndDrafts();
}
$pages = match ($this->status) {
'draft' => $this->parent->drafts(),
'listed' => $this->parent->children()->listed(),
'published' => $this->parent->children(),
'unlisted' => $this->parent->children()->unlisted(),
default => $this->parent->childrenAndDrafts()
};
// filters pages that are protected and not in the templates list
// internal `filter()` method used instead of foreach loop that previously included `unset()`
@@ -228,7 +221,7 @@ return [
'name' => basename($props['name']),
'title' => $props['title'],
];
} catch (Throwable $e) {
} catch (Throwable) {
$blueprints[] = [
'name' => basename($template),
'title' => ucfirst($template),
+1
View File
@@ -2,6 +2,7 @@
/**
* Constants
* @deprecated 3.8.0 Use `/` instead
*/
define('DS', '/');
+12 -5
View File
@@ -3,6 +3,7 @@
use Kirby\Cms\Html;
use Kirby\Cms\Url;
use Kirby\Toolkit\Str;
use Kirby\Uuid\Uuid;
/**
* Default KirbyTags definition
@@ -117,11 +118,8 @@ return [
return $img;
}
if ($link = $tag->file($tag->link)) {
$link = $link->url();
} else {
$link = $tag->link === 'self' ? $tag->src : $tag->link;
}
$link = $tag->file($tag->link)?->url();
$link ??= $tag->link === 'self' ? $tag->src : $tag->link;
return Html::a($link, [$img], [
'rel' => $tag->rel,
@@ -173,6 +171,15 @@ return [
$tag->value = Url::to($tag->value, $tag->lang);
}
// if value is a UUID, resolve to page/file model
// and use the URL as value
if (
Uuid::is($tag->value, 'page') === true ||
Uuid::is($tag->value, 'file') === true
) {
$tag->value = Uuid::for($tag->value)->model()->url();
}
return Html::a($tag->value, $tag->text, [
'rel' => $tag->rel,
'class' => $tag->class,
+25 -2
View File
@@ -70,7 +70,7 @@
"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.validation": "There's an error on the \"{field}\" field in block {index} using the \"{fieldset}\" block type",
"error.email.preset.notFound": "Email шаблонът \"{name}\" не може да бъде открит",
@@ -107,13 +107,15 @@
"error.language.name": "Please enter a valid name for the language",
"error.language.notFound": "The language could not be found",
"error.layout.validation.block": "There's an error in block {blockIndex} in layout {layoutIndex}",
"error.layout.validation.block": "There's an error on the \"{field}\" field in block {blockIndex} using the \"{fieldset}\" block type in layout {layoutIndex}",
"error.layout.validation.settings": "There's an error in layout {index} settings",
"error.license.format": "Please enter a valid license key",
"error.license.email": "Моля въведете валиден email адрес",
"error.license.verification": "The license could not be verified",
"error.object.validation": "There’s an error in the \"{label}\" field:\n{message}",
"error.offline": "The Panel is currently offline",
"error.page.changeSlug.permission": "Не можете да смените URL на \"{slug}\"",
@@ -282,9 +284,13 @@
"field.layout.empty": "No rows yet",
"field.layout.select": "Select a layout",
"field.object.empty": "No information yet",
"field.pages.empty": "Все още не са избрани страници",
"field.structure.delete.confirm": "Сигурни ли сте, че искате да изтриете това вписване?",
"field.structure.empty": "Все още няма статии",
"field.users.empty": "Все още не са избрани потребители",
"file.blueprint": "This file has no blueprint yet. You can define the setup in <strong>/site/blueprints/files/{blueprint}.yml</strong>",
@@ -448,6 +454,7 @@
"paste": "Paste",
"paste.after": "Paste after",
"pixel": "Пиксел",
"plugin": "Plugin",
"plugins": "Plugins",
"prev": "Previous",
"preview": "Preview",
@@ -487,11 +494,24 @@
"stats.empty": "No reports",
"system.issues.content": "The content folder seems to be exposed",
"system.issues.eol.kirby": "Your installed Kirby version has reached end-of-life and will not receive further security updates",
"system.issues.eol.plugin": "Your installed version of the { plugin } plugin is has reached end-of-life and will not receive further security updates",
"system.issues.debug": "Debugging must be turned off in production",
"system.issues.git": "The .git folder seems to be exposed",
"system.issues.https": "We recommend HTTPS for all your sites",
"system.issues.kirby": "The kirby folder seems to be exposed",
"system.issues.site": "The site folder seems to be exposed",
"system.issues.vulnerability.kirby": "Your installation might be affected by the following vulnerability ({ severity } severity): { description }",
"system.issues.vulnerability.plugin": "Your installation might be affected by the following vulnerability in the { plugin } plugin ({ severity } severity): { description }",
"system.updateStatus": "Update status",
"system.updateStatus.error": "Could not check for updates",
"system.updateStatus.not-vulnerable": "No known vulnerabilities",
"system.updateStatus.security-update": "Free security update { version } available",
"system.updateStatus.security-upgrade": "Upgrade { version } with security fixes available",
"system.updateStatus.unreleased": "Unreleased version",
"system.updateStatus.up-to-date": "Up to date",
"system.updateStatus.update": "Free update { version } available",
"system.updateStatus.upgrade": "Upgrade { version } available",
"title": "Заглавие",
"template": "Образец",
@@ -558,6 +578,9 @@
"users": "Потребители",
"version": "\u0412\u0435\u0440\u0441\u0438\u044f \u043d\u0430 Kirby",
"version.current": "Current version",
"version.latest": "Latest version",
"versionInformation": "Version information",
"view.account": "\u0412\u0430\u0448\u0438\u044f \u0430\u043a\u0430\u0443\u043d\u0442",
"view.installation": "\u0418\u043d\u0441\u0442\u0430\u043b\u0430\u0446\u0438\u044f",
+25 -2
View File
@@ -70,7 +70,7 @@
"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.validation": "There's an error on the \"{field}\" field in block {index} using the \"{fieldset}\" block type",
"error.email.preset.notFound": "No es pot trobar la configuració de correu electrònic \"{name}\"",
@@ -107,13 +107,15 @@
"error.language.name": "Introdueix un nom vàlid per a l'idioma",
"error.language.notFound": "The language could not be found",
"error.layout.validation.block": "There's an error in block {blockIndex} in layout {layoutIndex}",
"error.layout.validation.block": "There's an error on the \"{field}\" field in block {blockIndex} using the \"{fieldset}\" block type in layout {layoutIndex}",
"error.layout.validation.settings": "There's an error in layout {index} settings",
"error.license.format": "Introduïu una clau de llicència vàlida",
"error.license.email": "Si us plau, introdueix una adreça de correu electrònic vàlida",
"error.license.verification": "No s’ha pogut verificar la llicència",
"error.object.validation": "There’s an error in the \"{label}\" field:\n{message}",
"error.offline": "The Panel is currently offline",
"error.page.changeSlug.permission": "No teniu permís per canviar l'apèndix d'URL per a \"{slug}\"",
@@ -282,9 +284,13 @@
"field.layout.empty": "No rows yet",
"field.layout.select": "Select a layout",
"field.object.empty": "No information yet",
"field.pages.empty": "Encara no s'ha seleccionat cap pàgina",
"field.structure.delete.confirm": "Segur que voleu eliminar aquesta fila?",
"field.structure.empty": "Encara no hi ha entrades.",
"field.users.empty": "Encara no s'ha seleccionat cap usuari",
"file.blueprint": "This file has no blueprint yet. You can define the setup in <strong>/site/blueprints/files/{blueprint}.yml</strong>",
@@ -448,6 +454,7 @@
"paste": "Paste",
"paste.after": "Paste after",
"pixel": "Pixel",
"plugin": "Plugin",
"plugins": "Plugins",
"prev": "Anterior",
"preview": "Preview",
@@ -487,11 +494,24 @@
"stats.empty": "No reports",
"system.issues.content": "The content folder seems to be exposed",
"system.issues.eol.kirby": "Your installed Kirby version has reached end-of-life and will not receive further security updates",
"system.issues.eol.plugin": "Your installed version of the { plugin } plugin is has reached end-of-life and will not receive further security updates",
"system.issues.debug": "Debugging must be turned off in production",
"system.issues.git": "The .git folder seems to be exposed",
"system.issues.https": "We recommend HTTPS for all your sites",
"system.issues.kirby": "The kirby folder seems to be exposed",
"system.issues.site": "The site folder seems to be exposed",
"system.issues.vulnerability.kirby": "Your installation might be affected by the following vulnerability ({ severity } severity): { description }",
"system.issues.vulnerability.plugin": "Your installation might be affected by the following vulnerability in the { plugin } plugin ({ severity } severity): { description }",
"system.updateStatus": "Update status",
"system.updateStatus.error": "Could not check for updates",
"system.updateStatus.not-vulnerable": "No known vulnerabilities",
"system.updateStatus.security-update": "Free security update { version } available",
"system.updateStatus.security-upgrade": "Upgrade { version } with security fixes available",
"system.updateStatus.unreleased": "Unreleased version",
"system.updateStatus.up-to-date": "Up to date",
"system.updateStatus.update": "Free update { version } available",
"system.updateStatus.upgrade": "Upgrade { version } available",
"title": "Títol",
"template": "Plantilla",
@@ -558,6 +578,9 @@
"users": "Usuaris",
"version": "Versi\u00f3 de Kirby",
"version.current": "Current version",
"version.latest": "Latest version",
"versionInformation": "Version information",
"view.account": "La teva compta",
"view.installation": "Instal·lació",
+39 -16
View File
@@ -49,8 +49,8 @@
"email": "Email",
"email.placeholder": "mail@example.com",
"entries": "Entries",
"entry": "Entry",
"entries": "Záznamy",
"entry": "Záznam",
"environment": "Prostředí",
@@ -70,7 +70,7 @@
"error.blocks.max.singular": "Nelze přidat více než jeden blok",
"error.blocks.min.plural": "Musíte přidat alespoň {min} bloků",
"error.blocks.min.singular": "Musíte přidat alespoň jeden blok",
"error.blocks.validation": "Chyba v bloku {index}",
"error.blocks.validation": "V poli \"{field}\" v bloku {index} je při použití \"{fieldset}\" typu chyba",
"error.email.preset.notFound": "Nelze nalézt emailové přednastavení \"{name}\"",
@@ -107,13 +107,15 @@
"error.language.name": "Zadejte prosím platné jméno jazyka",
"error.language.notFound": "Jazyk nebyl nalezen",
"error.layout.validation.block": "Chyba v bloku {blockIndex} v rozvržení {layoutIndex}",
"error.layout.validation.block": "V rozvržení {layoutIndex} je v poli \"{field}\" v bloku {blockIndex} při použití \"{fieldset}\" typu chyba",
"error.layout.validation.settings": "Chyba v nastavení rozvržení {index}",
"error.license.format": "Zadejte prosím platné licenční číslo",
"error.license.email": "Zadejte prosím platnou emailovou adresu",
"error.license.verification": "Licenci nelze ověřit",
"error.object.validation": "V poli \"{label}\" je chyba:\n{message}",
"error.offline": "Panel je v současnosti off-line",
"error.page.changeSlug.permission": "Nem\u016f\u017eete zm\u011bnit URL t\u00e9to str\u00e1nky",
@@ -282,9 +284,13 @@
"field.layout.empty": "Zatím žádné řádky",
"field.layout.select": "Vyberte rozložení",
"field.object.empty": "Zatím žádná informace",
"field.pages.empty": "Nebyly zatím vybrány žádné stránky",
"field.structure.delete.confirm": "Opravdu chcete smazat tento z\u00e1znam?",
"field.structure.empty": "Zat\u00edm nejsou \u017e\u00e1dn\u00e9 z\u00e1znamy.",
"field.users.empty": "Nebyli zatím vybráni žádní uživatelé",
"file.blueprint": "Tento typ souboru nemá blueprint. Blueprint můžete definovat v <strong>/site/blueprints/files/{blueprint}.yml</strong>",
@@ -297,7 +303,7 @@
"hide": "Skrýt",
"hour": "Hodina",
"import": "Import",
"info": "Info",
"info": "Informace",
"insert": "Vlo\u017eit",
"insert.after": "Vložit za",
"insert.before": "Vložit před",
@@ -340,12 +346,12 @@
"license": "Kirby licence",
"license.buy": "Zakoupit licenci",
"license.register": "Registrovat",
"license.manage": "Manage your licenses",
"license.manage": "Spravovat licence",
"license.register.help": "Licenční kód jste po zakoupení obdrželi na email. Vložte prosím kód a zaregistrujte Vaší kopii.",
"license.register.label": "Zadejte prosím licenční kód",
"license.register.success": "Děkujeme Vám za podporu Kirby",
"license.unregistered": "Toto je neregistrovaná kopie Kirby",
"license.unregistered.label": "Unregistered",
"license.unregistered.label": "Neregistrovaný",
"link": "Odkaz",
"link.text": "Text odkazu",
@@ -360,7 +366,7 @@
"lock.unlock": "Odemknout",
"lock.isUnlocked": "Vaše neuložené změny byly přepsány jiným uživatelem. Můžeze si své úpravy stáhnout a zapracovat je ručně.",
"login": "P\u0159ihl\u00e1sit se",
"login": "Přihlásit se",
"login.code.label.login": "Kód pro přihlášení",
"login.code.label.password-reset": "Kód pro resetování hesla",
"login.code.placeholder.email": "000 000",
@@ -448,6 +454,7 @@
"paste": "Vložit",
"paste.after": "Vložit za",
"pixel": "Pixel",
"plugin": "Plugin",
"plugins": "Doplňky",
"prev": "Předchozí",
"preview": "Náhled",
@@ -475,7 +482,7 @@
"section.required": "Sekce musí být vyplněna",
"security": "Security",
"security": "Zabezpečení",
"select": "Vybrat",
"server": "Server",
"settings": "Nastavení",
@@ -485,13 +492,26 @@
"slug": "P\u0159\u00edpona URL",
"sort": "Řadit",
"stats.empty": "No reports",
"system.issues.content": "The content folder seems to be exposed",
"system.issues.debug": "Debugging must be turned off in production",
"system.issues.git": "The .git folder seems to be exposed",
"system.issues.https": "We recommend HTTPS for all your sites",
"system.issues.kirby": "The kirby folder seems to be exposed",
"system.issues.site": "The site folder seems to be exposed",
"stats.empty": "Žádná hlášení",
"system.issues.content": "Složka content je zřejmě přístupná zvenčí",
"system.issues.eol.kirby": "Your installed Kirby version has reached end-of-life and will not receive further security updates",
"system.issues.eol.plugin": "Your installed version of the { plugin } plugin is has reached end-of-life and will not receive further security updates",
"system.issues.debug": "Debug mode musí být v produkci vypnutý",
"system.issues.git": "Složka .git je zřejmě přístupná zvenčí",
"system.issues.https": "Při všechny stránky doporučujeme používat protokol HTTPS",
"system.issues.kirby": "Složka kirby je zřejmě přístupná zvenčí",
"system.issues.site": "Složka site je zřejmě přístupná zvenčí",
"system.issues.vulnerability.kirby": "Your installation might be affected by the following vulnerability ({ severity } severity): { description }",
"system.issues.vulnerability.plugin": "Your installation might be affected by the following vulnerability in the { plugin } plugin ({ severity } severity): { description }",
"system.updateStatus": "Update status",
"system.updateStatus.error": "Could not check for updates",
"system.updateStatus.not-vulnerable": "No known vulnerabilities",
"system.updateStatus.security-update": "Free security update { version } available",
"system.updateStatus.security-upgrade": "Upgrade { version } with security fixes available",
"system.updateStatus.unreleased": "Unreleased version",
"system.updateStatus.up-to-date": "Up to date",
"system.updateStatus.update": "Free update { version } available",
"system.updateStatus.upgrade": "Upgrade { version } available",
"title": "Název",
"template": "\u0160ablona",
@@ -558,6 +578,9 @@
"users": "Uživatelé",
"version": "Verze Kirby",
"version.current": "Current version",
"version.latest": "Latest version",
"versionInformation": "Version information",
"view.account": "V\u00e1\u0161 \u00fa\u010det",
"view.installation": "Instalace",
+25 -2
View File
@@ -70,7 +70,7 @@
"error.blocks.max.singular": "Du må ikke tilføje mere end een blok",
"error.blocks.min.plural": "Du skal tilføje minimum {min} blokke",
"error.blocks.min.singular": "Du skal tilføje minimum een blok",
"error.blocks.validation": "Der er fejl i blok {index}",
"error.blocks.validation": "There's an error on the \"{field}\" field in block {index} using the \"{fieldset}\" block type",
"error.email.preset.notFound": "Email preset \"{name}\" findes ikke",
@@ -107,13 +107,15 @@
"error.language.name": "Indtast venligst et gyldigt navn for sproget",
"error.language.notFound": "Sproget fandtes ikke",
"error.layout.validation.block": "Der er fejl i blok {blockIndex} i layout {layoutIndex}",
"error.layout.validation.block": "There's an error on the \"{field}\" field in block {blockIndex} using the \"{fieldset}\" block type in layout {layoutIndex}",
"error.layout.validation.settings": "Der er fejl i layout {index} indstillinger",
"error.license.format": "Indtast venligst en gyldig licensnøgle",
"error.license.email": "Indtast venligst en gyldig email adresse",
"error.license.verification": "Licensen kunne ikke verificeres",
"error.object.validation": "There’s an error in the \"{label}\" field:\n{message}",
"error.offline": "Panelet er i øjeblikket offline",
"error.page.changeSlug.permission": "Du kan ikke ændre URL-endelse for \"{slug}\"",
@@ -282,9 +284,13 @@
"field.layout.empty": "Ingen rækker endnu",
"field.layout.select": "Vælg et layout",
"field.object.empty": "No information yet",
"field.pages.empty": "Ingen sider valgt endnu",
"field.structure.delete.confirm": "\u00d8nsker du virkelig at slette denne indtastning?",
"field.structure.empty": "Ingen indtastninger endnu.",
"field.users.empty": "Ingen brugere er valgt",
"file.blueprint": "Denne fil har intet blueprint endnu. Du kan definere opsætningen i <strong>/site/blueprints/files/{blueprint}.yml</strong>",
@@ -448,6 +454,7 @@
"paste": "Indsæt",
"paste.after": "Indsæt efter",
"pixel": "Pixel",
"plugin": "Plugin",
"plugins": "Plugins",
"prev": "Forrige",
"preview": "Forhåndsvisning",
@@ -487,11 +494,24 @@
"stats.empty": "No reports",
"system.issues.content": "The content folder seems to be exposed",
"system.issues.eol.kirby": "Your installed Kirby version has reached end-of-life and will not receive further security updates",
"system.issues.eol.plugin": "Your installed version of the { plugin } plugin is has reached end-of-life and will not receive further security updates",
"system.issues.debug": "Debugging must be turned off in production",
"system.issues.git": "The .git folder seems to be exposed",
"system.issues.https": "We recommend HTTPS for all your sites",
"system.issues.kirby": "The kirby folder seems to be exposed",
"system.issues.site": "The site folder seems to be exposed",
"system.issues.vulnerability.kirby": "Your installation might be affected by the following vulnerability ({ severity } severity): { description }",
"system.issues.vulnerability.plugin": "Your installation might be affected by the following vulnerability in the { plugin } plugin ({ severity } severity): { description }",
"system.updateStatus": "Update status",
"system.updateStatus.error": "Could not check for updates",
"system.updateStatus.not-vulnerable": "No known vulnerabilities",
"system.updateStatus.security-update": "Free security update { version } available",
"system.updateStatus.security-upgrade": "Upgrade { version } with security fixes available",
"system.updateStatus.unreleased": "Unreleased version",
"system.updateStatus.up-to-date": "Up to date",
"system.updateStatus.update": "Free update { version } available",
"system.updateStatus.upgrade": "Upgrade { version } available",
"title": "Titel",
"template": "Skabelon",
@@ -558,6 +578,9 @@
"users": "Brugere",
"version": "Kirby version",
"version.current": "Current version",
"version.latest": "Latest version",
"versionInformation": "Version information",
"view.account": "Din konto",
"view.installation": "Installation",
+25 -2
View File
@@ -70,7 +70,7 @@
"error.blocks.max.singular": "Bitte füge nicht mehr als einen Block hinzu",
"error.blocks.min.plural": "Bitte füge mindestens {min} Blöcke hinzu",
"error.blocks.min.singular": "Bitte füge mindestens einen Block hinzu",
"error.blocks.validation": "Fehler in Block {index}",
"error.blocks.validation": "Fehler im \"{field}\" Feld in Block {index} mit dem Block Typ \"{fieldset}\"",
"error.email.preset.notFound": "Die E-Mailvorlage \"{name}\" wurde nicht gefunden",
@@ -107,13 +107,15 @@
"error.language.name": "Bitte gib einen gültigen Namen für die Sprache an",
"error.language.notFound": "Die Sprache konnte nicht gefunden werden",
"error.layout.validation.block": "Fehler in Block {blockIndex} in Layout {layoutIndex}",
"error.layout.validation.block": "Fehler im \"{field}\" Feld in Block {blockIndex} mit dem Block Typ \"{fieldset}\" in Layout {layoutIndex}",
"error.layout.validation.settings": "Fehler in den Einstellungen von Layout {index}",
"error.license.format": "Bitte gib einen gültigen Lizenzschlüssel ein",
"error.license.email": "Bitte gib eine gültige E-Mailadresse an",
"error.license.verification": "Die Lizenz konnte nicht verifiziert werden",
"error.object.validation": "Fehler im \"{label}\" Feld:\n{message}",
"error.offline": "Das Panel ist zur Zeit offline",
"error.page.changeSlug.permission": "Du darfst die URL der Seite \"{slug}\" nicht ändern",
@@ -282,9 +284,13 @@
"field.layout.empty": "Keine Layouts",
"field.layout.select": "Layout auswählen",
"field.object.empty": "Noch keine Information",
"field.pages.empty": "Keine Seiten ausgewählt",
"field.structure.delete.confirm": "Willst du diesen Eintrag wirklich l\u00f6schen?",
"field.structure.empty": "Es bestehen keine Eintr\u00e4ge.",
"field.users.empty": "Keine Accounts ausgewählt",
"file.blueprint": "Du kannst zusätzliche Felder und Bereiche für diese Datei in <strong>/site/blueprints/files/{blueprint}.yml</strong> anlegen",
@@ -448,6 +454,7 @@
"paste": "Einfügen",
"paste.after": "Danach einfügen",
"pixel": "Pixel",
"plugin": "Plugin",
"plugins": "Plugins",
"prev": "Vorheriger Eintrag",
"preview": "Vorschau",
@@ -487,11 +494,24 @@
"stats.empty": "Keine Daten",
"system.issues.content": "Der content Ordner scheint öffentlich zugänglich zu sein",
"system.issues.eol.kirby": "Deine Kirby Installation ist veraltet und erhält keine weiteren Sicherheitsupdates",
"system.issues.eol.plugin": "Deine Version des { plugin } Plugins ist veraltet und erhält keine weiteren Sicherheitsupdates",
"system.issues.debug": "Debugging muss im öffentlichen Betrieb ausgeschaltet sein",
"system.issues.git": "Der .git Ordner scheint öffentlich zugänglich zu sein",
"system.issues.https": "Wir empfehlen HTTPS für alle deine Seiten",
"system.issues.kirby": "Der kirby Ordner scheint öffentlich zugänglich zu sein",
"system.issues.site": "Der site Ordner scheint öffentlich zugänglich zu sein",
"system.issues.vulnerability.kirby": "Deine Installation könnte von folgender Sicherheitslücke betroffen sein ({ severity } severity): { description }",
"system.issues.vulnerability.plugin": "Deine Installation könnte von folgender Sicherheitslücke im { plugin } Plugin betroffen sein ({ severity } severity): { description }",
"system.updateStatus": "Update Status",
"system.updateStatus.error": "Update Check nicht möglich",
"system.updateStatus.not-vulnerable": "Keine bekannten Sicherheitslücken",
"system.updateStatus.security-update": "Kostenloses Sicherheitsupdate { version } verfügbar",
"system.updateStatus.security-upgrade": "Upgrade { version } mit Sicherheitsverbesserungen verfügbar ",
"system.updateStatus.unreleased": "Unveröffentlichte Version",
"system.updateStatus.up-to-date": "Aktuell",
"system.updateStatus.update": "Kostenloses Update { version } verfügbar",
"system.updateStatus.upgrade": "Upgrade { version } verfügbar",
"title": "Titel",
"template": "Vorlage",
@@ -558,6 +578,9 @@
"users": "Accounts",
"version": "Version",
"version.current": "Aktuelle Version",
"version.latest": "Neueste Version",
"versionInformation": "Informationen zur Version",
"view.account": "Dein Account",
"view.installation": "Installation",
+25 -2
View File
@@ -70,7 +70,7 @@
"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.validation": "There's an error on the \"{field}\" field in block {index} using the \"{fieldset}\" block type",
"error.email.preset.notFound": "Δεν είναι δυνατή η εύρεση της προεπιλογής διεύθινσης ηλεκτρονικού ταχυδρομείου \"{name}\"",
@@ -107,13 +107,15 @@
"error.language.name": "Please enter a valid name for the language",
"error.language.notFound": "The language could not be found",
"error.layout.validation.block": "There's an error in block {blockIndex} in layout {layoutIndex}",
"error.layout.validation.block": "There's an error on the \"{field}\" field in block {blockIndex} using the \"{fieldset}\" block type in layout {layoutIndex}",
"error.layout.validation.settings": "There's an error in layout {index} settings",
"error.license.format": "Please enter a valid license key",
"error.license.email": "Παρακαλώ εισάγετε μια έγκυρη διεύθυνση ηλεκτρονικού ταχυδρομείου",
"error.license.verification": "The license could not be verified",
"error.object.validation": "There’s an error in the \"{label}\" field:\n{message}",
"error.offline": "The Panel is currently offline",
"error.page.changeSlug.permission": "Δεν επιτρέπεται να αλλάξετε το URL της σελίδας \"{slug}\"",
@@ -282,9 +284,13 @@
"field.layout.empty": "No rows yet",
"field.layout.select": "Select a layout",
"field.object.empty": "No information yet",
"field.pages.empty": "Δεν έχουν επιλεγεί ακόμη σελίδες",
"field.structure.delete.confirm": "\u0395\u03af\u03c3\u03c4\u03b5 \u03c3\u03af\u03b3\u03bf\u03c5\u03c1\u03bf\u03c2 \u03cc\u03c4\u03b9 \u03b8\u03ad\u03bb\u03b5\u03c4\u03b5 \u03bd\u03b1 \u03b4\u03b9\u03b1\u03b3\u03c1\u03ac\u03c8\u03b5\u03c4\u03b5 \u03b1\u03c5\u03c4\u03ae\u03bd \u03c4\u03b7\u03bd \u03ba\u03b1\u03c4\u03b1\u03c7\u03ce\u03c1\u03b9\u03c3\u03b7;",
"field.structure.empty": "\u0394\u03b5\u03bd \u03c5\u03c0\u03ac\u03c1\u03c7\u03bf\u03c5\u03bd \u03b1\u03ba\u03cc\u03bc\u03b7 \u03ba\u03b1\u03c4\u03b1\u03c7\u03c9\u03c1\u03af\u03c3\u03b5\u03b9\u03c2.",
"field.users.empty": "Δεν έχουν επιλεγεί ακόμη χρήστες",
"file.blueprint": "This file has no blueprint yet. You can define the setup in <strong>/site/blueprints/files/{blueprint}.yml</strong>",
@@ -448,6 +454,7 @@
"paste": "Paste",
"paste.after": "Paste after",
"pixel": "Εικονοστοιχέιο",
"plugin": "Plugin",
"plugins": "Plugins",
"prev": "Προηγούμενο",
"preview": "Preview",
@@ -487,11 +494,24 @@
"stats.empty": "No reports",
"system.issues.content": "The content folder seems to be exposed",
"system.issues.eol.kirby": "Your installed Kirby version has reached end-of-life and will not receive further security updates",
"system.issues.eol.plugin": "Your installed version of the { plugin } plugin is has reached end-of-life and will not receive further security updates",
"system.issues.debug": "Debugging must be turned off in production",
"system.issues.git": "The .git folder seems to be exposed",
"system.issues.https": "We recommend HTTPS for all your sites",
"system.issues.kirby": "The kirby folder seems to be exposed",
"system.issues.site": "The site folder seems to be exposed",
"system.issues.vulnerability.kirby": "Your installation might be affected by the following vulnerability ({ severity } severity): { description }",
"system.issues.vulnerability.plugin": "Your installation might be affected by the following vulnerability in the { plugin } plugin ({ severity } severity): { description }",
"system.updateStatus": "Update status",
"system.updateStatus.error": "Could not check for updates",
"system.updateStatus.not-vulnerable": "No known vulnerabilities",
"system.updateStatus.security-update": "Free security update { version } available",
"system.updateStatus.security-upgrade": "Upgrade { version } with security fixes available",
"system.updateStatus.unreleased": "Unreleased version",
"system.updateStatus.up-to-date": "Up to date",
"system.updateStatus.update": "Free update { version } available",
"system.updateStatus.upgrade": "Upgrade { version } available",
"title": "Τίτλος",
"template": "\u03a0\u03c1\u03cc\u03c4\u03c5\u03c0\u03bf",
@@ -558,6 +578,9 @@
"users": "Χρήστες",
"version": "\u0388\u03ba\u03b4\u03bf\u03c3\u03b7 Kirby",
"version.current": "Current version",
"version.latest": "Latest version",
"versionInformation": "Version information",
"view.account": "\u039f \u03bb\u03bf\u03b3\u03b1\u03c1\u03b9\u03b1\u03c3\u03bc\u03cc\u03c2 \u03c3\u03b1\u03c2",
"view.installation": "\u0395\u03b3\u03ba\u03b1\u03c4\u03ac\u03c3\u03c4\u03b1\u03c3\u03b7",
+25 -2
View File
@@ -70,7 +70,7 @@
"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.validation": "There's an error on the \"{field}\" field in block {index} using the \"{fieldset}\" block type",
"error.email.preset.notFound": "The email preset \"{name}\" cannot be found",
@@ -107,13 +107,15 @@
"error.language.name": "Please enter a valid name for the language",
"error.language.notFound": "The language could not be found",
"error.layout.validation.block": "There's an error in block {blockIndex} in layout {layoutIndex}",
"error.layout.validation.block": "There's an error on the \"{field}\" field in block {blockIndex} using the \"{fieldset}\" block type in layout {layoutIndex}",
"error.layout.validation.settings": "There's an error in layout {index} settings",
"error.license.format": "Please enter a valid license key",
"error.license.email": "Please enter a valid email address",
"error.license.verification": "The license could not be verified",
"error.object.validation": "There’s an error in the \"{label}\" field:\n{message}",
"error.offline": "The Panel is currently offline",
"error.page.changeSlug.permission": "You are not allowed to change the URL appendix for \"{slug}\"",
@@ -282,9 +284,13 @@
"field.layout.empty": "No rows yet",
"field.layout.select": "Select a layout",
"field.object.empty": "No information yet",
"field.pages.empty": "No pages selected yet",
"field.structure.delete.confirm": "Do you really want to delete this row?",
"field.structure.empty": "No entries yet",
"field.users.empty": "No users selected yet",
"file.blueprint": "This file has no blueprint yet. You can define the setup in <strong>/site/blueprints/files/{blueprint}.yml</strong>",
@@ -448,6 +454,7 @@
"paste": "Paste",
"paste.after": "Paste after",
"pixel": "Pixel",
"plugin": "Plugin",
"plugins": "Plugins",
"prev": "Previous",
"preview": "Preview",
@@ -487,11 +494,24 @@
"stats.empty": "No reports",
"system.issues.content": "The content folder seems to be exposed",
"system.issues.eol.kirby": "Your installed Kirby version has reached end-of-life and will not receive further security updates",
"system.issues.eol.plugin": "Your installed version of the { plugin } plugin is has reached end-of-life and will not receive further security updates",
"system.issues.debug": "Debugging must be turned off in production",
"system.issues.git": "The .git folder seems to be exposed",
"system.issues.https": "We recommend HTTPS for all your sites",
"system.issues.kirby": "The kirby folder seems to be exposed",
"system.issues.site": "The site folder seems to be exposed",
"system.issues.vulnerability.kirby": "Your installation might be affected by the following vulnerability ({ severity } severity): { description }",
"system.issues.vulnerability.plugin": "Your installation might be affected by the following vulnerability in the { plugin } plugin ({ severity } severity): { description }",
"system.updateStatus": "Update status",
"system.updateStatus.error": "Could not check for updates",
"system.updateStatus.not-vulnerable": "No known vulnerabilities",
"system.updateStatus.security-update": "Free security update { version } available",
"system.updateStatus.security-upgrade": "Upgrade { version } with security fixes available",
"system.updateStatus.unreleased": "Unreleased version",
"system.updateStatus.up-to-date": "Up to date",
"system.updateStatus.update": "Free update { version } available",
"system.updateStatus.upgrade": "Upgrade { version } available",
"title": "Title",
"template": "Template",
@@ -558,6 +578,9 @@
"users": "Users",
"version": "Version",
"version.current": "Current version",
"version.latest": "Latest version",
"versionInformation": "Version information",
"view.account": "Your account",
"view.installation": "Installation",
+26 -3
View File
@@ -70,7 +70,7 @@
"error.blocks.max.singular": "Vi devas ne aldoni pli ol unu bloko",
"error.blocks.min.plural": "Oni devas aldoni almenaŭ {min} blokojn",
"error.blocks.min.singular": "Oni devas aldoni almenaŭ unu blokon",
"error.blocks.validation": "Estas eraro en bloko {index}",
"error.blocks.validation": "There's an error on the \"{field}\" field in block {index} using the \"{fieldset}\" block type",
"error.email.preset.notFound": "La retpoŝta antaŭagordo \"{name}\" ne estas trovebla",
@@ -107,13 +107,15 @@
"error.language.name": "Bonvolu entajpi validan nomon por la lingvo",
"error.language.notFound": "La lingvo ne troveblas",
"error.layout.validation.block": "Estas eraro en bloko {blockIndex}, en blokaranĝo {layoutIndex}",
"error.layout.validation.block": "There's an error on the \"{field}\" field in block {blockIndex} using the \"{fieldset}\" block type in layout {layoutIndex}",
"error.layout.validation.settings": "Estas eraro en la agordoj de blokaranĝo {index}",
"error.license.format": "Bonvolu entajpi validan kodon de permisilo",
"error.license.email": "Bonvolu entajpi validan retpoŝtadreson",
"error.license.verification": "Ne eblis kontroli la permisilon",
"error.object.validation": "There’s an error in the \"{label}\" field:\n{message}",
"error.offline": "La panelo estas ĉi-momente nekonektita",
"error.page.changeSlug.permission": "Vi ne rajtas ŝanĝi la URL-nomon de \"{slug}\"",
@@ -282,9 +284,13 @@
"field.layout.empty": "Ankoraŭ neniu vico",
"field.layout.select": "Elekti blokaranĝon",
"field.object.empty": "No information yet",
"field.pages.empty": "Ankoraŭ neniu paĝo elektita",
"field.structure.delete.confirm": "Ĉu vi certe volas forigi ĉi tiun vicon?",
"field.structure.empty": "Ankoraŭ neniu enigo",
"field.users.empty": "Ankoraŭ neniu uzanto elektita",
"file.blueprint": "Ĉi tiu dosiero ankoraŭ havas neniun planon. Vi povas difini planon ĉe <strong>/site/blueprints/files/{blueprint}.yml</strong>",
@@ -360,7 +366,7 @@
"lock.unlock": "Malŝlosi",
"lock.isUnlocked": "Viaj nekonservitaj ŝanĝoj estas ŝanĝitaj de alia uzanto. Vi povas elŝuti dosieron kun viaj ŝanĝoj por permane kunfandi ilin.",
"login": "Ensaluti",
"login": "Log in",
"login.code.label.login": "Ensaluta kodo",
"login.code.label.password-reset": "Kodo por restarigi pasvorton",
"login.code.placeholder.email": "000 000",
@@ -448,6 +454,7 @@
"paste": "Alglui",
"paste.after": "Alglui post",
"pixel": "Pikselo",
"plugin": "Plugin",
"plugins": "Kromprogramoj",
"prev": "Antaŭe",
"preview": "Antaŭrigardi",
@@ -487,11 +494,24 @@
"stats.empty": "No reports",
"system.issues.content": "The content folder seems to be exposed",
"system.issues.eol.kirby": "Your installed Kirby version has reached end-of-life and will not receive further security updates",
"system.issues.eol.plugin": "Your installed version of the { plugin } plugin is has reached end-of-life and will not receive further security updates",
"system.issues.debug": "Debugging must be turned off in production",
"system.issues.git": "The .git folder seems to be exposed",
"system.issues.https": "We recommend HTTPS for all your sites",
"system.issues.kirby": "The kirby folder seems to be exposed",
"system.issues.site": "The site folder seems to be exposed",
"system.issues.vulnerability.kirby": "Your installation might be affected by the following vulnerability ({ severity } severity): { description }",
"system.issues.vulnerability.plugin": "Your installation might be affected by the following vulnerability in the { plugin } plugin ({ severity } severity): { description }",
"system.updateStatus": "Update status",
"system.updateStatus.error": "Could not check for updates",
"system.updateStatus.not-vulnerable": "No known vulnerabilities",
"system.updateStatus.security-update": "Free security update { version } available",
"system.updateStatus.security-upgrade": "Upgrade { version } with security fixes available",
"system.updateStatus.unreleased": "Unreleased version",
"system.updateStatus.up-to-date": "Up to date",
"system.updateStatus.update": "Free update { version } available",
"system.updateStatus.upgrade": "Upgrade { version } available",
"title": "Titolo",
"template": "Ŝablono",
@@ -558,6 +578,9 @@
"users": "Uzantoj",
"version": "Versio",
"version.current": "Current version",
"version.latest": "Latest version",
"versionInformation": "Version information",
"view.account": "Via konto",
"view.installation": "Instalado",
+25 -2
View File
@@ -70,7 +70,7 @@
"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.blocks.validation": "There's an error on the \"{field}\" field in block {index} using the \"{fieldset}\" block type",
"error.email.preset.notFound": "El preajuste de email \"{name}\" no se pudo encontrar.",
@@ -107,13 +107,15 @@
"error.language.name": "Por favor introduce un nombre válido para el idioma",
"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.block": "There's an error on the \"{field}\" field in block {blockIndex} using the \"{fieldset}\" block type in layout {layoutIndex}",
"error.layout.validation.settings": "There's an error in layout {index} settings",
"error.license.format": "Por favor introduce una llave de licencia válida",
"error.license.email": "Por favor ingresa un correo electrónico valido",
"error.license.verification": "La licencia no pude ser verificada",
"error.object.validation": "There’s an error in the \"{label}\" field:\n{message}",
"error.offline": "El Panel se encuentra fuera de linea ",
"error.page.changeSlug.permission": "No está permitido cambiar el apéndice de URL para \"{slug}\".",
@@ -282,9 +284,13 @@
"field.layout.empty": "No rows yet",
"field.layout.select": "Select a layout",
"field.object.empty": "No information yet",
"field.pages.empty": "Aún no ha seleccionado ningúna pagina",
"field.structure.delete.confirm": "\u00bfEn realidad desea borrar esta entrada?",
"field.structure.empty": "A\u00fan no existen entradas.",
"field.users.empty": "Aún no ha seleccionado ningún usuario",
"file.blueprint": "This file has no blueprint yet. You can define the setup in <strong>/site/blueprints/files/{blueprint}.yml</strong>",
@@ -448,6 +454,7 @@
"paste": "Paste",
"paste.after": "Paste after",
"pixel": "Pixel",
"plugin": "Plugin",
"plugins": "Plugins",
"prev": "Anterior",
"preview": "Preview",
@@ -487,11 +494,24 @@
"stats.empty": "No reports",
"system.issues.content": "The content folder seems to be exposed",
"system.issues.eol.kirby": "Your installed Kirby version has reached end-of-life and will not receive further security updates",
"system.issues.eol.plugin": "Your installed version of the { plugin } plugin is has reached end-of-life and will not receive further security updates",
"system.issues.debug": "Debugging must be turned off in production",
"system.issues.git": "The .git folder seems to be exposed",
"system.issues.https": "We recommend HTTPS for all your sites",
"system.issues.kirby": "The kirby folder seems to be exposed",
"system.issues.site": "The site folder seems to be exposed",
"system.issues.vulnerability.kirby": "Your installation might be affected by the following vulnerability ({ severity } severity): { description }",
"system.issues.vulnerability.plugin": "Your installation might be affected by the following vulnerability in the { plugin } plugin ({ severity } severity): { description }",
"system.updateStatus": "Update status",
"system.updateStatus.error": "Could not check for updates",
"system.updateStatus.not-vulnerable": "No known vulnerabilities",
"system.updateStatus.security-update": "Free security update { version } available",
"system.updateStatus.security-upgrade": "Upgrade { version } with security fixes available",
"system.updateStatus.unreleased": "Unreleased version",
"system.updateStatus.up-to-date": "Up to date",
"system.updateStatus.update": "Free update { version } available",
"system.updateStatus.upgrade": "Upgrade { version } available",
"title": "Título",
"template": "Plantilla",
@@ -558,6 +578,9 @@
"users": "Usuarios",
"version": "Versión",
"version.current": "Current version",
"version.latest": "Latest version",
"versionInformation": "Version information",
"view.account": "Tu cuenta",
"view.installation": "Instalaci\u00f3n",
+25 -2
View File
@@ -70,7 +70,7 @@
"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.blocks.validation": "There's an error on the \"{field}\" field in block {index} using the \"{fieldset}\" block type",
"error.email.preset.notFound": "El preset del correo \"{name}\" no pudo ser encontrado",
@@ -107,13 +107,15 @@
"error.language.name": "Por favor introduce un nombre válido para el idioma",
"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.block": "There's an error on the \"{field}\" field in block {blockIndex} using the \"{fieldset}\" block type in layout {layoutIndex}",
"error.layout.validation.settings": "There's an error in layout {index} settings",
"error.license.format": "Por favor introduce una llave de licencia válida",
"error.license.email": "Por favor, introduce un correo electrónico válido",
"error.license.verification": "La licencia no pude ser verificada",
"error.object.validation": "There’s an error in the \"{label}\" field:\n{message}",
"error.offline": "El Panel se encuentra fuera de linea ",
"error.page.changeSlug.permission": "No está permitido cambiar el apéndice de URL para \"{slug}\"",
@@ -282,9 +284,13 @@
"field.layout.empty": "No rows yet",
"field.layout.select": "Select a layout",
"field.object.empty": "No information yet",
"field.pages.empty": "Aún no hay páginas seleccionadas",
"field.structure.delete.confirm": "¿Realmente quieres eliminar esta fila?",
"field.structure.empty": "Aún no hay entradas",
"field.users.empty": "Aún no hay usuarios seleccionados",
"file.blueprint": "This file has no blueprint yet. You can define the setup in <strong>/site/blueprints/files/{blueprint}.yml</strong>",
@@ -448,6 +454,7 @@
"paste": "Paste",
"paste.after": "Paste after",
"pixel": "Pixel",
"plugin": "Plugin",
"plugins": "Plugins",
"prev": "Anterior",
"preview": "Preview",
@@ -487,11 +494,24 @@
"stats.empty": "No reports",
"system.issues.content": "The content folder seems to be exposed",
"system.issues.eol.kirby": "Your installed Kirby version has reached end-of-life and will not receive further security updates",
"system.issues.eol.plugin": "Your installed version of the { plugin } plugin is has reached end-of-life and will not receive further security updates",
"system.issues.debug": "Debugging must be turned off in production",
"system.issues.git": "The .git folder seems to be exposed",
"system.issues.https": "We recommend HTTPS for all your sites",
"system.issues.kirby": "The kirby folder seems to be exposed",
"system.issues.site": "The site folder seems to be exposed",
"system.issues.vulnerability.kirby": "Your installation might be affected by the following vulnerability ({ severity } severity): { description }",
"system.issues.vulnerability.plugin": "Your installation might be affected by the following vulnerability in the { plugin } plugin ({ severity } severity): { description }",
"system.updateStatus": "Update status",
"system.updateStatus.error": "Could not check for updates",
"system.updateStatus.not-vulnerable": "No known vulnerabilities",
"system.updateStatus.security-update": "Free security update { version } available",
"system.updateStatus.security-upgrade": "Upgrade { version } with security fixes available",
"system.updateStatus.unreleased": "Unreleased version",
"system.updateStatus.up-to-date": "Up to date",
"system.updateStatus.update": "Free update { version } available",
"system.updateStatus.upgrade": "Upgrade { version } available",
"title": "Titulo",
"template": "Plantilla",
@@ -558,6 +578,9 @@
"users": "Usuarios",
"version": "Versión",
"version.current": "Current version",
"version.latest": "Latest version",
"versionInformation": "Version information",
"view.account": "Su cuenta",
"view.installation": "Instalación",
+25 -2
View File
@@ -70,7 +70,7 @@
"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.validation": "There's an error on the \"{field}\" field in block {index} using the \"{fieldset}\" block type",
"error.email.preset.notFound": "قالب ایمیل «{name}» پیدا نشد",
@@ -107,13 +107,15 @@
"error.language.name": "Please enter a valid name for the language",
"error.language.notFound": "The language could not be found",
"error.layout.validation.block": "There's an error in block {blockIndex} in layout {layoutIndex}",
"error.layout.validation.block": "There's an error on the \"{field}\" field in block {blockIndex} using the \"{fieldset}\" block type in layout {layoutIndex}",
"error.layout.validation.settings": "There's an error in layout {index} settings",
"error.license.format": "Please enter a valid license key",
"error.license.email": "لطفا ایمیل صحیحی وارد کنید",
"error.license.verification": "The license could not be verified",
"error.object.validation": "There’s an error in the \"{label}\" field:\n{message}",
"error.offline": "The Panel is currently offline",
"error.page.changeSlug.permission": "شما امکان تغییر پسوند Url صفحه «{slug}» را ندارید",
@@ -282,9 +284,13 @@
"field.layout.empty": "No rows yet",
"field.layout.select": "Select a layout",
"field.object.empty": "No information yet",
"field.pages.empty": "صفحه‌ای انتخاب نشده است",
"field.structure.delete.confirm": "\u0645\u062f\u062e\u0644 \u062c\u0627\u0631\u06cc \u062d\u0630\u0641 \u0634\u0648\u062f\u061f",
"field.structure.empty": "\u0645\u0648\u0631\u062f\u06cc \u0648\u062c\u0648\u062f \u0646\u062f\u0627\u0631\u062f.",
"field.users.empty": "کاربری انتخاب نشده است",
"file.blueprint": "This file has no blueprint yet. You can define the setup in <strong>/site/blueprints/files/{blueprint}.yml</strong>",
@@ -448,6 +454,7 @@
"paste": "Paste",
"paste.after": "Paste after",
"pixel": "پیکسل",
"plugin": "Plugin",
"plugins": "Plugins",
"prev": "قبلی",
"preview": "Preview",
@@ -487,11 +494,24 @@
"stats.empty": "No reports",
"system.issues.content": "The content folder seems to be exposed",
"system.issues.eol.kirby": "Your installed Kirby version has reached end-of-life and will not receive further security updates",
"system.issues.eol.plugin": "Your installed version of the { plugin } plugin is has reached end-of-life and will not receive further security updates",
"system.issues.debug": "Debugging must be turned off in production",
"system.issues.git": "The .git folder seems to be exposed",
"system.issues.https": "We recommend HTTPS for all your sites",
"system.issues.kirby": "The kirby folder seems to be exposed",
"system.issues.site": "The site folder seems to be exposed",
"system.issues.vulnerability.kirby": "Your installation might be affected by the following vulnerability ({ severity } severity): { description }",
"system.issues.vulnerability.plugin": "Your installation might be affected by the following vulnerability in the { plugin } plugin ({ severity } severity): { description }",
"system.updateStatus": "Update status",
"system.updateStatus.error": "Could not check for updates",
"system.updateStatus.not-vulnerable": "No known vulnerabilities",
"system.updateStatus.security-update": "Free security update { version } available",
"system.updateStatus.security-upgrade": "Upgrade { version } with security fixes available",
"system.updateStatus.unreleased": "Unreleased version",
"system.updateStatus.up-to-date": "Up to date",
"system.updateStatus.update": "Free update { version } available",
"system.updateStatus.upgrade": "Upgrade { version } available",
"title": "عنوان",
"template": "\u0642\u0627\u0644\u0628 \u0635\u0641\u062d\u0647",
@@ -558,6 +578,9 @@
"users": "کاربران",
"version": "\u0646\u0633\u062e\u0647 \u0646\u0631\u0645 \u0627\u0641\u0632\u0627\u0631",
"version.current": "Current version",
"version.latest": "Latest version",
"versionInformation": "Version information",
"view.account": "حساب کاربری شما",
"view.installation": "\u0646\u0635\u0628 \u0648 \u0631\u0627\u0647 \u0627\u0646\u062f\u0627\u0632\u06cc",
+25 -2
View File
@@ -70,7 +70,7 @@
"error.blocks.max.singular": "Voit lisätä enintään yhden lohkon",
"error.blocks.min.plural": "Lisää vähintään {min} lohkoa",
"error.blocks.min.singular": "Lisää vähintään yksi lohko",
"error.blocks.validation": "Virhe lohkossa {index}",
"error.blocks.validation": "There's an error on the \"{field}\" field in block {index} using the \"{fieldset}\" block type",
"error.email.preset.notFound": "Nimellä \"{name}\" ja kyseisellä verkkotunnuksella ei löydy sähköpostiosoitetta",
@@ -107,13 +107,15 @@
"error.language.name": "Anna kielen nimi",
"error.language.notFound": "Kieltä ei löytynyt",
"error.layout.validation.block": "Lohkon {blockIndex} asetelmassa {layoutIndex} tapahtui virhe",
"error.layout.validation.block": "There's an error on the \"{field}\" field in block {blockIndex} using the \"{fieldset}\" block type in layout {layoutIndex}",
"error.layout.validation.settings": "Virhe asetelman {index} asetuksissa",
"error.license.format": "Anna lisenssiavain",
"error.license.email": "Anna sähköpostiosoite",
"error.license.verification": "Lisenssiä ei voitu vahvistaa",
"error.object.validation": "There’s an error in the \"{label}\" field:\n{message}",
"error.offline": "Paneeli on offline-tilassa",
"error.page.changeSlug.permission": "Sinulla ei ole oikeutta muuttaa URL-liitettä sivulle \"{slug}\"",
@@ -282,9 +284,13 @@
"field.layout.empty": "Ei rivejä",
"field.layout.select": "Valitse asettelu",
"field.object.empty": "No information yet",
"field.pages.empty": " Sivuja ei ole vielä valittu",
"field.structure.delete.confirm": "Haluatko varmasti poistaa tämän rivin?",
"field.structure.empty": "Rivejä ei ole vielä lisätty",
"field.users.empty": "Käyttäjiä ei ole vielä valittu",
"file.blueprint": "Tällä tiedostolla ei ole vielä suunnitelmaa. Voit määrittää suunnitelman tiedostoon <strong>/site/blueprints/files/{blueprint}.yml</strong>",
@@ -448,6 +454,7 @@
"paste": "Liitä",
"paste.after": "Liitä jälkeen",
"pixel": "Pikseli",
"plugin": "Plugin",
"plugins": "Liitännäiset",
"prev": "Edellinen",
"preview": "Esikatselu",
@@ -487,11 +494,24 @@
"stats.empty": "No reports",
"system.issues.content": "The content folder seems to be exposed",
"system.issues.eol.kirby": "Your installed Kirby version has reached end-of-life and will not receive further security updates",
"system.issues.eol.plugin": "Your installed version of the { plugin } plugin is has reached end-of-life and will not receive further security updates",
"system.issues.debug": "Debugging must be turned off in production",
"system.issues.git": "The .git folder seems to be exposed",
"system.issues.https": "We recommend HTTPS for all your sites",
"system.issues.kirby": "The kirby folder seems to be exposed",
"system.issues.site": "The site folder seems to be exposed",
"system.issues.vulnerability.kirby": "Your installation might be affected by the following vulnerability ({ severity } severity): { description }",
"system.issues.vulnerability.plugin": "Your installation might be affected by the following vulnerability in the { plugin } plugin ({ severity } severity): { description }",
"system.updateStatus": "Update status",
"system.updateStatus.error": "Could not check for updates",
"system.updateStatus.not-vulnerable": "No known vulnerabilities",
"system.updateStatus.security-update": "Free security update { version } available",
"system.updateStatus.security-upgrade": "Upgrade { version } with security fixes available",
"system.updateStatus.unreleased": "Unreleased version",
"system.updateStatus.up-to-date": "Up to date",
"system.updateStatus.update": "Free update { version } available",
"system.updateStatus.upgrade": "Upgrade { version } available",
"title": "Nimi",
"template": "Sivupohja",
@@ -558,6 +578,9 @@
"users": "Käyttäjät",
"version": "Versio",
"version.current": "Current version",
"version.latest": "Latest version",
"versionInformation": "Version information",
"view.account": "Oma käyttäjätili",
"view.installation": "Asennus",
+25 -2
View File
@@ -70,7 +70,7 @@
"error.blocks.max.singular": "Vous ne devez pas ajouter plus d'un bloc",
"error.blocks.min.plural": "Vous devez ajouter au moins {min} blocs",
"error.blocks.min.singular": "Vous devez ajouter au moins un bloc",
"error.blocks.validation": "Il y a une erreur dans le bloc {index}",
"error.blocks.validation": "Il y a une erreur sur le champ \"{field}\" du bloc {index} utilisant le type de bloc \"{fieldset}\"",
"error.email.preset.notFound": "La configuration de courriel « {name} » n’a pu être trouvé ",
@@ -107,13 +107,15 @@
"error.language.name": "Veuillez saisir un nom valide pour cette langue",
"error.language.notFound": "La langue n’a pu être trouvée",
"error.layout.validation.block": "Il y a une erreur dans le block {blockIndex} de la disposition {layoutIndex}",
"error.layout.validation.block": "Il y a une erreur sur le champ \"{field}\" du bloc {blockIndex} utilisant le type de bloc \"{fieldset}\" dans le layout {layoutIndex}.",
"error.layout.validation.settings": "Il y a une erreur dans les paramètres de la disposition {index}",
"error.license.format": "Veuillez saisir un numéro de licence valide",
"error.license.email": "Veuillez saisir un courriel valide",
"error.license.verification": "La licence n’a pu être vérifiée",
"error.object.validation": "Il y a une erreur dans le champ \"{label}\" :\n{message}",
"error.offline": "Le Panel est actuellement hors ligne",
"error.page.changeSlug.permission": "Vous n’êtes pas autorisé à modifier l’identifiant d’URL pour « {slug} »",
@@ -282,9 +284,13 @@
"field.layout.empty": "Pas encore de rangées",
"field.layout.select": "Choisir une disposition",
"field.object.empty": "Pas encore d‘information",
"field.pages.empty": "Pas encore de page sélectionnée",
"field.structure.delete.confirm": "Voulez-vous vraiment supprimer cette ligne ?",
"field.structure.empty": "Pas encore d’entrée",
"field.users.empty": "Pas encore d’utilisateur sélectionné",
"file.blueprint": "Ce fichier n’a pas encore de blueprint. Vous pouvez en définir les paramètres dans <strong>/site/blueprints/files/{blueprint}.yml</strong>",
@@ -448,6 +454,7 @@
"paste": "Coller",
"paste.after": "Coller après",
"pixel": "Pixel",
"plugin": "Plugin",
"plugins": "Plugins",
"prev": "Précédent",
"preview": "Prévisualiser",
@@ -487,11 +494,24 @@
"stats.empty": "Aucun rapport",
"system.issues.content": "Le dossier content semble exposé",
"system.issues.eol.kirby": "La version de Kirby installée a atteint la fin de son cycle de vie et ne recevra plus de mises à jour de sécurité",
"system.issues.eol.plugin": "La version du plugin { plugin } installée a atteint la fin de son cycle de vie et ne recevra plus de mises à jour de sécurité",
"system.issues.debug": "Le débogage doit être désactivé en production",
"system.issues.git": "Le dossier .git semble exposé",
"system.issues.https": "Nous recommandons HTTPS pour tous vos sites",
"system.issues.kirby": "Le dossier kirby semble exposé",
"system.issues.site": "Le dossier site semble exposé",
"system.issues.vulnerability.kirby": "Votre installation pourrait être affectée par la vulnérabilité suivante ({ severity } gravité) : { description }",
"system.issues.vulnerability.plugin": "Votre installation pourrait être affectée par la vulnérabilité suivante du plugin { plugin } ({ severity } gravité) : { description }",
"system.updateStatus": "Statut des mises à jour",
"system.updateStatus.error": "Les mises à jour n'ont pu être vérifiées",
"system.updateStatus.not-vulnerable": "Aucune vulnérabilité connue",
"system.updateStatus.security-update": "Mise à jour gratuite { version } disponible",
"system.updateStatus.security-upgrade": "Mise à jour { version } avec correctifs de sécurité disponible",
"system.updateStatus.unreleased": "Version non diffusée",
"system.updateStatus.up-to-date": "À jour",
"system.updateStatus.update": "Mise à jour gratuite { version } disponible",
"system.updateStatus.upgrade": "Mise à jour { version } disponible",
"title": "Titre",
"template": "Modèle",
@@ -558,6 +578,9 @@
"users": "Utilisateurs",
"version": "Version",
"version.current": "Version actuelle",
"version.latest": "Dernière version",
"versionInformation": "Informations de version",
"view.account": "Votre compte",
"view.installation": "Installation",
+25 -2
View File
@@ -70,7 +70,7 @@
"error.blocks.max.singular": "Csak egyetlen blokk adható hozzá",
"error.blocks.min.plural": "Legalább {min} blokkot hozzá kell adnod",
"error.blocks.min.singular": "Legalább egy blokkot hozzá kell adnod",
"error.blocks.validation": "Hiba van az alábbi blokkban: {index}",
"error.blocks.validation": "There's an error on the \"{field}\" field in block {index} using the \"{fieldset}\" block type",
"error.email.preset.notFound": "A \"{name}\" email-beállítás nem található",
@@ -107,13 +107,15 @@
"error.language.name": "Kérlek, add meg a nyelv érvényes nevét",
"error.language.notFound": "A nyelv nem található",
"error.layout.validation.block": "Hibát találtunk az alábbi blokkban: {blockIndex} az alábbi elrendezésben: {layoutIndex}",
"error.layout.validation.block": "There's an error on the \"{field}\" field in block {blockIndex} using the \"{fieldset}\" block type in layout {layoutIndex}",
"error.layout.validation.settings": "Hibát találtunk a(z) {index} elrendezés beállításaiban",
"error.license.format": "Kérlek, add meg az évényes lincensz kulcsot",
"error.license.email": "Kérlek adj meg egy valós email-címet",
"error.license.verification": "A licensz nem ellenőrizhető",
"error.object.validation": "There’s an error in the \"{label}\" field:\n{message}",
"error.offline": "A Panel jelenleg nem elérhető",
"error.page.changeSlug.permission": "Nem változtathatod meg az URL-előtagot: \"{slug}\"",
@@ -282,9 +284,13 @@
"field.layout.empty": "Még nincsenek sorok",
"field.layout.select": "Válassz elrendezést",
"field.object.empty": "No information yet",
"field.pages.empty": "Nincs oldal kiválasztva",
"field.structure.delete.confirm": "Biztos t\u00f6r\u00f6lni szeretn\u00e9d ezt a bejegyz\u00e9st?",
"field.structure.empty": "Nincs m\u00e9g bejegyz\u00e9s",
"field.users.empty": "Nincs felhasználó kiválasztva",
"file.blueprint": "Ehhez a fájlhoz még nem tartozik oldalsablon. Itt hozhatod létre: <strong>/site/blueprints/files/{blueprint}.yml</strong>",
@@ -448,6 +454,7 @@
"paste": "Beillesztés",
"paste.after": "Beillesztés utána",
"pixel": "Pixel",
"plugin": "Plugin",
"plugins": "Pluginek",
"prev": "Előző",
"preview": "Előnézet",
@@ -487,11 +494,24 @@
"stats.empty": "No reports",
"system.issues.content": "The content folder seems to be exposed",
"system.issues.eol.kirby": "Your installed Kirby version has reached end-of-life and will not receive further security updates",
"system.issues.eol.plugin": "Your installed version of the { plugin } plugin is has reached end-of-life and will not receive further security updates",
"system.issues.debug": "Debugging must be turned off in production",
"system.issues.git": "The .git folder seems to be exposed",
"system.issues.https": "We recommend HTTPS for all your sites",
"system.issues.kirby": "The kirby folder seems to be exposed",
"system.issues.site": "The site folder seems to be exposed",
"system.issues.vulnerability.kirby": "Your installation might be affected by the following vulnerability ({ severity } severity): { description }",
"system.issues.vulnerability.plugin": "Your installation might be affected by the following vulnerability in the { plugin } plugin ({ severity } severity): { description }",
"system.updateStatus": "Update status",
"system.updateStatus.error": "Could not check for updates",
"system.updateStatus.not-vulnerable": "No known vulnerabilities",
"system.updateStatus.security-update": "Free security update { version } available",
"system.updateStatus.security-upgrade": "Upgrade { version } with security fixes available",
"system.updateStatus.unreleased": "Unreleased version",
"system.updateStatus.up-to-date": "Up to date",
"system.updateStatus.update": "Free update { version } available",
"system.updateStatus.upgrade": "Upgrade { version } available",
"title": "Cím",
"template": "Sablon",
@@ -558,6 +578,9 @@
"users": "Felhasználók",
"version": "Kirby verzi\u00f3",
"version.current": "Current version",
"version.latest": "Latest version",
"versionInformation": "Version information",
"view.account": "Fi\u00f3kod",
"view.installation": "Telep\u00edt\u00e9s",
+25 -2
View File
@@ -70,7 +70,7 @@
"error.blocks.max.singular": "Anda tidak boleh menambahkan lebih dari satu blok",
"error.blocks.min.plural": "Anda setidaknya menambahkan {min} blok",
"error.blocks.min.singular": "Anda setidaknya menambahkan satu blok",
"error.blocks.validation": "Ada kesalahan di blok {index}",
"error.blocks.validation": "There's an error on the \"{field}\" field in block {index} using the \"{fieldset}\" block type",
"error.email.preset.notFound": "Surel \"{name}\" tidak dapat ditemukan",
@@ -107,13 +107,15 @@
"error.language.name": "Masukkan nama bahasa yang valid",
"error.language.notFound": "The language could not be found",
"error.layout.validation.block": "Ada kesalahan di blok {blockIndex} di tata letak {layoutIndex}",
"error.layout.validation.block": "There's an error on the \"{field}\" field in block {blockIndex} using the \"{fieldset}\" block type in layout {layoutIndex}",
"error.layout.validation.settings": "Ada kesalahan di pengaturan tata letak {index}",
"error.license.format": "Masukkan kode lisensi yang valid",
"error.license.email": "Masukkan surel yang valid",
"error.license.verification": "Lisensi tidak dapat diverifikasi",
"error.object.validation": "There’s an error in the \"{label}\" field:\n{message}",
"error.offline": "The Panel is currently offline",
"error.page.changeSlug.permission": "Anda tidak diizinkan mengubah akhiran URL untuk \"{slug}\"",
@@ -282,9 +284,13 @@
"field.layout.empty": "Belum ada baris",
"field.layout.select": "Pilih tata letak",
"field.object.empty": "No information yet",
"field.pages.empty": "Belum ada halaman yang dipilih",
"field.structure.delete.confirm": "Anda yakin menghapus baris ini?",
"field.structure.empty": "Belum ada entri",
"field.users.empty": "Belum ada pengguna yang dipilih",
"file.blueprint": "This file has no blueprint yet. You can define the setup in <strong>/site/blueprints/files/{blueprint}.yml</strong>",
@@ -448,6 +454,7 @@
"paste": "Paste",
"paste.after": "Paste after",
"pixel": "Piksel",
"plugin": "Plugin",
"plugins": "Plugins",
"prev": "Sebelumnya",
"preview": "Pratinjau",
@@ -487,11 +494,24 @@
"stats.empty": "No reports",
"system.issues.content": "The content folder seems to be exposed",
"system.issues.eol.kirby": "Your installed Kirby version has reached end-of-life and will not receive further security updates",
"system.issues.eol.plugin": "Your installed version of the { plugin } plugin is has reached end-of-life and will not receive further security updates",
"system.issues.debug": "Debugging must be turned off in production",
"system.issues.git": "The .git folder seems to be exposed",
"system.issues.https": "We recommend HTTPS for all your sites",
"system.issues.kirby": "The kirby folder seems to be exposed",
"system.issues.site": "The site folder seems to be exposed",
"system.issues.vulnerability.kirby": "Your installation might be affected by the following vulnerability ({ severity } severity): { description }",
"system.issues.vulnerability.plugin": "Your installation might be affected by the following vulnerability in the { plugin } plugin ({ severity } severity): { description }",
"system.updateStatus": "Update status",
"system.updateStatus.error": "Could not check for updates",
"system.updateStatus.not-vulnerable": "No known vulnerabilities",
"system.updateStatus.security-update": "Free security update { version } available",
"system.updateStatus.security-upgrade": "Upgrade { version } with security fixes available",
"system.updateStatus.unreleased": "Unreleased version",
"system.updateStatus.up-to-date": "Up to date",
"system.updateStatus.update": "Free update { version } available",
"system.updateStatus.upgrade": "Upgrade { version } available",
"title": "Judul",
"template": "Templat",
@@ -558,6 +578,9 @@
"users": "Pengguna",
"version": "Versi",
"version.current": "Current version",
"version.latest": "Latest version",
"versionInformation": "Version information",
"view.account": "Akun Anda",
"view.installation": "Pemasangan",
+26 -3
View File
@@ -70,7 +70,7 @@
"error.blocks.max.singular": "Ekki meira en einn bálkur",
"error.blocks.min.plural": "Minnst {min}. bálka",
"error.blocks.min.singular": "Allavegana einn bálkur takk",
"error.blocks.validation": "Það er villa í bálki númer {index}. Klikkaðu á bálkinn og finndu villuna. Það er væntanlega rauðlitur rammi utan um villuna.",
"error.blocks.validation": "There's an error on the \"{field}\" field in block {index} using the \"{fieldset}\" block type",
"error.email.preset.notFound": "Netfangstillingarnar: \"{name}\" fundust ekki",
@@ -107,13 +107,15 @@
"error.language.name": "Gott og gyllt nafn fyrir tungumálið",
"error.language.notFound": "Tungumálið fannst ekkert",
"error.layout.validation.block": "Það er villa í bálki {blockIndex} í rammanum {layoutIndex}",
"error.layout.validation.block": "There's an error on the \"{field}\" field in block {blockIndex} using the \"{fieldset}\" block type in layout {layoutIndex}",
"error.layout.validation.settings": "Hér er villa í sitllingum fyrir ramman {index}",
"error.license.format": "Gildur leyfiskóði hér",
"error.license.email": "Almennilegt netfang hér",
"error.license.verification": "Ekki heppnaðist að staðfesta leyfið",
"error.object.validation": "There’s an error in the \"{label}\" field:\n{message}",
"error.offline": "Stjórnborðið er óvirkt eins og stendur.",
"error.page.changeSlug.permission": "Þú hefur ekkert leyfi til þess að breyta slóðarforskeytinu fyrir \"{slug}\"",
@@ -282,9 +284,13 @@
"field.layout.empty": "Nei. Engir rammar enn.",
"field.layout.select": "Veldu rammategund",
"field.object.empty": "No information yet",
"field.pages.empty": "Engar síður valdar ennþá",
"field.structure.delete.confirm": "Viltu virkilega eyða þessari röð?",
"field.structure.empty": "Engar færslur enn",
"field.users.empty": "Engir notendur valdir enn",
"file.blueprint": "Þessi skrá hefur ekki skipan (e. blueprint) ennþá. Þú mátt skilgreina skipanina í <strong>/site/blueprints/{template}.yml</strong>",
@@ -360,7 +366,7 @@
"lock.unlock": "Aflæsa",
"lock.isUnlocked": "Þær breytingar sem þú gerðir hafa verið yfirskrifaðar af öðrum notanda. Þú getur sótt þær breytingar og splæst þeim saman við þínar breytingar. Handvirkt.",
"login": "Innskrá",
"login": "Log in",
"login.code.label.login": "Innskráningarkóði",
"login.code.label.password-reset": "Kóði fyrir endurstillingu lykilorðs",
"login.code.placeholder.email": "000 000",
@@ -448,6 +454,7 @@
"paste": "Líma",
"paste.after": "Líma eftir",
"pixel": "Punkta",
"plugin": "Plugin",
"plugins": "Viðbætur",
"prev": "Fyrri",
"preview": "Forskoða",
@@ -487,11 +494,24 @@
"stats.empty": "No reports",
"system.issues.content": "The content folder seems to be exposed",
"system.issues.eol.kirby": "Your installed Kirby version has reached end-of-life and will not receive further security updates",
"system.issues.eol.plugin": "Your installed version of the { plugin } plugin is has reached end-of-life and will not receive further security updates",
"system.issues.debug": "Debugging must be turned off in production",
"system.issues.git": "The .git folder seems to be exposed",
"system.issues.https": "We recommend HTTPS for all your sites",
"system.issues.kirby": "The kirby folder seems to be exposed",
"system.issues.site": "The site folder seems to be exposed",
"system.issues.vulnerability.kirby": "Your installation might be affected by the following vulnerability ({ severity } severity): { description }",
"system.issues.vulnerability.plugin": "Your installation might be affected by the following vulnerability in the { plugin } plugin ({ severity } severity): { description }",
"system.updateStatus": "Update status",
"system.updateStatus.error": "Could not check for updates",
"system.updateStatus.not-vulnerable": "No known vulnerabilities",
"system.updateStatus.security-update": "Free security update { version } available",
"system.updateStatus.security-upgrade": "Upgrade { version } with security fixes available",
"system.updateStatus.unreleased": "Unreleased version",
"system.updateStatus.up-to-date": "Up to date",
"system.updateStatus.update": "Free update { version } available",
"system.updateStatus.upgrade": "Upgrade { version } available",
"title": "Titill",
"template": "Sniðmát",
@@ -558,6 +578,9 @@
"users": "Notendur",
"version": "Útgáfa",
"version.current": "Current version",
"version.latest": "Latest version",
"versionInformation": "Version information",
"view.account": "Notandareikningurinn þinn",
"view.installation": "Uppsetning",
+25 -2
View File
@@ -70,7 +70,7 @@
"error.blocks.max.singular": "Non puoi aggiungere più di un blocco",
"error.blocks.min.plural": "Devi aggiungere almeno {min} blocchi",
"error.blocks.min.singular": "Devi aggiungere almeno un blocco",
"error.blocks.validation": "C'è un errore nel blocco {index}",
"error.blocks.validation": "There's an error on the \"{field}\" field in block {index} using the \"{fieldset}\" block type",
"error.email.preset.notFound": "Non è stato possibile trovare il preset email \"{name}\"",
@@ -107,13 +107,15 @@
"error.language.name": "Inserisci un nome valido per la lingua",
"error.language.notFound": "La lingua non è stata trovata",
"error.layout.validation.block": "C'è un errore nel blocco {blockIndex} nel layout {layoutIndex}",
"error.layout.validation.block": "There's an error on the \"{field}\" field in block {blockIndex} using the \"{fieldset}\" block type in layout {layoutIndex}",
"error.layout.validation.settings": "C'è un errore nelle impostazioni del layout {index}",
"error.license.format": "Inserisci un codice di licenza valido",
"error.license.email": "Inserisci un indirizzo email valido",
"error.license.verification": "Non è stato possibile verificare la licenza",
"error.object.validation": "There’s an error in the \"{label}\" field:\n{message}",
"error.offline": "Il pannello di controllo è attualmente offline",
"error.page.changeSlug.permission": "Non ti è permesso cambiare l'URL di \"{slug}\"",
@@ -282,9 +284,13 @@
"field.layout.empty": "Nessuna riga inserita",
"field.layout.select": "Scegli un layout",
"field.object.empty": "No information yet",
"field.pages.empty": "Nessuna pagina selezionata",
"field.structure.delete.confirm": "Vuoi veramente eliminare questo elemento?",
"field.structure.empty": "Non ci sono ancora elementi.",
"field.users.empty": "Nessun utente selezionato",
"file.blueprint": "Questo file non ha ancora un blueprint. Puoi definire la sua configurazione in <strong>/site/blueprints/files/{blueprint}.yml</strong>",
@@ -448,6 +454,7 @@
"paste": "Incolla",
"paste.after": "Incolla dopo",
"pixel": "Pixel",
"plugin": "Plugin",
"plugins": "Plugins",
"prev": "Precedente",
"preview": "Anteprima",
@@ -487,11 +494,24 @@
"stats.empty": "No reports",
"system.issues.content": "The content folder seems to be exposed",
"system.issues.eol.kirby": "Your installed Kirby version has reached end-of-life and will not receive further security updates",
"system.issues.eol.plugin": "Your installed version of the { plugin } plugin is has reached end-of-life and will not receive further security updates",
"system.issues.debug": "Debugging must be turned off in production",
"system.issues.git": "The .git folder seems to be exposed",
"system.issues.https": "We recommend HTTPS for all your sites",
"system.issues.kirby": "The kirby folder seems to be exposed",
"system.issues.site": "The site folder seems to be exposed",
"system.issues.vulnerability.kirby": "Your installation might be affected by the following vulnerability ({ severity } severity): { description }",
"system.issues.vulnerability.plugin": "Your installation might be affected by the following vulnerability in the { plugin } plugin ({ severity } severity): { description }",
"system.updateStatus": "Update status",
"system.updateStatus.error": "Could not check for updates",
"system.updateStatus.not-vulnerable": "No known vulnerabilities",
"system.updateStatus.security-update": "Free security update { version } available",
"system.updateStatus.security-upgrade": "Upgrade { version } with security fixes available",
"system.updateStatus.unreleased": "Unreleased version",
"system.updateStatus.up-to-date": "Up to date",
"system.updateStatus.update": "Free update { version } available",
"system.updateStatus.upgrade": "Upgrade { version } available",
"title": "Titolo",
"template": "Template",
@@ -558,6 +578,9 @@
"users": "Utenti",
"version": "Versione di Kirby",
"version.current": "Current version",
"version.latest": "Latest version",
"versionInformation": "Version information",
"view.account": "Il tuo account",
"view.installation": "Installazione",
+25 -2
View File
@@ -70,7 +70,7 @@
"error.blocks.max.singular": "블록을 하나 이상 추가할 수 없습니다.",
"error.blocks.min.plural": "블록을 {min}개 이상 추가하세요.",
"error.blocks.min.singular": "블록을 하나 이상 추가하세요.",
"error.blocks.validation": "블록({index})이 올바르지 않습니다.",
"error.blocks.validation": "There's an error on the \"{field}\" field in block {index} using the \"{fieldset}\" block type",
"error.email.preset.notFound": "기본 이메일 주소({name})가 없습니다.",
@@ -107,13 +107,15 @@
"error.language.name": "올바른 언어명을 입력하세요.",
"error.language.notFound": "언어를 찾을 수 없습니다.",
"error.layout.validation.block": "레이아웃({layoutIndex})의 블록({blockIndex})을 확인하세요.",
"error.layout.validation.block": "There's an error on the \"{field}\" field in block {blockIndex} using the \"{fieldset}\" block type in layout {layoutIndex}",
"error.layout.validation.settings": "레이아웃({index})의 옵션을 확인하세요.",
"error.license.format": "올바른 라이선스 키를 입력하세요.",
"error.license.email": "올바른 이메일 주소를 입력하세요.",
"error.license.verification": "라이선스 키가 올바르지 않습니다.",
"error.object.validation": "{label} 필드에 오류가 있습니다.\n{message}",
"error.offline": "패널이 오프라인 상태입니다.",
"error.page.changeSlug.permission": "고유 주소({slug})를 변경할 권한이 없습니다.",
@@ -282,9 +284,13 @@
"field.layout.empty": "행이 없습니다.",
"field.layout.select": "레이아웃 선택",
"field.object.empty": "정보가 없습니다.",
"field.pages.empty": "선택한 페이지가 없습니다.",
"field.structure.delete.confirm": "이 항목을 삭제할까요?",
"field.structure.empty": "항목이 없습니다.",
"field.users.empty": "선택한 사용자가 없습니다.",
"file.blueprint": "블루프린트(<strong>/site/blueprints/files/{blueprint}.yml</strong>)를 설정하세요.",
@@ -448,6 +454,7 @@
"paste": "붙여넣기",
"paste.after": "뒤로 붙여넣기",
"pixel": "픽셀",
"plugin": "Plugin",
"plugins": "플러그인",
"prev": "이전",
"preview": "미리 보기",
@@ -487,11 +494,24 @@
"stats.empty": "관련 기록이 없습니다.",
"system.issues.content": "<code>/content</code> 폴더의 권한을 확인하세요.",
"system.issues.eol.kirby": "Your installed Kirby version has reached end-of-life and will not receive further security updates",
"system.issues.eol.plugin": "Your installed version of the { plugin } plugin is has reached end-of-life and will not receive further security updates",
"system.issues.debug": "공개 서버상에서는 디버그 모드를 해제하세요.",
"system.issues.git": "<code>/.git</code> 폴더의 권한을 확인하세요.",
"system.issues.https": "HTTPS를 권장합니다.",
"system.issues.kirby": "<code>/kirby</code> 폴더의 권한을 확인하세요.",
"system.issues.site": "<code>/site</code> 폴더의 권한을 확인하세요.",
"system.issues.vulnerability.kirby": "Your installation might be affected by the following vulnerability ({ severity } severity): { description }",
"system.issues.vulnerability.plugin": "Your installation might be affected by the following vulnerability in the { plugin } plugin ({ severity } severity): { description }",
"system.updateStatus": "Update status",
"system.updateStatus.error": "Could not check for updates",
"system.updateStatus.not-vulnerable": "No known vulnerabilities",
"system.updateStatus.security-update": "Free security update { version } available",
"system.updateStatus.security-upgrade": "Upgrade { version } with security fixes available",
"system.updateStatus.unreleased": "Unreleased version",
"system.updateStatus.up-to-date": "Up to date",
"system.updateStatus.update": "Free update { version } available",
"system.updateStatus.upgrade": "Upgrade { version } available",
"title": "제목",
"template": "\ud15c\ud50c\ub9bf",
@@ -558,6 +578,9 @@
"users": "사용자",
"version": "버전",
"version.current": "Current version",
"version.latest": "Latest version",
"versionInformation": "Version information",
"view.account": "계정",
"view.installation": "\uc124\uce58",
+25 -2
View File
@@ -70,7 +70,7 @@
"error.blocks.max.singular": "Jūs galite pridėti daugiausiai vieną bloką",
"error.blocks.min.plural": "Minimalus blokų kiekis: {min}",
"error.blocks.min.singular": "Jūs turite pridėti bent vieną bloką",
"error.blocks.validation": "Bloke {index} yra klaida",
"error.blocks.validation": "There's an error on the \"{field}\" field in block {index} using the \"{fieldset}\" block type",
"error.email.preset.notFound": "El. pašto paruoštukas \"{name}\" nerastas",
@@ -107,13 +107,15 @@
"error.language.name": "Prašome įrašyti teisingą kalbos pavadinimą",
"error.language.notFound": "Nepavyko rasti šios kalbos",
"error.layout.validation.block": "Yra klaida bloke {blockIndex} išdėstyme {layoutIndex}",
"error.layout.validation.block": "There's an error on the \"{field}\" field in block {blockIndex} using the \"{fieldset}\" block type in layout {layoutIndex}",
"error.layout.validation.settings": "Yra klaida išdėstymo {index} nustatymuose",
"error.license.format": "Prašome įrašyti teisingą licenzijos kodą",
"error.license.email": "Prašome įrašyti teisingą el. pašto adresą",
"error.license.verification": "Nepavyko patikrinti licenzijos",
"error.object.validation": "There’s an error in the \"{label}\" field:\n{message}",
"error.offline": "The Panel is currently offline",
"error.page.changeSlug.permission": "Neturite teisės pakeisti \"{slug}\" URL",
@@ -282,9 +284,13 @@
"field.layout.empty": "Dar nėra eilučių",
"field.layout.select": "Pasirinkite išdėstymą",
"field.object.empty": "No information yet",
"field.pages.empty": "Dar nėra puslapių",
"field.structure.delete.confirm": "Ar tikrai norite pašalinti šią eilutę?",
"field.structure.empty": "Dar nėra įrašų",
"field.users.empty": "Dar nėra vartotojų",
"file.blueprint": "Šis failas dar neturi blueprint. Galite nustatyti jį per <strong>/site/blueprints/files/{blueprint}.yml</strong>",
@@ -448,6 +454,7 @@
"paste": "Įterpti",
"paste.after": "Įterpti po",
"pixel": "Pikselis",
"plugin": "Plugin",
"plugins": "Plugins",
"prev": "Ankstesnis",
"preview": "Peržiūra",
@@ -487,11 +494,24 @@
"stats.empty": "No reports",
"system.issues.content": "The content folder seems to be exposed",
"system.issues.eol.kirby": "Your installed Kirby version has reached end-of-life and will not receive further security updates",
"system.issues.eol.plugin": "Your installed version of the { plugin } plugin is has reached end-of-life and will not receive further security updates",
"system.issues.debug": "Debugging must be turned off in production",
"system.issues.git": "The .git folder seems to be exposed",
"system.issues.https": "We recommend HTTPS for all your sites",
"system.issues.kirby": "The kirby folder seems to be exposed",
"system.issues.site": "The site folder seems to be exposed",
"system.issues.vulnerability.kirby": "Your installation might be affected by the following vulnerability ({ severity } severity): { description }",
"system.issues.vulnerability.plugin": "Your installation might be affected by the following vulnerability in the { plugin } plugin ({ severity } severity): { description }",
"system.updateStatus": "Update status",
"system.updateStatus.error": "Could not check for updates",
"system.updateStatus.not-vulnerable": "No known vulnerabilities",
"system.updateStatus.security-update": "Free security update { version } available",
"system.updateStatus.security-upgrade": "Upgrade { version } with security fixes available",
"system.updateStatus.unreleased": "Unreleased version",
"system.updateStatus.up-to-date": "Up to date",
"system.updateStatus.update": "Free update { version } available",
"system.updateStatus.upgrade": "Upgrade { version } available",
"title": "Pavadinimas",
"template": "Puslapio šablonas",
@@ -558,6 +578,9 @@
"users": "Vartotojai",
"version": "Versija",
"version.current": "Current version",
"version.latest": "Latest version",
"versionInformation": "Version information",
"view.account": "Jūsų paskyra",
"view.installation": "Installation",
+25 -2
View File
@@ -70,7 +70,7 @@
"error.blocks.max.singular": "Du kan ikke legge til mer enn en blokk",
"error.blocks.min.plural": "Du må legge til minst {min} blokker",
"error.blocks.min.singular": "Du må legge til minst en blokk",
"error.blocks.validation": "Det er en feil i blokken {index}",
"error.blocks.validation": "There's an error on the \"{field}\" field in block {index} using the \"{fieldset}\" block type",
"error.email.preset.notFound": "E-postinnstillingen \"{name}\" ble ikke funnet",
@@ -107,13 +107,15 @@
"error.language.name": "Vennligst skriv inn et gyldig navn for språket",
"error.language.notFound": "Finner ikke språket",
"error.layout.validation.block": "Det er en feil i blokk {blockIndex} i layout {layoutIndex}",
"error.layout.validation.block": "There's an error on the \"{field}\" field in block {blockIndex} using the \"{fieldset}\" block type in layout {layoutIndex}",
"error.layout.validation.settings": "Det er en feil i layout {index} innstillinger",
"error.license.format": "Vennligst skriv inn gyldig lisensnøkkel",
"error.license.email": "Vennligst skriv inn en gyldig e-postadresse",
"error.license.verification": "Lisensen kunne ikke verifiseres",
"error.object.validation": "There’s an error in the \"{label}\" field:\n{message}",
"error.offline": "Panelet er i øyeblikket offline",
"error.page.changeSlug.permission": "Du kan ikke endre URLen for denne siden",
@@ -282,9 +284,13 @@
"field.layout.empty": "Ingen rader enda",
"field.layout.select": "Velg en layout",
"field.object.empty": "No information yet",
"field.pages.empty": "Ingen side har blitt valgt",
"field.structure.delete.confirm": "\u00d8nsker du virkelig \u00e5 slette denne oppf\u00f8ringen?",
"field.structure.empty": "Ingen oppf\u00f8ringer enda",
"field.users.empty": "Ingen bruker har blitt valgt",
"file.blueprint": "Denne filen har ikke en blueprint enda. Du kan definere oppsettet i <strong>/site/blueprints/files/{blueprint}.yml</strong>",
@@ -448,6 +454,7 @@
"paste": "Lim inn",
"paste.after": "Lim inn etter",
"pixel": "Piksel",
"plugin": "Plugin",
"plugins": "Plugins",
"prev": "Forrige",
"preview": "Forhåndsvisning",
@@ -487,11 +494,24 @@
"stats.empty": "No reports",
"system.issues.content": "The content folder seems to be exposed",
"system.issues.eol.kirby": "Your installed Kirby version has reached end-of-life and will not receive further security updates",
"system.issues.eol.plugin": "Your installed version of the { plugin } plugin is has reached end-of-life and will not receive further security updates",
"system.issues.debug": "Debugging must be turned off in production",
"system.issues.git": "The .git folder seems to be exposed",
"system.issues.https": "We recommend HTTPS for all your sites",
"system.issues.kirby": "The kirby folder seems to be exposed",
"system.issues.site": "The site folder seems to be exposed",
"system.issues.vulnerability.kirby": "Your installation might be affected by the following vulnerability ({ severity } severity): { description }",
"system.issues.vulnerability.plugin": "Your installation might be affected by the following vulnerability in the { plugin } plugin ({ severity } severity): { description }",
"system.updateStatus": "Update status",
"system.updateStatus.error": "Could not check for updates",
"system.updateStatus.not-vulnerable": "No known vulnerabilities",
"system.updateStatus.security-update": "Free security update { version } available",
"system.updateStatus.security-upgrade": "Upgrade { version } with security fixes available",
"system.updateStatus.unreleased": "Unreleased version",
"system.updateStatus.up-to-date": "Up to date",
"system.updateStatus.update": "Free update { version } available",
"system.updateStatus.upgrade": "Upgrade { version } available",
"title": "Tittel",
"template": "Mal",
@@ -558,6 +578,9 @@
"users": "Brukere",
"version": "Kirby versjon",
"version.current": "Current version",
"version.latest": "Latest version",
"versionInformation": "Version information",
"view.account": "Din konto",
"view.installation": "Installasjon",
+29 -6
View File
@@ -70,7 +70,7 @@
"error.blocks.max.singular": "Je kunt niet meer dan één blok toevoegen",
"error.blocks.min.plural": "Je moet ten minste {min} blok toevoegen",
"error.blocks.min.singular": "Je moet ten minste één blok toevoegen",
"error.blocks.validation": "Er is een fout gevonden in blok {index}",
"error.blocks.validation": "There's an error on the \"{field}\" field in block {index} using the \"{fieldset}\" block type",
"error.email.preset.notFound": "De e-mailvoorinstelling \"{name}\" kan niet worden gevonden",
@@ -107,13 +107,15 @@
"error.language.name": "Vul een geldige naam voor deze taal in",
"error.language.notFound": "De taal kan niet worden gevonden",
"error.layout.validation.block": "Er is een fout gevonden in blok {blockIndex} in ontwerp {layoutIndex}",
"error.layout.validation.block": "There's an error on the \"{field}\" field in block {blockIndex} using the \"{fieldset}\" block type in layout {layoutIndex}",
"error.layout.validation.settings": "Er is een fout gevonden in de instellingen van ontwerp {index} ",
"error.license.format": "Vul een gelidge licentie-key in",
"error.license.email": "Gelieve een geldig emailadres in te voeren",
"error.license.verification": "De licentie kon niet worden geverifieerd. ",
"error.object.validation": "There’s an error in the \"{label}\" field:\n{message}",
"error.offline": "Het Panel is momenteel offline",
"error.page.changeSlug.permission": "Je kunt de URL van deze pagina niet wijzigen",
@@ -282,9 +284,13 @@
"field.layout.empty": "Er zijn nog geen rijen",
"field.layout.select": "Selecteer een indeling",
"field.object.empty": "Nog geen informatie",
"field.pages.empty": "Nog geen pagina's geselecteerd",
"field.structure.delete.confirm": "Wil je deze entry verwijderen?",
"field.structure.empty": "Nog geen items.",
"field.users.empty": "Nog geen gebruikers geselecteerd",
"file.blueprint": "Dit bestand heeft nog geen blauwdruk. U kunt de instellingen definiëren in <strong>/site/blueprints/files/{blueprint}.yml</strong>",
@@ -340,7 +346,7 @@
"license": "Licentie",
"license.buy": "Koop een licentie",
"license.register": "Registreren",
"license.manage": "Manage your licenses",
"license.manage": "Beheer je licenties",
"license.register.help": "Je hebt de licentie via e-mail gekregen nadat je de aankoop hebt gedaan. Kopieer en plak de licentie om te registreren. ",
"license.register.label": "Vul je licentie in",
"license.register.success": "Bedankt dat je Kirby ondersteunt",
@@ -448,6 +454,7 @@
"paste": "Plak",
"paste.after": "Plak achter",
"pixel": "Pixel",
"plugin": "Plugin",
"plugins": "Plugins",
"prev": "Vorige",
"preview": "Voorbeeld",
@@ -475,7 +482,7 @@
"section.required": "De sectie is verplicht",
"security": "Security",
"security": "Beveiliging",
"select": "Selecteren",
"server": "Server",
"settings": "Opties",
@@ -487,11 +494,24 @@
"stats.empty": "No reports",
"system.issues.content": "The content folder seems to be exposed",
"system.issues.eol.kirby": "Your installed Kirby version has reached end-of-life and will not receive further security updates",
"system.issues.eol.plugin": "Your installed version of the { plugin } plugin is has reached end-of-life and will not receive further security updates",
"system.issues.debug": "Debugging must be turned off in production",
"system.issues.git": "The .git folder seems to be exposed",
"system.issues.https": "We recommend HTTPS for all your sites",
"system.issues.git": "De .git map lijkt zichtbaar te zijn",
"system.issues.https": "We raden HTTPS aan voor al je sites",
"system.issues.kirby": "The kirby folder seems to be exposed",
"system.issues.site": "The site folder seems to be exposed",
"system.issues.vulnerability.kirby": "Your installation might be affected by the following vulnerability ({ severity } severity): { description }",
"system.issues.vulnerability.plugin": "Your installation might be affected by the following vulnerability in the { plugin } plugin ({ severity } severity): { description }",
"system.updateStatus": "Update status",
"system.updateStatus.error": "Could not check for updates",
"system.updateStatus.not-vulnerable": "Geen gekende kwetsbaarheden",
"system.updateStatus.security-update": "Gratis veiligheids update { version } beschikbaar",
"system.updateStatus.security-upgrade": "Upgrade { version } met veiligheid aanpassingen beschikbaar",
"system.updateStatus.unreleased": "Niet vrijgegeven versie",
"system.updateStatus.up-to-date": "Up to date",
"system.updateStatus.update": "Gratis update { version } beschikbaar",
"system.updateStatus.upgrade": "Upgrade { version } beschikbaar",
"title": "Titel",
"template": "Template",
@@ -558,6 +578,9 @@
"users": "Gebruikers",
"version": "Kirby-versie",
"version.current": "Huidige versie",
"version.latest": "Laatste versie",
"versionInformation": "Versie informatie",
"view.account": "Jouw account",
"view.installation": "Installatie",
+25 -2
View File
@@ -70,7 +70,7 @@
"error.blocks.max.singular": "Możesz dodać tylko jeden blok",
"error.blocks.min.plural": "Musisz dodać co najmniej {min} bloki/-ów",
"error.blocks.min.singular": "Musisz dodać co najmniej jeden blok",
"error.blocks.validation": "W bloku {index} jest błąd",
"error.blocks.validation": "There's an error on the \"{field}\" field in block {index} using the \"{fieldset}\" block type",
"error.email.preset.notFound": "Nie udało się załadować wzorca wiadomości e-mail \"{name}\"",
@@ -107,13 +107,15 @@
"error.language.name": "Wprowadź poprawną nazwę języka.",
"error.language.notFound": "Język nie został odnaleziony",
"error.layout.validation.block": "W bloku {blockIndex} w układzie {layoutIndex} jest błąd",
"error.layout.validation.block": "There's an error on the \"{field}\" field in block {blockIndex} using the \"{fieldset}\" block type in layout {layoutIndex}",
"error.layout.validation.settings": "W ustawieniach układu {index} jest błąd",
"error.license.format": "Wprowadź poprawny klucz licencyjny",
"error.license.email": "Wprowadź poprawny adres email",
"error.license.verification": "Nie udało się zweryfikować licencji",
"error.object.validation": "There’s an error in the \"{label}\" field:\n{message}",
"error.offline": "Panel jest obecnie offline",
"error.page.changeSlug.permission": "Nie możesz zmienić końcówki adresu URL w \"{slug}\"",
@@ -282,9 +284,13 @@
"field.layout.empty": "Nie ma jeszcze żadnych rzędów",
"field.layout.select": "Wybierz układ",
"field.object.empty": "No information yet",
"field.pages.empty": "Nie wybrano jeszcze żadnych stron",
"field.structure.delete.confirm": "Czy na pewno chcesz usunąć ten wiersz?",
"field.structure.empty": "Nie ma jeszcze \u017cadnych wpis\u00f3w.",
"field.users.empty": "Nie wybrano jeszcze żadnych użytkowników",
"file.blueprint": "Ten plik nie ma jeszcze wzorca. Możesz go zdefiniować w <strong>/site/blueprints/files/{blueprint}.yml</strong>",
@@ -448,6 +454,7 @@
"paste": "Wklej",
"paste.after": "Wklej po",
"pixel": "Piksel",
"plugin": "Plugin",
"plugins": "Wtyczki",
"prev": "Poprzednie",
"preview": "Podgląd",
@@ -487,11 +494,24 @@
"stats.empty": "Brak raportów",
"system.issues.content": "Zdaje się, że folder „content” jest wystawiony na publiczny dostęp",
"system.issues.eol.kirby": "Your installed Kirby version has reached end-of-life and will not receive further security updates",
"system.issues.eol.plugin": "Your installed version of the { plugin } plugin is has reached end-of-life and will not receive further security updates",
"system.issues.debug": "Debugowanie musi być wyłączone w środowisku produkcyjnym",
"system.issues.git": "Zdaje się, że folder „.git” jest wystawiony na publiczny dostęp",
"system.issues.https": "Zalecamy HTTPS dla wszystkich Twoich witryn",
"system.issues.kirby": "Zdaje się, że folder „kirby” jest wystawiony na publiczny dostęp",
"system.issues.site": "Zdaje się, że folder „site” jest wystawiony na publiczny dostęp",
"system.issues.vulnerability.kirby": "Your installation might be affected by the following vulnerability ({ severity } severity): { description }",
"system.issues.vulnerability.plugin": "Your installation might be affected by the following vulnerability in the { plugin } plugin ({ severity } severity): { description }",
"system.updateStatus": "Update status",
"system.updateStatus.error": "Could not check for updates",
"system.updateStatus.not-vulnerable": "No known vulnerabilities",
"system.updateStatus.security-update": "Free security update { version } available",
"system.updateStatus.security-upgrade": "Upgrade { version } with security fixes available",
"system.updateStatus.unreleased": "Unreleased version",
"system.updateStatus.up-to-date": "Up to date",
"system.updateStatus.update": "Free update { version } available",
"system.updateStatus.upgrade": "Upgrade { version } available",
"title": "Tytuł",
"template": "Szablon",
@@ -558,6 +578,9 @@
"users": "Użytkownicy",
"version": "Wersja",
"version.current": "Current version",
"version.latest": "Latest version",
"versionInformation": "Version information",
"view.account": "Twoje konto",
"view.installation": "Instalacja",
+25 -2
View File
@@ -70,7 +70,7 @@
"error.blocks.max.singular": "Você não deve adicionar mais do que um bloco",
"error.blocks.min.plural": "Você deve adicionar pelo menos {min} blocos",
"error.blocks.min.singular": "Você deve adicionar pelo menos um bloco",
"error.blocks.validation": "Há um erro no bloco {index}",
"error.blocks.validation": "There's an error on the \"{field}\" field in block {index} using the \"{fieldset}\" block type",
"error.email.preset.notFound": "Pré-configuração de email \"{name}\" não foi encontrada",
@@ -107,13 +107,15 @@
"error.language.name": "Por favor entre um nome válido para o idioma",
"error.language.notFound": "O idioma não foi encontrado",
"error.layout.validation.block": "Há um erro no bloco {blockIndex} no layout {layoutIndex}",
"error.layout.validation.block": "There's an error on the \"{field}\" field in block {blockIndex} using the \"{fieldset}\" block type in layout {layoutIndex}",
"error.layout.validation.settings": "Há um erro na configuração do layout {index}",
"error.license.format": "Por favor entre uma chave de licensa válida ",
"error.license.email": "Digite um endereço de email válido",
"error.license.verification": "A licensa não pôde ser verificada",
"error.object.validation": "There’s an error in the \"{label}\" field:\n{message}",
"error.offline": "O painel está offline no momento",
"error.page.changeSlug.permission": "Você não tem permissão para alterar o anexo de URL de \"{slug}\"",
@@ -282,9 +284,13 @@
"field.layout.empty": "Nenhuma linha",
"field.layout.select": "Selecionar um layout",
"field.object.empty": "No information yet",
"field.pages.empty": "Nenhuma página selecionada",
"field.structure.delete.confirm": "Deseja realmente deletar esta linha?",
"field.structure.empty": "Nenhum registro",
"field.users.empty": "Nenhum usuário selecionado",
"file.blueprint": "Este arquivo não tem planta. Você pode definir sua planta em <strong>/site/blueprints/files/{blueprint}.yml</strong>",
@@ -448,6 +454,7 @@
"paste": "Colar",
"paste.after": "Colar após",
"pixel": "Pixel",
"plugin": "Plugin",
"plugins": "Plugins",
"prev": "Anterior",
"preview": "Visualizar",
@@ -487,11 +494,24 @@
"stats.empty": "No reports",
"system.issues.content": "The content folder seems to be exposed",
"system.issues.eol.kirby": "Your installed Kirby version has reached end-of-life and will not receive further security updates",
"system.issues.eol.plugin": "Your installed version of the { plugin } plugin is has reached end-of-life and will not receive further security updates",
"system.issues.debug": "Debugging must be turned off in production",
"system.issues.git": "The .git folder seems to be exposed",
"system.issues.https": "We recommend HTTPS for all your sites",
"system.issues.kirby": "The kirby folder seems to be exposed",
"system.issues.site": "The site folder seems to be exposed",
"system.issues.vulnerability.kirby": "Your installation might be affected by the following vulnerability ({ severity } severity): { description }",
"system.issues.vulnerability.plugin": "Your installation might be affected by the following vulnerability in the { plugin } plugin ({ severity } severity): { description }",
"system.updateStatus": "Update status",
"system.updateStatus.error": "Could not check for updates",
"system.updateStatus.not-vulnerable": "No known vulnerabilities",
"system.updateStatus.security-update": "Free security update { version } available",
"system.updateStatus.security-upgrade": "Upgrade { version } with security fixes available",
"system.updateStatus.unreleased": "Unreleased version",
"system.updateStatus.up-to-date": "Up to date",
"system.updateStatus.update": "Free update { version } available",
"system.updateStatus.upgrade": "Upgrade { version } available",
"title": "Título",
"template": "Tema",
@@ -558,6 +578,9 @@
"users": "Usuários",
"version": "Vers\u00e3o do Kirby",
"version.current": "Current version",
"version.latest": "Latest version",
"versionInformation": "Version information",
"view.account": "Sua conta",
"view.installation": "Instala\u00e7\u00e3o",
+25 -2
View File
@@ -70,7 +70,7 @@
"error.blocks.max.singular": "Você não deve adicionar mais do que um bloco",
"error.blocks.min.plural": "Você deve adicionar pelo menos {min} blocos",
"error.blocks.min.singular": "Você deve adicionar pelo menos um bloco",
"error.blocks.validation": "Há um erro no bloco {index}",
"error.blocks.validation": "There's an error on the \"{field}\" field in block {index} using the \"{fieldset}\" block type",
"error.email.preset.notFound": "Preset de email \"{name}\" não encontrado",
@@ -107,13 +107,15 @@
"error.language.name": "Insira um nome válido para o idioma",
"error.language.notFound": "O idioma não foi encontrado",
"error.layout.validation.block": "Há um erro no bloco {blockIndex} no layout {layoutIndex}",
"error.layout.validation.block": "There's an error on the \"{field}\" field in block {blockIndex} using the \"{fieldset}\" block type in layout {layoutIndex}",
"error.layout.validation.settings": "Há um erro na configuração do layout {index}",
"error.license.format": "Insira uma chave de licença válida",
"error.license.email": "Digite um endereço de email válido",
"error.license.verification": "Não foi possível verificar a licença",
"error.object.validation": "There’s an error in the \"{label}\" field:\n{message}",
"error.offline": "O painel está offline no momento",
"error.page.changeSlug.permission": "Não tem permissões para alterar a URL de \"{slug}\"",
@@ -282,9 +284,13 @@
"field.layout.empty": "Nenhuma linha",
"field.layout.select": "Selecionar um layout",
"field.object.empty": "No information yet",
"field.pages.empty": "Nenhuma página selecionada",
"field.structure.delete.confirm": "Deseja realmente excluir este registro?",
"field.structure.empty": "Nenhum registro",
"field.users.empty": "Nenhum utilizador selecionado",
"file.blueprint": "Este arquivo não tem planta. Você pode definir sua planta em <strong>/site/blueprints/files/{blueprint}.yml</strong>",
@@ -448,6 +454,7 @@
"paste": "Colar",
"paste.after": "Colar após",
"pixel": "Pixel",
"plugin": "Plugin",
"plugins": "Plugins",
"prev": "Anterior",
"preview": "Visualizar",
@@ -487,11 +494,24 @@
"stats.empty": "No reports",
"system.issues.content": "The content folder seems to be exposed",
"system.issues.eol.kirby": "Your installed Kirby version has reached end-of-life and will not receive further security updates",
"system.issues.eol.plugin": "Your installed version of the { plugin } plugin is has reached end-of-life and will not receive further security updates",
"system.issues.debug": "Debugging must be turned off in production",
"system.issues.git": "The .git folder seems to be exposed",
"system.issues.https": "We recommend HTTPS for all your sites",
"system.issues.kirby": "The kirby folder seems to be exposed",
"system.issues.site": "The site folder seems to be exposed",
"system.issues.vulnerability.kirby": "Your installation might be affected by the following vulnerability ({ severity } severity): { description }",
"system.issues.vulnerability.plugin": "Your installation might be affected by the following vulnerability in the { plugin } plugin ({ severity } severity): { description }",
"system.updateStatus": "Update status",
"system.updateStatus.error": "Could not check for updates",
"system.updateStatus.not-vulnerable": "No known vulnerabilities",
"system.updateStatus.security-update": "Free security update { version } available",
"system.updateStatus.security-upgrade": "Upgrade { version } with security fixes available",
"system.updateStatus.unreleased": "Unreleased version",
"system.updateStatus.up-to-date": "Up to date",
"system.updateStatus.update": "Free update { version } available",
"system.updateStatus.upgrade": "Upgrade { version } available",
"title": "Título",
"template": "Tema",
@@ -558,6 +578,9 @@
"users": "Utilizadores",
"version": "Vers\u00e3o do Kirby",
"version.current": "Current version",
"version.latest": "Latest version",
"versionInformation": "Version information",
"view.account": "A sua conta",
"view.installation": "Instala\u00e7\u00e3o",
+25 -2
View File
@@ -70,7 +70,7 @@
"error.blocks.max.singular": "Вы не можете добавить больше одного блока",
"error.blocks.min.plural": "Вы должны добавить хотя бы {min} блоков",
"error.blocks.min.singular": "Вы должны добавить хотя бы один блок",
"error.blocks.validation": "Обнаружена ошибка в блоке {index}",
"error.blocks.validation": "Ошибка в поле \"{field}\" в блоке {index} типа \"{fieldset}\"",
"error.email.preset.notFound": "Шаблон эл. почты \"{name}\" не найден",
@@ -107,13 +107,15 @@
"error.language.name": "Пожалуйста, впишите правильное название языка",
"error.language.notFound": "Не получилось найти этот язык",
"error.layout.validation.block": "Ошибка в блоке {blockIndex} в макете {layoutIndex}",
"error.layout.validation.block": "Ошибка в поле \"{field}\" в блоке {blockIndex} типа \"{fieldset}\" внутри разметки {layoutIndex}",
"error.layout.validation.settings": "Ошибка в настройках макета {index}",
"error.license.format": "Пожалуйста, введите правильный лицензионный код",
"error.license.email": "Пожалуйста, введите правильный Email",
"error.license.verification": "Лицензия не подтверждена",
"error.object.validation": "Ошибка в поле \"{label}\":\n{message}",
"error.offline": "Панель управления не в сети",
"error.page.changeSlug.permission": "\u0412\u044b \u043d\u0435 \u043c\u043e\u0436\u0435\u0442\u0435 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c URL \u044d\u0442\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b",
@@ -282,9 +284,13 @@
"field.layout.empty": "Строк нет",
"field.layout.select": "Выберите разметку",
"field.object.empty": "Пока нет информации",
"field.pages.empty": "Страницы не выбраны",
"field.structure.delete.confirm": "Вы точно хотите удалить эту запись?",
"field.structure.empty": "Записей нет",
"field.users.empty": "Пользователей нет",
"file.blueprint": "У файла пока нет разметки. Вы можете определить новые секции и поля разметки в <strong>/site/blueprints/files/{blueprint}.yml</strong>",
@@ -448,6 +454,7 @@
"paste": "Вставить",
"paste.after": "Вставить после",
"pixel": "Пиксель",
"plugin": "Расширение",
"plugins": "Плагины",
"prev": "Предыдущий",
"preview": "Предпросмотр",
@@ -487,11 +494,24 @@
"stats.empty": "Статистики нет",
"system.issues.content": "Похоже, к папке content есть несанкционированный доступ",
"system.issues.eol.kirby": "Срок службы установленной вами версии Kirby истек, и она больше не будет получать обновления для системы безопасности",
"system.issues.eol.plugin": "Your installed version of the { plugin } plugin is has reached end-of-life and will not receive further security updates",
"system.issues.debug": "Включен режим отладки (debugging). Используйте его только при разработке.",
"system.issues.git": "Похоже, к папке .git есть несанкционированный доступ",
"system.issues.https": "Рекомендуется использовать HTTPS на всех сайтах",
"system.issues.kirby": "Похоже, к папке kirby есть несанкционированный доступ",
"system.issues.site": "Похоже, к папке site есть несанкционированный доступ",
"system.issues.vulnerability.kirby": "Your installation might be affected by the following vulnerability ({ severity } severity): { description }",
"system.issues.vulnerability.plugin": "Your installation might be affected by the following vulnerability in the { plugin } plugin ({ severity } severity): { description }",
"system.updateStatus": "Update status",
"system.updateStatus.error": "Не удалось проверить обновления",
"system.updateStatus.not-vulnerable": "Известных уязвимостей не выявлено",
"system.updateStatus.security-update": "Доступно бесплатное обновление для системы безопасности { version }",
"system.updateStatus.security-upgrade": "Upgrade { version } with security fixes available",
"system.updateStatus.unreleased": "Unreleased version",
"system.updateStatus.up-to-date": "Последняя версия",
"system.updateStatus.update": "Доступно бесплатное обновление { version }",
"system.updateStatus.upgrade": "Upgrade { version } available",
"title": "Название",
"template": "\u0428\u0430\u0431\u043b\u043e\u043d",
@@ -558,6 +578,9 @@
"users": "Пользователи",
"version": "Версия",
"version.current": "Текущая версия",
"version.latest": "Последняя версия",
"versionInformation": "Version information",
"view.account": "\u0412\u0430\u0448 \u0430\u043a\u043a\u0430\u0443\u043d\u0442",
"view.installation": "\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430",
+25 -2
View File
@@ -70,7 +70,7 @@
"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.validation": "There's an error on the \"{field}\" field in block {index} using the \"{fieldset}\" block type",
"error.email.preset.notFound": "E-mailovú predvoľbu \"{name}\" nie je možné nájsť",
@@ -107,13 +107,15 @@
"error.language.name": "Please enter a valid name for the language",
"error.language.notFound": "The language could not be found",
"error.layout.validation.block": "There's an error in block {blockIndex} in layout {layoutIndex}",
"error.layout.validation.block": "There's an error on the \"{field}\" field in block {blockIndex} using the \"{fieldset}\" block type in layout {layoutIndex}",
"error.layout.validation.settings": "There's an error in layout {index} settings",
"error.license.format": "Please enter a valid license key",
"error.license.email": "Prosím, zadajte platnú e-mailovú adresu",
"error.license.verification": "The license could not be verified",
"error.object.validation": "There’s an error in the \"{label}\" field:\n{message}",
"error.offline": "The Panel is currently offline",
"error.page.changeSlug.permission": "Nemáte povolenie na zmenu URL príponu pre \"{slug}\"",
@@ -282,9 +284,13 @@
"field.layout.empty": "No rows yet",
"field.layout.select": "Select a layout",
"field.object.empty": "No information yet",
"field.pages.empty": "Žiadne stránky zatiaľ neboli zvolené",
"field.structure.delete.confirm": "Ste si istý, že chcete zmazať tento riadok?",
"field.structure.empty": "Zatiaľ žiadne údaje",
"field.users.empty": "Žiadni užívatelia zatiaľ neboli zvolení",
"file.blueprint": "This file has no blueprint yet. You can define the setup in <strong>/site/blueprints/files/{blueprint}.yml</strong>",
@@ -448,6 +454,7 @@
"paste": "Paste",
"paste.after": "Paste after",
"pixel": "Pixel",
"plugin": "Plugin",
"plugins": "Plugins",
"prev": "Predchádzajúci",
"preview": "Preview",
@@ -487,11 +494,24 @@
"stats.empty": "No reports",
"system.issues.content": "The content folder seems to be exposed",
"system.issues.eol.kirby": "Your installed Kirby version has reached end-of-life and will not receive further security updates",
"system.issues.eol.plugin": "Your installed version of the { plugin } plugin is has reached end-of-life and will not receive further security updates",
"system.issues.debug": "Debugging must be turned off in production",
"system.issues.git": "The .git folder seems to be exposed",
"system.issues.https": "We recommend HTTPS for all your sites",
"system.issues.kirby": "The kirby folder seems to be exposed",
"system.issues.site": "The site folder seems to be exposed",
"system.issues.vulnerability.kirby": "Your installation might be affected by the following vulnerability ({ severity } severity): { description }",
"system.issues.vulnerability.plugin": "Your installation might be affected by the following vulnerability in the { plugin } plugin ({ severity } severity): { description }",
"system.updateStatus": "Update status",
"system.updateStatus.error": "Could not check for updates",
"system.updateStatus.not-vulnerable": "No known vulnerabilities",
"system.updateStatus.security-update": "Free security update { version } available",
"system.updateStatus.security-upgrade": "Upgrade { version } with security fixes available",
"system.updateStatus.unreleased": "Unreleased version",
"system.updateStatus.up-to-date": "Up to date",
"system.updateStatus.update": "Free update { version } available",
"system.updateStatus.upgrade": "Upgrade { version } available",
"title": "Titulok",
"template": "Šablóna",
@@ -558,6 +578,9 @@
"users": "Užívatelia",
"version": "Verzia",
"version.current": "Current version",
"version.latest": "Latest version",
"versionInformation": "Version information",
"view.account": "Váš účet",
"view.installation": "Inštalácia",
+25 -2
View File
@@ -70,7 +70,7 @@
"error.blocks.max.singular": "Du får inte lägga till mer än ett block",
"error.blocks.min.plural": "Du måste lägga till minst {min} block",
"error.blocks.min.singular": "Du måste lägga till minst ett block",
"error.blocks.validation": "Det finns ett fel i block {index}",
"error.blocks.validation": "Det finns ett fel i fältet \"{field}\" i block {index} med blocktypen \"{fieldset}\"",
"error.email.preset.notFound": "E-postförinställningen \"{name}\" kan inte hittas",
@@ -107,13 +107,15 @@
"error.language.name": "Ange ett giltigt namn för språket",
"error.language.notFound": "Språket hittades inte",
"error.layout.validation.block": "Det finns ett fel i block {blockIndex} i layout {layoutIndex}",
"error.layout.validation.block": "Det finns ett fel i fältet \"{field}\" i blocket {blockIndex} med blocktypen \"{fieldset}\" i layouten {layoutIndex}",
"error.layout.validation.settings": "Det finns ett fel i inställningarna för layout {index}",
"error.license.format": "Ange en giltig licensnyckel",
"error.license.email": "Ange en giltig e-postadress",
"error.license.verification": "Licensen kunde inte verifieras",
"error.object.validation": "Det finns ett fel i fältet \"{label}\":\n{message}",
"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}\"",
@@ -282,9 +284,13 @@
"field.layout.empty": "Inga rader än",
"field.layout.select": "Välj en layout",
"field.object.empty": "Ingen information ännu",
"field.pages.empty": "Inga sidor valda än",
"field.structure.delete.confirm": "Vill du verkligen radera denna rad?",
"field.structure.empty": "Inga poster än",
"field.users.empty": "Inga användare valda än",
"file.blueprint": "Denna fil har ingen blueprint än. Du kan skapa en i <strong>/site/blueprints/files/{blueprint}.yml</strong>",
@@ -448,6 +454,7 @@
"paste": "Klistra in",
"paste.after": "Klistra in efter",
"pixel": "Pixel",
"plugin": "Tillägg",
"plugins": "Tillägg",
"prev": "Föregående",
"preview": "Förhandsgranska",
@@ -487,11 +494,24 @@
"stats.empty": "Inga rapporter",
"system.issues.content": "Mappen content verkar vara exponerad",
"system.issues.eol.kirby": "Din installerade Kirby-version har nått slutet av sin livscykel och kommer inte att få fler säkerhetsuppdateringar",
"system.issues.eol.plugin": "Den installerade versionen av tillägget { plugin } har nått slutet på sin livscykel och kommer inte att få fler säkerhetsuppdateringar.",
"system.issues.debug": "Felsökningsläget måste vara avstängt i produktion",
"system.issues.git": "Mappen .git verkar vara exponerad",
"system.issues.https": "Vi rekommenderar HTTPS för alla dina webbplatser",
"system.issues.kirby": "Mappen kirby verkar vara exponerad",
"system.issues.site": "Mappen site verkar vara exponerad",
"system.issues.vulnerability.kirby": "Din installation kan vara påverkad av följande sårbarhet ({ severity } allvarlighetsgrad): { description }",
"system.issues.vulnerability.plugin": "Din installation kan vara påverkad av följande sårbarhet i tillägget { plugin } ({ severity } allvarlighetsgrad): { description }",
"system.updateStatus": "Uppdatera status",
"system.updateStatus.error": "Det gick inte att söka efter uppdateringar",
"system.updateStatus.not-vulnerable": "Inga kända sårbarheter",
"system.updateStatus.security-update": "Gratis säkerhetsuppdatering { version } tillgänglig",
"system.updateStatus.security-upgrade": "Uppgradering { version } med säkerhetskorrigeringar är tillgänglig",
"system.updateStatus.unreleased": "Osläppt version",
"system.updateStatus.up-to-date": "Uppdaterad",
"system.updateStatus.update": "Gratis uppdatering { version } tillgänglig",
"system.updateStatus.upgrade": "Uppgradering { version } tillgänglig",
"title": "Titel",
"template": "Mall",
@@ -558,6 +578,9 @@
"users": "Användare",
"version": "Version",
"version.current": "Aktuell version",
"version.latest": "Senaste versionen",
"versionInformation": "Versionsinformation",
"view.account": "Ditt konto",
"view.installation": "Installation",
+25 -2
View File
@@ -70,7 +70,7 @@
"error.blocks.max.singular": "Birden fazla blok eklememelisiniz",
"error.blocks.min.plural": "En az {min} blok eklemelisiniz",
"error.blocks.min.singular": "En az bir blok eklemelisiniz",
"error.blocks.validation": "{index} bloğunda bir hata var",
"error.blocks.validation": "\"{fieldset}\" blok türünü kullanan {index}. bloktaki \"{field}\" alanında bir hata var",
"error.email.preset.notFound": "\"{name}\" e-posta adresi bulunamadı",
@@ -107,13 +107,15 @@
"error.language.name": "Lütfen dil için geçerli bir isim girin",
"error.language.notFound": "Dil bulunamadı",
"error.layout.validation.block": "{layoutIndex}. düzenin {blockIndex}. bloğunda bir hata var",
"error.layout.validation.block": "{layoutIndex}. sıradaki düzende \"{fieldset}\" blok türünü kullanan {blockIndex}. bloktaki \"{field}\" alanında bir hata var",
"error.layout.validation.settings": "{index}. düzen ayarlarında bir hata var",
"error.license.format": "Lütfen geçerli bir lisans anahtarı girin",
"error.license.email": "Lütfen geçerli bir e-posta adresi girin",
"error.license.verification": "Lisans doğrulanamadı",
"error.object.validation": "\"{label}\" alanında bir hata var:\n{message}",
"error.offline": "Panel şu anda çevrimdışı",
"error.page.changeSlug.permission": "\"{slug}\" uzantısına sahip bu sayfanın adresini değiştirilemez",
@@ -282,9 +284,13 @@
"field.layout.empty": "Henüz satır yok",
"field.layout.select": "Bir düzen seçin",
"field.object.empty": "Henüz bilgi yok",
"field.pages.empty": "Henüz sayfa seçilmedi",
"field.structure.delete.confirm": "Bu girdiyi silmek istedi\u011finizden emin misiniz?",
"field.structure.empty": "Hen\u00fcz bir girdi yok",
"field.users.empty": "Henüz kullanıcı seçilmedi",
"file.blueprint": "Bu dosyanın henüz bir planı yok. Kurulumu <strong>/site/blueprints/files/{blueprint}.yml</strong> dosyasında tanımlayabilirsiniz.",
@@ -448,6 +454,7 @@
"paste": "Yapıştır",
"paste.after": "Sonrasına yapıştır",
"pixel": "Piksel",
"plugin": "Eklenti",
"plugins": "Eklentiler",
"prev": "Önceki",
"preview": "Önizle",
@@ -487,11 +494,24 @@
"stats.empty": "Rapor yok",
"system.issues.content": "İçerik klasörü açığa çıkmış görünüyor",
"system.issues.eol.kirby": "Yüklü Kirby sürümünüz kullanım ömrünün sonuna ulaştı ve daha fazla güvenlik güncellemesi almayacak",
"system.issues.eol.plugin": "{ plugin } eklentisinin yüklü sürümü kullanım ömrünün sonuna ulaştı ve daha fazla güvenlik güncellemesi almayacak",
"system.issues.debug": "Canlı modda hata ayıklama kapatılmalıdır",
"system.issues.git": ".git klasörü açığa çıkmış görünüyor",
"system.issues.https": "Tüm siteleriniz için HTTPS'yi öneriyoruz",
"system.issues.kirby": "Kirby klasörü açığa çıkmış görünüyor",
"system.issues.site": "Site klasörü açığa çıkmış görünüyor",
"system.issues.vulnerability.kirby": "Kurulumunuz aşağıdaki güvenlik açığından ({ severity } önem derecesi) etkilenebilir: { description }",
"system.issues.vulnerability.plugin": "Kurulumunuz, { plugin } eklentisindeki ({ severity } önem derecesi) aşağıdaki güvenlik açığından etkilenebilir: { description }",
"system.updateStatus": "Güncelleme durumu",
"system.updateStatus.error": "Güncellemeler kontrol edilemedi",
"system.updateStatus.not-vulnerable": "Bilinen güvenlik açığı yok",
"system.updateStatus.security-update": "Ücretsiz güvenlik güncellemesi { version } mevcut",
"system.updateStatus.security-upgrade": "Mevcut güvenlik düzeltmeleriyle { version } sürümüne yükseltin",
"system.updateStatus.unreleased": "Yayınlanmamış sürüm",
"system.updateStatus.up-to-date": "Güncel",
"system.updateStatus.update": "Ücretsiz güncelleme { version } mevcut",
"system.updateStatus.upgrade": "{ version } yükseltme mevcut",
"title": "Başlık",
"template": "\u015eablon",
@@ -558,6 +578,9 @@
"users": "Kullanıcılar",
"version": "Versiyon",
"version.current": "Mevcut sürüm",
"version.latest": "En son sürüm",
"versionInformation": "Sürüm bilgisi",
"view.account": "Hesap Bilgilerin",
"view.installation": "Kurulum",
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+2 -2
View File
File diff suppressed because one or more lines are too long
+83 -180
View File
@@ -4,10 +4,14 @@ namespace Kirby\Api;
use Closure;
use Exception;
use Kirby\Cms\User;
use Kirby\Exception\Exception as ExceptionException;
use Kirby\Exception\NotFoundException;
use Kirby\Filesystem\F;
use Kirby\Http\Response;
use Kirby\Http\Route;
use Kirby\Http\Router;
use Kirby\Toolkit\Collection as BaseCollection;
use Kirby\Toolkit\I18n;
use Kirby\Toolkit\Pagination;
use Kirby\Toolkit\Properties;
@@ -32,82 +36,59 @@ class Api
/**
* Authentication callback
*
* @var \Closure
*/
protected $authentication;
protected Closure|null $authentication = null;
/**
* Debugging flag
*
* @var bool
*/
protected $debug = false;
protected bool $debug = false;
/**
* Collection definition
*
* @var array
*/
protected $collections = [];
protected array $collections = [];
/**
* Injected data/dependencies
*
* @var array
*/
protected $data = [];
protected array $data = [];
/**
* Model definitions
*
* @var array
*/
protected $models = [];
protected array $models = [];
/**
* The current route
*
* @var \Kirby\Http\Route
*/
protected $route;
protected Route|null $route = null;
/**
* The Router instance
*
* @var \Kirby\Http\Router
*/
protected $router;
protected Router|null $router = null;
/**
* Route definition
*
* @var array
*/
protected $routes = [];
protected array $routes = [];
/**
* Request data
* [query, body, files]
*
* @var array
*/
protected $requestData = [];
protected array $requestData = [];
/**
* The applied request method
* (GET, POST, PATCH, etc.)
*
* @var string
*/
protected $requestMethod;
protected string|null $requestMethod = null;
/**
* Magic accessor for any given data
*
* @param string $method
* @param array $args
* @return mixed
* @throws \Kirby\Exception\NotFoundException
*/
public function __call(string $method, array $args = [])
@@ -117,8 +98,6 @@ class Api
/**
* Creates a new API instance
*
* @param array $props
*/
public function __construct(array $props)
{
@@ -128,16 +107,10 @@ class Api
/**
* Runs the authentication method
* if set
*
* @return mixed
*/
public function authenticate()
{
if ($auth = $this->authentication()) {
return $auth->call($this);
}
return true;
return $this->authentication()?->call($this) ?? true;
}
/**
@@ -145,7 +118,7 @@ class Api
*
* @return \Closure|null
*/
public function authentication()
public function authentication(): Closure|null
{
return $this->authentication;
}
@@ -154,14 +127,10 @@ class Api
* Execute an API call for the given path,
* request method and optional request data
*
* @param string|null $path
* @param string $method
* @param array $requestData
* @return mixed
* @throws \Kirby\Exception\NotFoundException
* @throws \Exception
*/
public function call(string $path = null, string $method = 'GET', array $requestData = [])
public function call(string|null $path = null, string $method = 'GET', array $requestData = [])
{
$path = rtrim($path ?? '', '/');
@@ -170,19 +139,18 @@ class Api
$this->router = new Router($this->routes());
$this->route = $this->router->find($path, $method);
$auth = $this->route->attributes()['auth'] ?? true;
$auth = $this->route?->attributes()['auth'] ?? true;
if ($auth !== false) {
$user = $this->authenticate();
// set PHP locales based on *user* language
// so that e.g. strftime() gets formatted correctly
if (is_a($user, 'Kirby\Cms\User') === true) {
if ($user instanceof User) {
$language = $user->language();
// get the locale from the translation
$translation = $user->kirby()->translation($language);
$locale = ($translation !== null) ? $translation->locale() : $language;
$locale = $user->kirby()->translation($language)->locale();
// provide some variants as fallbacks to be
// compatible with as many systems as possible
@@ -208,14 +176,17 @@ class Api
$validate = Pagination::$validate;
Pagination::$validate = false;
$output = $this->route->action()->call($this, ...$this->route->arguments());
$output = $this->route?->action()->call(
$this,
...$this->route->arguments()
);
// restore old pagination validation mode
Pagination::$validate = $validate;
if (
is_object($output) === true &&
is_a($output, 'Kirby\\Http\\Response') !== true
$output instanceof Response === false
) {
return $this->resolve($output)->toResponse();
}
@@ -226,13 +197,10 @@ class Api
/**
* Setter and getter for an API collection
*
* @param string $name
* @param array|null $collection
* @return \Kirby\Api\Collection
* @throws \Kirby\Exception\NotFoundException If no collection for `$name` exists
* @throws \Exception
*/
public function collection(string $name, $collection = null)
public function collection(string $name, array|BaseCollection|null $collection = null): Collection
{
if (isset($this->collections[$name]) === false) {
throw new NotFoundException(sprintf('The collection "%s" does not exist', $name));
@@ -243,8 +211,6 @@ class Api
/**
* Returns the collections definition
*
* @return array
*/
public function collections(): array
{
@@ -255,13 +221,9 @@ class Api
* Returns the injected data array
* or certain parts of it by key
*
* @param string|null $key
* @param mixed ...$args
* @return mixed
*
* @throws \Kirby\Exception\NotFoundException If no data for `$key` exists
*/
public function data($key = null, ...$args)
public function data(string|null $key = null, ...$args)
{
if ($key === null) {
return $this->data;
@@ -272,7 +234,7 @@ class Api
}
// lazy-load data wrapped in Closures
if (is_a($this->data[$key], 'Closure') === true) {
if ($this->data[$key] instanceof Closure) {
return $this->data[$key]->call($this, ...$args);
}
@@ -281,8 +243,6 @@ class Api
/**
* Returns the debugging flag
*
* @return bool
*/
public function debug(): bool
{
@@ -291,9 +251,6 @@ class Api
/**
* Checks if injected data exists for the given key
*
* @param string $key
* @return bool
*/
public function hasData(string $key): bool
{
@@ -305,39 +262,31 @@ class Api
* based on the `type` field
*
* @param array models or collections
* @param mixed $object
*
* @return string key of match
* @return string|null key of match
*/
protected function match(array $array, $object = null)
protected function match(array $array, $object = null): string|null
{
foreach ($array as $definition => $model) {
if (is_a($object, $model['type']) === true) {
if ($object instanceof $model['type']) {
return $definition;
}
}
return null;
}
/**
* Returns an API model instance by name
*
* @param string|null $name
* @param mixed $object
* @return \Kirby\Api\Model
*
* @throws \Kirby\Exception\NotFoundException If no model for `$name` exists
*/
public function model(string $name = null, $object = null)
public function model(string|null $name = null, $object = null): Model
{
// Try to auto-match object with API models
if ($name === null) {
if ($model = $this->match($this->models, $object)) {
$name = $model;
}
}
$name ??= $this->match($this->models, $object);
if (isset($this->models[$name]) === false) {
throw new NotFoundException(sprintf('The model "%s" does not exist', $name));
throw new NotFoundException(sprintf('The model "%s" does not exist', $name ?? 'NULL'));
}
return new Model($this, $object, $this->models[$name]);
@@ -345,8 +294,6 @@ class Api
/**
* Returns all model definitions
*
* @return array
*/
public function models(): array
{
@@ -363,8 +310,11 @@ class Api
* @param mixed $default
* @return mixed
*/
public function requestData(string $type = null, string $key = null, $default = null)
{
public function requestData(
string|null $type = null,
string|null $key = null,
$default = null
) {
if ($type === null) {
return $this->requestData;
}
@@ -381,58 +331,40 @@ class Api
/**
* Returns the request body if available
*
* @param string|null $key
* @param mixed $default
* @return mixed
*/
public function requestBody(string $key = null, $default = null)
public function requestBody(string|null $key = null, $default = null)
{
return $this->requestData('body', $key, $default);
}
/**
* Returns the files from the request if available
*
* @param string|null $key
* @param mixed $default
* @return mixed
*/
public function requestFiles(string $key = null, $default = null)
public function requestFiles(string|null $key = null, $default = null)
{
return $this->requestData('files', $key, $default);
}
/**
* Returns all headers from the request if available
*
* @param string|null $key
* @param mixed $default
* @return mixed
*/
public function requestHeaders(string $key = null, $default = null)
public function requestHeaders(string|null $key = null, $default = null)
{
return $this->requestData('headers', $key, $default);
}
/**
* Returns the request method
*
* @return string
*/
public function requestMethod(): string
public function requestMethod(): string|null
{
return $this->requestMethod;
}
/**
* Returns the request query if available
*
* @param string|null $key
* @param mixed $default
* @return mixed
*/
public function requestQuery(string $key = null, $default = null)
public function requestQuery(string|null $key = null, $default = null)
{
return $this->requestData('query', $key, $default);
}
@@ -441,14 +373,14 @@ class Api
* Turns a Kirby object into an
* API model or collection representation
*
* @param mixed $object
* @return \Kirby\Api\Model|\Kirby\Api\Collection
*
* @throws \Kirby\Exception\NotFoundException If `$object` cannot be resolved
*/
public function resolve($object)
public function resolve($object): Model|Collection
{
if (is_a($object, 'Kirby\Api\Model') === true || is_a($object, 'Kirby\Api\Collection') === true) {
if (
$object instanceof Model ||
$object instanceof Collection
) {
return $object;
}
@@ -465,8 +397,6 @@ class Api
/**
* Returns all defined routes
*
* @return array
*/
public function routes(): array
{
@@ -475,11 +405,9 @@ class Api
/**
* Setter for the authentication callback
*
* @param \Closure|null $authentication
* @return $this
*/
protected function setAuthentication(Closure $authentication = null)
protected function setAuthentication(Closure|null $authentication = null): static
{
$this->authentication = $authentication;
return $this;
@@ -487,11 +415,9 @@ class Api
/**
* Setter for the collections definition
*
* @param array|null $collections
* @return $this
*/
protected function setCollections(array $collections = null)
protected function setCollections(array|null $collections = null): static
{
if ($collections !== null) {
$this->collections = array_change_key_case($collections);
@@ -501,11 +427,9 @@ class Api
/**
* Setter for the injected data
*
* @param array|null $data
* @return $this
*/
protected function setData(array $data = null)
protected function setData(array|null $data = null): static
{
$this->data = $data ?? [];
return $this;
@@ -513,11 +437,9 @@ class Api
/**
* Setter for the debug flag
*
* @param bool $debug
* @return $this
*/
protected function setDebug(bool $debug = false)
protected function setDebug(bool $debug = false): static
{
$this->debug = $debug;
return $this;
@@ -525,11 +447,9 @@ class Api
/**
* Setter for the model definitions
*
* @param array|null $models
* @return $this
*/
protected function setModels(array $models = null)
protected function setModels(array|null $models = null): static
{
if ($models !== null) {
$this->models = array_change_key_case($models);
@@ -540,11 +460,9 @@ class Api
/**
* Setter for the request data
*
* @param array|null $requestData
* @return $this
*/
protected function setRequestData(array $requestData = null)
protected function setRequestData(array|null $requestData = null): static
{
$defaults = [
'query' => [],
@@ -558,11 +476,9 @@ class Api
/**
* Setter for the request method
*
* @param string|null $requestMethod
* @return $this
*/
protected function setRequestMethod(string $requestMethod = null)
protected function setRequestMethod(string|null $requestMethod = null): static
{
$this->requestMethod = $requestMethod ?? 'GET';
return $this;
@@ -570,11 +486,9 @@ class Api
/**
* Setter for the route definitions
*
* @param array|null $routes
* @return $this
*/
protected function setRoutes(array $routes = null)
protected function setRoutes(array|null $routes = null): static
{
$this->routes = $routes ?? [];
return $this;
@@ -582,13 +496,8 @@ class Api
/**
* Renders the API call
*
* @param string $path
* @param string $method
* @param array $requestData
* @return mixed
*/
public function render(string $path, $method = 'GET', array $requestData = [])
public function render(string $path, string $method = 'GET', array $requestData = [])
{
try {
$result = $this->call($path, $method, $requestData);
@@ -596,13 +505,12 @@ class Api
$result = $this->responseForException($e);
}
if ($result === null) {
$result = $this->responseFor404();
} elseif ($result === false) {
$result = $this->responseFor400();
} elseif ($result === true) {
$result = $this->responseFor200();
}
$result = match ($result) {
null => $this->responseFor404(),
false => $this->responseFor400(),
true => $this->responseFor200(),
default => $result
};
if (is_array($result) === false) {
return $result;
@@ -628,8 +536,6 @@ class Api
/**
* Returns a 200 - ok
* response array.
*
* @return array
*/
public function responseFor200(): array
{
@@ -643,8 +549,6 @@ class Api
/**
* Returns a 400 - bad request
* response array.
*
* @return array
*/
public function responseFor400(): array
{
@@ -658,8 +562,6 @@ class Api
/**
* Returns a 404 - not found
* response array.
*
* @return array
*/
public function responseFor404(): array
{
@@ -674,9 +576,6 @@ class Api
* Creates the response array for
* an exception. Kirby exceptions will
* have more information
*
* @param \Throwable $e
* @return array
*/
public function responseForException(Throwable $e): array
{
@@ -696,11 +595,11 @@ class Api
'file' => F::relativepath($e->getFile(), $docRoot),
'line' => $e->getLine(),
'details' => [],
'route' => $this->route ? $this->route->pattern() : null
'route' => $this->route?->pattern()
];
// extend the information for Kirby Exceptions
if (is_a($e, 'Kirby\Exception\Exception') === true) {
if ($e instanceof ExceptionException) {
$result['key'] = $e->getKey();
$result['details'] = $e->getDetails();
$result['code'] = $e->getHttpCode();
@@ -726,14 +625,9 @@ class Api
* move_uploaded_file() not working with unit test
* Added debug parameter for testing purposes as we did in the Email class
*
* @param \Closure $callback
* @param bool $single
* @param bool $debug
* @return array
*
* @throws \Exception If request has no files or there was an error with the upload
*/
public function upload(Closure $callback, $single = false, $debug = false): array
public function upload(Closure $callback, bool $single = false, bool $debug = false): array
{
$trials = 0;
$uploads = [];
@@ -757,13 +651,16 @@ class Api
if ($postMaxSize < $uploadMaxFileSize) {
throw new Exception(I18n::translate('upload.error.iniPostSize'));
} else {
throw new Exception(I18n::translate('upload.error.noFiles'));
}
throw new Exception(I18n::translate('upload.error.noFiles'));
}
foreach ($files as $upload) {
if (isset($upload['tmp_name']) === false && is_array($upload)) {
if (
isset($upload['tmp_name']) === false &&
is_array($upload) === true
) {
continue;
}
@@ -780,7 +677,10 @@ class Api
// try to detect the correct mime and add the extension
// accordingly. This will avoid .tmp filenames
if (empty($extension) === true || in_array($extension, ['tmp', 'temp'])) {
if (
empty($extension) === true ||
in_array($extension, ['tmp', 'temp']) === true
) {
$mime = F::mime($upload['tmp_name']);
$extension = F::mimeToExtension($mime);
$filename = F::name($upload['name']) . '.' . $extension;
@@ -792,7 +692,10 @@ class Api
// move the file to a location including the extension,
// for better mime detection
if ($debug === false && move_uploaded_file($upload['tmp_name'], $source) === false) {
if (
$debug === false &&
move_uploaded_file($upload['tmp_name'], $source) === false
) {
throw new Exception(I18n::translate('upload.error.cantMove'));
}
+7 -31
View File
@@ -2,6 +2,7 @@
namespace Kirby\Api;
use Closure;
use Exception;
use Kirby\Toolkit\Str;
@@ -19,37 +20,15 @@ use Kirby\Toolkit\Str;
*/
class Collection
{
/**
* @var \Kirby\Api\Api
*/
protected $api;
/**
* @var mixed|null
*/
protected Api $api;
protected $data;
/**
* @var mixed|null
*/
protected $model;
/**
* @var mixed|null
*/
protected $select;
/**
* @var mixed|null
*/
protected $view;
/**
* Collection constructor
*
* @param \Kirby\Api\Api $api
* @param mixed|null $data
* @param array $schema
* @throws \Exception
*/
public function __construct(Api $api, $data, array $schema)
@@ -57,10 +36,11 @@ class Collection
$this->api = $api;
$this->data = $data;
$this->model = $schema['model'] ?? null;
$this->select = null;
$this->view = $schema['view'] ?? null;
if ($data === null) {
if (is_a($schema['default'] ?? null, 'Closure') === false) {
if (($schema['default'] ?? null) instanceof Closure === false) {
throw new Exception('Missing collection data');
}
@@ -69,18 +49,17 @@ class Collection
if (
isset($schema['type']) === true &&
is_a($this->data, $schema['type']) === false
$this->data instanceof $schema['type'] === false
) {
throw new Exception('Invalid collection type');
}
}
/**
* @param string|array|null $keys
* @return $this
* @throws \Exception
*/
public function select($keys = null)
public function select($keys = null): static
{
if ($keys === false) {
return $this;
@@ -99,7 +78,6 @@ class Collection
}
/**
* @return array
* @throws \Kirby\Exception\NotFoundException
* @throws \Exception
*/
@@ -125,7 +103,6 @@ class Collection
}
/**
* @return array
* @throws \Kirby\Exception\NotFoundException
* @throws \Exception
*/
@@ -167,10 +144,9 @@ class Collection
}
/**
* @param string $view
* @return $this
*/
public function view(string $view)
public function view(string $view): static
{
$this->view = $view;
return $this;
+16 -36
View File
@@ -2,6 +2,7 @@
namespace Kirby\Api;
use Closure;
use Exception;
use Kirby\Toolkit\Str;
@@ -21,37 +22,15 @@ use Kirby\Toolkit\Str;
*/
class Model
{
/**
* @var \Kirby\Api\Api
*/
protected $api;
/**
* @var mixed|null
*/
protected Api $api;
protected $data;
/**
* @var array|mixed
*/
protected $fields;
/**
* @var mixed|null
*/
protected $select;
/**
* @var array|mixed
*/
protected $views;
/**
* Model constructor
*
* @param \Kirby\Api\Api $api
* @param mixed $data
* @param array $schema
* @throws \Exception
*/
public function __construct(Api $api, $data, array $schema)
@@ -62,12 +41,15 @@ class Model
$this->select = $schema['select'] ?? null;
$this->views = $schema['views'] ?? [];
if ($this->select === null && array_key_exists('default', $this->views)) {
if (
$this->select === null &&
array_key_exists('default', $this->views)
) {
$this->view('default');
}
if ($data === null) {
if (is_a($schema['default'] ?? null, 'Closure') === false) {
if (($schema['default'] ?? null) instanceof Closure === false) {
throw new Exception('Missing model data');
}
@@ -76,18 +58,17 @@ class Model
if (
isset($schema['type']) === true &&
is_a($this->data, $schema['type']) === false
$this->data instanceof $schema['type'] === false
) {
throw new Exception(sprintf('Invalid model type "%s" expected: "%s"', get_class($this->data), $schema['type']));
}
}
/**
* @param null $keys
* @return $this
* @throws \Exception
*/
public function select($keys = null)
public function select($keys = null): static
{
if ($keys === false) {
return $this;
@@ -106,7 +87,6 @@ class Model
}
/**
* @return array
* @throws \Exception
*/
public function selection(): array
@@ -153,7 +133,6 @@ class Model
}
/**
* @return array
* @throws \Kirby\Exception\NotFoundException
* @throws \Exception
*/
@@ -163,7 +142,10 @@ class Model
$result = [];
foreach ($this->fields as $key => $resolver) {
if (array_key_exists($key, $select) === false || is_a($resolver, 'Closure') === false) {
if (
array_key_exists($key, $select) === false ||
$resolver instanceof Closure === false
) {
continue;
}
@@ -174,8 +156,8 @@ class Model
}
if (
is_a($value, 'Kirby\Api\Collection') === true ||
is_a($value, 'Kirby\Api\Model') === true
$value instanceof Collection ||
$value instanceof self
) {
$selection = $select[$key];
@@ -199,7 +181,6 @@ class Model
}
/**
* @return array
* @throws \Kirby\Exception\NotFoundException
* @throws \Exception
*/
@@ -224,11 +205,10 @@ class Model
}
/**
* @param string $name
* @return $this
* @throws \Exception
*/
public function view(string $name)
public function view(string $name): static
{
if ($name === 'any') {
return $this->select(null);
+90
View File
@@ -0,0 +1,90 @@
<?php
namespace Kirby\Blueprint;
use Kirby\Cms\Collection as BaseCollection;
use Kirby\Cms\ModelWithContent;
use Kirby\Toolkit\A;
use TypeError;
/**
* Typed collection
*
* @package Kirby Blueprint
* @author Bastian Allgeier <bastian@getkirby.com>
* @link https://getkirby.com
* @copyright Bastian Allgeier
* @license https://opensource.org/licenses/MIT
*
* // TODO: include in test coverage in 3.9
* @codeCoverageIgnore
*/
class Collection extends BaseCollection
{
/**
* The expected object type
*/
public const TYPE = Node::class;
public function __construct(array $objects = [])
{
foreach ($objects as $object) {
$this->__set($object->id, $object);
}
}
/**
* The Kirby Collection class only shows the key to
* avoid huge tress with dump, but for the blueprint
* collections this is really not useful
*/
public function __debugInfo(): array
{
return A::map($this->data, fn ($item) => (array)$item);
}
/**
* Validate the type of every item that is being
* added to the collection. They cneed to have
* the class defined by static::TYPE.
*/
public function __set(string $key, $value): void
{
if (
is_a($value, static::TYPE) === false
) {
throw new TypeError('Each value in the collection must be an instance of ' . static::TYPE);
}
parent::__set($key, $value);
}
public static function factory(array $items)
{
$collection = new static();
$className = static::TYPE;
foreach ($items as $id => $item) {
if (is_array($item) === true) {
$item['id'] ??= $id;
$item = $className::factory($item);
$collection->__set($item->id, $item);
} else {
$collection->__set($id, $className::factory($item));
}
}
return $collection;
}
public function render(ModelWithContent $model)
{
$props = [];
foreach ($this->data as $key => $item) {
$props[$key] = $item->render($model);
}
return $props;
}
}
+75
View File
@@ -0,0 +1,75 @@
<?php
namespace Kirby\Blueprint;
use Closure;
use Kirby\Cms\App;
use Kirby\Data\Yaml;
use Kirby\Exception\NotFoundException;
use Kirby\Filesystem\F;
/**
* Config
*
* @package Kirby Blueprint
* @author Bastian Allgeier <bastian@getkirby.com>
* @link https://getkirby.com
* @copyright Bastian Allgeier
* @license https://opensource.org/licenses/MIT
*
* // TODO: include in test coverage in 3.9
* @codeCoverageIgnore
*/
class Config
{
public string $file;
public string $id;
public string|array|Closure|null $plugin;
public string $root;
public function __construct(
public string $path
) {
$kirby = App::instance();
$this->id = basename($this->path);
$this->root = $kirby->root('blueprints');
$this->file = $this->root . '/' . $this->path . '.yml';
$this->plugin = $kirby->extension('blueprints', $this->path);
}
public function read(): array
{
if (F::exists($this->file, $this->root) === true) {
return $this->unpack($this->file);
}
return $this->unpack($this->plugin);
}
public function write(array $props): bool
{
return Yaml::write($this->file, $props);
}
public function unpack(string|array|Closure|null $extension): array
{
return match (true) {
// extension does not exist
is_null($extension)
=> throw new NotFoundException('"' . $this->path . '" could not be found'),
// extension is stored as a file path
is_string($extension)
=> Yaml::read($extension),
// extension is a callback to be resolved
is_callable($extension)
=> $extension(App::instance()),
// extension is already defined as array
default
=> $extension
};
}
}
+65
View File
@@ -0,0 +1,65 @@
<?php
namespace Kirby\Blueprint;
/**
* Extension
*
* @package Kirby Blueprint
* @author Bastian Allgeier <bastian@getkirby.com>
* @link https://getkirby.com
* @copyright Bastian Allgeier
* @license https://opensource.org/licenses/MIT
*
* // TODO: include in test coverage in 3.9
* @codeCoverageIgnore
*/
class Extension
{
public function __construct(
public string $path
) {
}
public static function apply(array $props): array
{
if (isset($props['extends']) === false) {
return $props;
}
// already extended
if (is_a($props['extends'], Extension::class) === true) {
return $props;
}
$extension = new static($props['extends']);
return $extension->extend($props);
}
public function extend(array $props): array
{
$props = array_replace_recursive(
$this->read(),
$props
);
$props['extends'] = $this;
return $props;
}
public static function factory(string|array $path): static
{
if (is_string($path) === true) {
return new static(path: $path);
}
return new static(...$path);
}
public function read(): array
{
$config = new Config($this->path);
return $config->read();
}
}
+119
View File
@@ -0,0 +1,119 @@
<?php
namespace Kirby\Blueprint;
use ReflectionException;
use ReflectionNamedType;
use ReflectionProperty;
use ReflectionUnionType;
/**
* Factory
*
* @package Kirby Blueprint
* @author Bastian Allgeier <bastian@getkirby.com>
* @link https://getkirby.com
* @copyright Bastian Allgeier
* @license https://opensource.org/licenses/MIT
*
* // TODO: include in test coverage in 3.9
* @codeCoverageIgnore
*/
class Factory
{
/**
* Resolves the properties by
* applying a map of factories (propName => class)
*/
public static function apply(array $properties, array $factories): array
{
foreach ($factories as $property => $class) {
// skip non-existing properties, empty properties
// or properties that are matching objects
if (
isset($properties[$property]) === false ||
$properties[$property] === null ||
is_a($properties[$property], $class) === true
) {
continue;
}
$properties[$property] = $class::factory($properties[$property]);
}
return $properties;
}
public static function forNamedType(ReflectionNamedType|null $type, $value)
{
// get the class name for the single type
$className = $type->getName();
// check if there's a factory for the value
if (method_exists($className, 'factory') === true) {
return $className::factory($value);
}
// try to assign the value directly and trust
// in PHP's type system.
return $value;
}
public static function forProperties(string $class, array $properties): array
{
foreach ($properties as $property => $value) {
try {
$properties[$property] = static::forProperty($class, $property, $value);
} catch (ReflectionException $e) {
// the property does not exist
unset($properties[$property]);
}
}
return $properties;
}
public static function forProperty(string $class, string $property, $value)
{
if (is_null($value) === true) {
return $value;
}
// instantly assign objects
// PHP's type system will find issues automatically
if (is_object($value) === true) {
return $value;
}
// get the type for the property
$reflection = new ReflectionProperty($class, $property);
$propType = $reflection->getType();
// no type given
if ($propType === null) {
return $value;
}
// union types
if (is_a($propType, ReflectionUnionType::class) === true) {
return static::forUnionType($propType, $value);
}
return static::forNamedType($propType, $value);
}
/**
* For properties with union types,
* the first named type is used to create
* the factory or pass a built-in value
*/
public static function forUnionType(ReflectionUnionType $type, $value)
{
return static::forNamedType($type->getTypes()[0], $value);
}
public static function make(string $class, array $properties): object
{
return new $class(...static::forProperties($class, $properties));
}
}
+118
View File
@@ -0,0 +1,118 @@
<?php
namespace Kirby\Blueprint;
use Kirby\Cms\ModelWithContent;
/**
* A node of the blueprint
*
* @package Kirby Blueprint
* @author Bastian Allgeier <bastian@getkirby.com>
* @link https://getkirby.com
* @copyright Bastian Allgeier
* @license https://opensource.org/licenses/MIT
*
* // TODO: include in test coverage in 3.9
* @codeCoverageIgnore
*/
class Node
{
public const TYPE = 'node';
public function __construct(
public string $id,
public Extension|null $extends = null,
) {
}
/**
* Dynamic getter for properties
*/
public function __call(string $name, array $args)
{
$this->defaults();
return $this->$name;
}
/**
* Apply default values
*/
public function defaults(): static
{
return $this;
}
/**
* Creates an instance by a set of array properties.
*/
public static function factory(array $props): static
{
$props = Extension::apply($props);
$props = static::polyfill($props);
return Factory::make(static::class, $props);
}
public static function load(string|array $props): static
{
// load by path
if (is_string($props) === true) {
$props = static::loadProps($props);
}
return static::factory($props);
}
public static function loadProps(string $path): array
{
$config = new Config($path);
$props = $config->read();
// add the id if it's not set yet
$props['id'] ??= basename($path);
return $props;
}
/**
* Optional method that runs before static::factory sends
* its properties to the instance. This is perfect to clean
* up props or keep deprecated props compatible.
*/
public static function polyfill(array $props): array
{
return $props;
}
public function render(ModelWithContent $model)
{
// apply default values
$this->defaults();
$array = [];
// go through all public properties
foreach (get_object_vars($this) as $key => $value) {
if (is_object($value) === false && is_resource($value) === false) {
$array[$key] = $value;
continue;
}
if (method_exists($value, 'render') === true) {
$array[$key] = $value->render($model);
}
}
return $array;
}
/**
* Universal setter for properties
*/
public function set(string $property, $value): static
{
$this->$property = Factory::forProperty(static::class, $property, $value);
return $this;
}
}
+44
View File
@@ -0,0 +1,44 @@
<?php
namespace Kirby\Blueprint;
use Kirby\Cms\ModelWithContent;
use Kirby\Toolkit\I18n;
/**
* Translatable node property
*
* @package Kirby Blueprint
* @author Bastian Allgeier <bastian@getkirby.com>
* @link https://getkirby.com
* @copyright Bastian Allgeier
* @license https://opensource.org/licenses/MIT
*
* // TODO: include in test coverage in 3.9
* @codeCoverageIgnore
*/
class NodeI18n extends NodeProperty
{
public function __construct(
public array $translations,
) {
}
public static function factory($value = null): static|null
{
if ($value === false || $value === null) {
return null;
}
if (is_array($value) === false) {
$value = ['en' => $value];
}
return new static($value);
}
public function render(ModelWithContent $model): string|null
{
return I18n::translate($this->translations, $this->translations);
}
}
+27
View File
@@ -0,0 +1,27 @@
<?php
namespace Kirby\Blueprint;
/**
* Custom emoji or icon from the Kirby iconset
*
* @package Kirby Blueprint
* @author Bastian Allgeier <bastian@getkirby.com>
* @link https://getkirby.com
* @copyright Bastian Allgeier
* @license https://opensource.org/licenses/MIT
*
* // TODO: include in test coverage in 3.9
* @codeCoverageIgnore
*/
class NodeIcon extends NodeString
{
public static function field()
{
$field = parent::field();
$field->id = 'icon';
$field->label->translations = ['en' => 'Icon'];
return $field;
}
}
+27
View File
@@ -0,0 +1,27 @@
<?php
namespace Kirby\Blueprint;
use Kirby\Cms\ModelWithContent;
/**
* Represents a property for a node
*
* @package Kirby Blueprint
* @author Bastian Allgeier <bastian@getkirby.com>
* @link https://getkirby.com
* @copyright Bastian Allgeier
* @license https://opensource.org/licenses/MIT
*
* // TODO: include in test coverage in 3.9
* @codeCoverageIgnore
*/
abstract class NodeProperty
{
abstract public static function factory($value = null): static|null;
public function render(ModelWithContent $model)
{
return null;
}
}
+39
View File
@@ -0,0 +1,39 @@
<?php
namespace Kirby\Blueprint;
use Kirby\Cms\ModelWithContent;
/**
* Simple string blueprint node
*
* @package Kirby Blueprint
* @author Bastian Allgeier <bastian@getkirby.com>
* @link https://getkirby.com
* @copyright Bastian Allgeier
* @license https://opensource.org/licenses/MIT
*
* // TODO: include in test coverage in 3.9
* @codeCoverageIgnore
*/
class NodeString extends NodeProperty
{
public function __construct(
public string $value,
) {
}
public static function factory($value = null): static|null
{
if ($value === null) {
return $value;
}
return new static($value);
}
public function render(ModelWithContent $model): string|null
{
return $this->value;
}
}
+30
View File
@@ -0,0 +1,30 @@
<?php
namespace Kirby\Blueprint;
use Kirby\Cms\ModelWithContent;
/**
* The text node is translatable
* and will parse query template strings
*
* @package Kirby Blueprint
* @author Bastian Allgeier <bastian@getkirby.com>
* @link https://getkirby.com
* @copyright Bastian Allgeier
* @license https://opensource.org/licenses/MIT
*
* // TODO: include in test coverage in 3.9
* @codeCoverageIgnore
*/
class NodeText extends NodeI18n
{
public function render(ModelWithContent $model): ?string
{
if ($text = parent::render($model)) {
return $model->toSafeString($text);
}
return $text;
}
}
+18 -21
View File
@@ -15,11 +15,17 @@ use APCUIterator;
*/
class ApcuCache extends Cache
{
/**
* Returns whether the cache is ready to
* store values
*/
public function enabled(): bool
{
return apcu_enabled();
}
/**
* Determines if an item exists in the cache
*
* @param string $key
* @return bool
*/
public function exists(string $key): bool
{
@@ -29,24 +35,19 @@ class ApcuCache extends Cache
/**
* Flushes the entire cache and returns
* whether the operation was successful
*
* @return bool
*/
public function flush(): bool
{
if (empty($this->options['prefix']) === false) {
return apcu_delete(new APCUIterator('!^' . preg_quote($this->options['prefix']) . '!'));
} else {
return apcu_clear_cache();
}
return apcu_clear_cache();
}
/**
* Removes an item from the cache and returns
* whether the operation was successful
*
* @param string $key
* @return bool
*/
public function remove(string $key): bool
{
@@ -56,13 +57,11 @@ class ApcuCache extends Cache
/**
* Internal method to retrieve the raw cache value;
* needs to return a Value object or null if not found
*
* @param string $key
* @return \Kirby\Cache\Value|null
*/
public function retrieve(string $key)
public function retrieve(string $key): Value|null
{
return Value::fromJson(apcu_fetch($this->key($key)));
$value = apcu_fetch($this->key($key));
return Value::fromJson($value);
}
/**
@@ -73,14 +72,12 @@ class ApcuCache extends Cache
* // put an item in the cache for 15 minutes
* $cache->set('value', 'my value', 15);
* </code>
*
* @param string $key
* @param mixed $value
* @param int $minutes
* @return bool
*/
public function set(string $key, $value, int $minutes = 0): bool
{
return apcu_store($this->key($key), (new Value($value, $minutes))->toJson(), $this->expiration($minutes));
$key = $this->key($key);
$value = (new Value($value, $minutes))->toJson();
$expires = $this->expiration($minutes);
return apcu_store($key, $value, $expires);
}
}
+118 -122
View File
@@ -2,6 +2,8 @@
namespace Kirby\Cache;
use Closure;
/**
* Cache foundation
* This abstract class is used as
@@ -18,14 +20,11 @@ abstract class Cache
{
/**
* Stores all options for the driver
* @var array
*/
protected $options = [];
protected array $options = [];
/**
* Sets all parameters which are needed to connect to the cache storage
*
* @param array $options
*/
public function __construct(array $options = [])
{
@@ -33,87 +32,47 @@ abstract class Cache
}
/**
* Writes an item to the cache for a given number of minutes and
* returns whether the operation was successful;
* this needs to be defined by the driver
*
* <code>
* // put an item in the cache for 15 minutes
* $cache->set('value', 'my value', 15);
* </code>
*
* @param string $key
* @param mixed $value
* @param int $minutes
* @return bool
* Checks when the cache has been created;
* returns the creation timestamp on success
* and false if the item does not exist
*/
abstract public function set(string $key, $value, int $minutes = 0): bool;
/**
* Adds the prefix to the key if given
*
* @param string $key
* @return string
*/
protected function key(string $key): string
public function created(string $key): int|false
{
if (empty($this->options['prefix']) === false) {
$key = $this->options['prefix'] . '/' . $key;
}
return $key;
}
/**
* Internal method to retrieve the raw cache value;
* needs to return a Value object or null if not found;
* this needs to be defined by the driver
*
* @param string $key
* @return \Kirby\Cache\Value|null
*/
abstract public function retrieve(string $key);
/**
* Gets an item from the cache
*
* <code>
* // get an item from the cache driver
* $value = $cache->get('value');
*
* // return a default value if the requested item isn't cached
* $value = $cache->get('value', 'default value');
* </code>
*
* @param string $key
* @param mixed $default
* @return mixed
*/
public function get(string $key, $default = null)
{
// get the Value
// get the Value object
$value = $this->retrieve($key);
// check for a valid cache value
if (!is_a($value, 'Kirby\Cache\Value')) {
return $default;
// check for a valid Value object
if ($value instanceof Value === false) {
return false;
}
// remove the item if it is expired
if ($value->expires() > 0 && time() >= $value->expires()) {
$this->remove($key);
return $default;
// return the expires timestamp
return $value->created();
}
// return the pure value
return $value->value();
/**
* Returns whether the cache is ready to
* store values
*/
public function enabled(): bool
{
// TODO: Make this method abstract in a future
// release to ensure that cache drivers override it;
// until then, we assume that the cache is enabled
return true;
}
/**
* Determines if an item exists in the cache
*/
public function exists(string $key): bool
{
return $this->expired($key) === false;
}
/**
* Calculates the expiration timestamp
*
* @param int $minutes
* @return int
*/
protected function expiration(int $minutes = 0): int
{
@@ -130,17 +89,14 @@ abstract class Cache
* Checks when an item in the cache expires;
* returns the expiry timestamp on success, null if the
* item never expires and false if the item does not exist
*
* @param string $key
* @return int|null|false
*/
public function expires(string $key)
public function expires(string $key): int|false|null
{
// get the Value object
$value = $this->retrieve($key);
// check for a valid Value object
if (!is_a($value, 'Kirby\Cache\Value')) {
if ($value instanceof Value === false) {
return false;
}
@@ -150,9 +106,6 @@ abstract class Cache
/**
* Checks if an item in the cache is expired
*
* @param string $key
* @return bool
*/
public function expired(string $key): bool
{
@@ -160,83 +113,126 @@ abstract class Cache
if ($expires === null) {
return false;
} elseif (!is_int($expires)) {
return true;
} else {
return time() >= $expires;
}
if (is_int($expires) === false) {
return true;
}
return time() >= $expires;
}
/**
* Checks when the cache has been created;
* returns the creation timestamp on success
* and false if the item does not exist
*
* @param string $key
* @return int|false
* Flushes the entire cache and returns
* whether the operation was successful;
* this needs to be defined by the driver
*/
public function created(string $key)
abstract public function flush(): bool;
/**
* Gets an item from the cache
*
* <code>
* // get an item from the cache driver
* $value = $cache->get('value');
*
* // return a default value if the requested item isn't cached
* $value = $cache->get('value', 'default value');
* </code>
*/
public function get(string $key, $default = null)
{
// get the Value object
// get the Value
$value = $this->retrieve($key);
// check for a valid Value object
if (!is_a($value, 'Kirby\Cache\Value')) {
return false;
// check for a valid cache value
if ($value instanceof Value === false) {
return $default;
}
// return the expires timestamp
return $value->created();
// remove the item if it is expired
if ($value->expires() > 0 && time() >= $value->expires()) {
$this->remove($key);
return $default;
}
// return the pure value
return $value->value();
}
/**
* Returns a value by either getting it from the cache
* or via the callback function which then is stored in
* the cache for future retrieval. This method cannot be
* used for `null` as value to be cached.
* @since 3.8.0
*/
public function getOrSet(
string $key,
Closure $result,
int $minutes = 0
) {
$value = $this->get($key);
$result = $value ?? $result();
if ($value === null) {
$this->set($key, $result, $minutes);
}
return $result;
}
/**
* Adds the prefix to the key if given
*/
protected function key(string $key): string
{
if (empty($this->options['prefix']) === false) {
$key = $this->options['prefix'] . '/' . $key;
}
return $key;
}
/**
* Alternate version for Cache::created($key)
*
* @param string $key
* @return int|false
*/
public function modified(string $key)
public function modified(string $key): int|false
{
return static::created($key);
}
/**
* Determines if an item exists in the cache
*
* @param string $key
* @return bool
* Returns all passed cache options
*/
public function exists(string $key): bool
public function options(): array
{
return $this->expired($key) === false;
return $this->options;
}
/**
* Removes an item from the cache and returns
* whether the operation was successful;
* this needs to be defined by the driver
*
* @param string $key
* @return bool
*/
abstract public function remove(string $key): bool;
/**
* Flushes the entire cache and returns
* whether the operation was successful;
* Internal method to retrieve the raw cache value;
* needs to return a Value object or null if not found;
* this needs to be defined by the driver
*
* @return bool
*/
abstract public function flush(): bool;
abstract public function retrieve(string $key): Value|null;
/**
* Returns all passed cache options
* Writes an item to the cache for a given number of minutes and
* returns whether the operation was successful;
* this needs to be defined by the driver
*
* @return array
* <code>
* // put an item in the cache for 15 minutes
* $cache->set('value', 'my value', 15);
* </code>
*/
public function options(): array
{
return $this->options;
}
abstract public function set(string $key, $value, int $minutes = 0): bool;
}
+28 -35
View File
@@ -20,10 +20,8 @@ class FileCache extends Cache
{
/**
* Full root including prefix
*
* @var string
*/
protected $root;
protected string $root;
/**
* Sets all parameters which are needed for the file cache
@@ -44,6 +42,7 @@ class FileCache extends Cache
// build the full root including prefix
$this->root = $this->options['root'];
if (empty($this->options['prefix']) === false) {
$this->root .= '/' . $this->options['prefix'];
}
@@ -52,10 +51,17 @@ class FileCache extends Cache
Dir::make($this->root, true);
}
/**
* Returns whether the cache is ready to
* store values
*/
public function enabled(): bool
{
return is_writable($this->root) === true;
}
/**
* Returns the full root including prefix
*
* @return string
*/
public function root(): string
{
@@ -64,9 +70,6 @@ class FileCache extends Cache
/**
* Returns the full path to a file for a given key
*
* @param string $key
* @return string
*/
protected function file(string $key): string
{
@@ -108,9 +111,9 @@ class FileCache extends Cache
if (isset($this->options['extension'])) {
return $file . '.' . $this->options['extension'];
} else {
return $file;
}
return $file;
}
/**
@@ -121,11 +124,6 @@ class FileCache extends Cache
* // put an item in the cache for 15 minutes
* $cache->set('value', 'my value', 15);
* </code>
*
* @param string $key
* @param mixed $value
* @param int $minutes
* @return bool
*/
public function set(string $key, $value, int $minutes = 0): bool
{
@@ -137,11 +135,8 @@ class FileCache extends Cache
/**
* Internal method to retrieve the raw cache value;
* needs to return a Value object or null if not found
*
* @param string $key
* @return \Kirby\Cache\Value|null
*/
public function retrieve(string $key)
public function retrieve(string $key): Value|null
{
$file = $this->file($key);
$value = F::read($file);
@@ -153,11 +148,8 @@ class FileCache extends Cache
* Checks when the cache has been created;
* returns the creation timestamp on success
* and false if the item does not exist
*
* @param string $key
* @return mixed
*/
public function created(string $key)
public function created(string $key): int|false
{
// use the modification timestamp
// as indicator when the cache has been created/overwritten
@@ -165,15 +157,12 @@ class FileCache extends Cache
// get the file for this cache key
$file = $this->file($key);
return file_exists($file) ? filemtime($this->file($key)) : false;
return file_exists($file) ? filemtime($file) : false;
}
/**
* Removes an item from the cache and returns
* whether the operation was successful
*
* @param string $key
* @return bool
*/
public function remove(string $key): bool
{
@@ -190,9 +179,6 @@ class FileCache extends Cache
/**
* Removes empty directories safely by checking each directory
* up to the root directory
*
* @param string $dir
* @return void
*/
protected function removeEmptyDirectories(string $dir): void
{
@@ -202,7 +188,13 @@ class FileCache extends Cache
// checks all directory segments until reaching the root directory
while (Str::startsWith($dir, $this->root()) === true && $dir !== $this->root()) {
$files = array_diff(scandir($dir) ?? [], ['.', '..']);
$files = scandir($dir);
if ($files === false) {
$files = []; // @codeCoverageIgnore
}
$files = array_diff($files, ['.', '..']);
if (empty($files) === true && Dir::remove($dir) === true) {
// continue with the next level up
@@ -212,7 +204,7 @@ class FileCache extends Cache
break;
}
}
} catch (Exception $e) { // @codeCoverageIgnore
} catch (Exception) { // @codeCoverageIgnore
// silently stops the process
}
}
@@ -220,12 +212,13 @@ class FileCache extends Cache
/**
* Flushes the entire cache and returns
* whether the operation was successful
*
* @return bool
*/
public function flush(): bool
{
if (Dir::remove($this->root) === true && Dir::make($this->root) === true) {
if (
Dir::remove($this->root) === true &&
Dir::make($this->root) === true
) {
return true;
}
+27 -20
View File
@@ -16,10 +16,14 @@ use Memcached as MemcachedExt;
class MemCached extends Cache
{
/**
* store for the memcache connection
* @var \Memcached
* Store for the memcache connection
*/
protected $connection;
protected MemcachedExt $connection;
/**
* Stores whether the connection was successful
*/
protected bool $enabled;
/**
* Sets all parameters which are needed to connect to Memcached
@@ -39,7 +43,19 @@ class MemCached extends Cache
parent::__construct(array_merge($defaults, $options));
$this->connection = new MemcachedExt();
$this->connection->addServer($this->options['host'], $this->options['port']);
$this->enabled = $this->connection->addServer(
$this->options['host'],
$this->options['port']
);
}
/**
* Returns whether the cache is ready to
* store values
*/
public function enabled(): bool
{
return $this->enabled;
}
/**
@@ -50,35 +66,28 @@ class MemCached extends Cache
* // put an item in the cache for 15 minutes
* $cache->set('value', 'my value', 15);
* </code>
*
* @param string $key
* @param mixed $value
* @param int $minutes
* @return bool
*/
public function set(string $key, $value, int $minutes = 0): bool
{
return $this->connection->set($this->key($key), (new Value($value, $minutes))->toJson(), $this->expiration($minutes));
$key = $this->key($key);
$value = (new Value($value, $minutes))->toJson();
$expires = $this->expiration($minutes);
return $this->connection->set($key, $value, $expires);
}
/**
* Internal method to retrieve the raw cache value;
* needs to return a Value object or null if not found
*
* @param string $key
* @return \Kirby\Cache\Value|null
*/
public function retrieve(string $key)
public function retrieve(string $key): Value|null
{
return Value::fromJson($this->connection->get($this->key($key)));
$value = $this->connection->get($this->key($key));
return Value::fromJson($value);
}
/**
* Removes an item from the cache and returns
* whether the operation was successful
*
* @param string $key
* @return bool
*/
public function remove(string $key): bool
{
@@ -89,8 +98,6 @@ class MemCached extends Cache
* Flushes the entire cache and returns
* whether the operation was successful;
* WARNING: Memcached only supports flushing the whole cache at once!
*
* @return bool
*/
public function flush(): bool
{
+13 -18
View File
@@ -15,9 +15,17 @@ class MemoryCache extends Cache
{
/**
* Cache data
* @var array
*/
protected $store = [];
protected array $store = [];
/**
* Returns whether the cache is ready to
* store values
*/
public function enabled(): bool
{
return true;
}
/**
* Writes an item to the cache for a given number of minutes and
@@ -27,11 +35,6 @@ class MemoryCache extends Cache
* // put an item in the cache for 15 minutes
* $cache->set('value', 'my value', 15);
* </code>
*
* @param string $key
* @param mixed $value
* @param int $minutes
* @return bool
*/
public function set(string $key, $value, int $minutes = 0): bool
{
@@ -42,11 +45,8 @@ class MemoryCache extends Cache
/**
* Internal method to retrieve the raw cache value;
* needs to return a Value object or null if not found
*
* @param string $key
* @return \Kirby\Cache\Value|null
*/
public function retrieve(string $key)
public function retrieve(string $key): Value|null
{
return $this->store[$key] ?? null;
}
@@ -54,25 +54,20 @@ class MemoryCache extends Cache
/**
* Removes an item from the cache and returns
* whether the operation was successful
*
* @param string $key
* @return bool
*/
public function remove(string $key): bool
{
if (isset($this->store[$key])) {
unset($this->store[$key]);
return true;
} else {
return false;
}
return false;
}
/**
* Flushes the entire cache and returns
* whether the operation was successful
*
* @return bool
*/
public function flush(): bool
{
+10 -14
View File
@@ -13,6 +13,15 @@ namespace Kirby\Cache;
*/
class NullCache extends Cache
{
/**
* Returns whether the cache is ready to
* store values
*/
public function enabled(): bool
{
return false;
}
/**
* Writes an item to the cache for a given number of minutes and
* returns whether the operation was successful
@@ -21,11 +30,6 @@ class NullCache extends Cache
* // put an item in the cache for 15 minutes
* $cache->set('value', 'my value', 15);
* </code>
*
* @param string $key
* @param mixed $value
* @param int $minutes
* @return bool
*/
public function set(string $key, $value, int $minutes = 0): bool
{
@@ -35,11 +39,8 @@ class NullCache extends Cache
/**
* Internal method to retrieve the raw cache value;
* needs to return a Value object or null if not found
*
* @param string $key
* @return \Kirby\Cache\Value|null
*/
public function retrieve(string $key)
public function retrieve(string $key): Value|null
{
return null;
}
@@ -47,9 +48,6 @@ class NullCache extends Cache
/**
* Removes an item from the cache and returns
* whether the operation was successful
*
* @param string $key
* @return bool
*/
public function remove(string $key): bool
{
@@ -59,8 +57,6 @@ class NullCache extends Cache
/**
* Flushes the entire cache and returns
* whether the operation was successful
*
* @return bool
*/
public function flush(): bool
{
+16 -32
View File
@@ -19,7 +19,6 @@ class Value
{
/**
* Cached value
* @var mixed
*/
protected $value;
@@ -27,35 +26,30 @@ class Value
* the number of minutes until the value expires
* @todo Rename this property to $expiry to reflect
* both minutes and absolute timestamps
* @var int
*/
protected $minutes;
protected int $minutes;
/**
* Creation timestamp
* @var int
*/
protected $created;
protected int $created;
/**
* Constructor
*
* @param mixed $value
* @param int $minutes the number of minutes until the value expires
* or an absolute UNIX timestamp
* @param int $created the UNIX timestamp when the value has been created
*/
public function __construct($value, int $minutes = 0, int $created = null)
public function __construct($value, int $minutes = 0, int|null $created = null)
{
$this->value = $value;
$this->minutes = $minutes ?? 0;
$this->minutes = $minutes;
$this->created = $created ?? time();
}
/**
* Returns the creation date as UNIX timestamp
*
* @return int
*/
public function created(): int
{
@@ -65,10 +59,8 @@ class Value
/**
* Returns the expiration date as UNIX timestamp or
* null if the value never expires
*
* @return int|null
*/
public function expires(): ?int
public function expires(): int|null
{
// 0 = keep forever
if ($this->minutes === 0) {
@@ -85,41 +77,37 @@ class Value
/**
* Creates a value object from an array
*
* @param array $array
* @return static
*/
public static function fromArray(array $array)
public static function fromArray(array $array): static
{
return new static($array['value'] ?? null, $array['minutes'] ?? 0, $array['created'] ?? null);
return new static(
$array['value'] ?? null,
$array['minutes'] ?? 0,
$array['created'] ?? null
);
}
/**
* Creates a value object from a JSON string;
* returns null on error
*
* @param string $json
* @return static|null
*/
public static function fromJson(string $json)
public static function fromJson(string $json): static|null
{
try {
$array = json_decode($json, true);
if (is_array($array)) {
if (is_array($array) === true) {
return static::fromArray($array);
} else {
return null;
}
} catch (Throwable $e) {
return null;
} catch (Throwable) {
return null;
}
}
/**
* Converts the object to a JSON string
*
* @return string
*/
public function toJson(): string
{
@@ -128,8 +116,6 @@ class Value
/**
* Converts the object to an array
*
* @return array
*/
public function toArray(): array
{
@@ -142,8 +128,6 @@ class Value
/**
* Returns the pure value
*
* @return mixed
*/
public function value()
{
+30 -65
View File
@@ -5,6 +5,7 @@ namespace Kirby\Cms;
use Kirby\Api\Api as BaseApi;
use Kirby\Exception\NotFoundException;
use Kirby\Form\Form;
use Kirby\Session\Session;
/**
* Api
@@ -25,38 +26,30 @@ class Api extends BaseApi
/**
* Execute an API call for the given path,
* request method and optional request data
*
* @param string|null $path
* @param string $method
* @param array $requestData
* @return mixed
*/
public function call(string $path = null, string $method = 'GET', array $requestData = [])
{
public function call(
string|null $path = null,
string $method = 'GET',
array $requestData = []
) {
$this->setRequestMethod($method);
$this->setRequestData($requestData);
$this->kirby->setCurrentLanguage($this->language());
$allowImpersonation = $this->kirby()->option('api.allowImpersonation', false);
if ($user = $this->kirby->user(null, $allowImpersonation)) {
$translation = $user->language();
} else {
$translation = $this->kirby->panelLanguage();
}
$translation = $this->kirby->user(null, $allowImpersonation)?->language();
$translation ??= $this->kirby->panelLanguage();
$this->kirby->setCurrentTranslation($translation);
return parent::call($path, $method, $requestData);
}
/**
* @param mixed $model
* @param string $name
* @param string|null $path
* @return mixed
* @throws \Kirby\Exception\NotFoundException if the field type cannot be found or the field cannot be loaded
*/
public function fieldApi($model, string $name, string $path = null)
public function fieldApi($model, string $name, string|null $path = null)
{
$field = Form::for($model)->field($name);
@@ -75,11 +68,9 @@ class Api extends BaseApi
* parent path and filename
*
* @param string|null $path Path to file's parent model
* @param string $filename Filename
* @return \Kirby\Cms\File|null
* @throws \Kirby\Exception\NotFoundException if the file cannot be found
*/
public function file(string $path = null, string $filename)
public function file(string|null $path = null, string $filename): File|null
{
return Find::file($path, $filename);
}
@@ -88,31 +79,26 @@ class Api extends BaseApi
* Returns the model's object for the given path
*
* @param string $path Path to parent model
* @return \Kirby\Cms\Model|null
* @throws \Kirby\Exception\InvalidArgumentException if the model type is invalid
* @throws \Kirby\Exception\NotFoundException if the model cannot be found
*/
public function parent(string $path)
public function parent(string $path): Model|null
{
return Find::parent($path);
}
/**
* Returns the Kirby instance
*
* @return \Kirby\Cms\App
*/
public function kirby()
public function kirby(): App
{
return $this->kirby;
}
/**
* Returns the language request header
*
* @return string|null
*/
public function language(): ?string
public function language(): string|null
{
return $this->requestQuery('language') ?? $this->requestHeaders('x-language');
}
@@ -121,10 +107,9 @@ class Api extends BaseApi
* Returns the page object for the given id
*
* @param string $id Page's id
* @return \Kirby\Cms\Page|null
* @throws \Kirby\Exception\NotFoundException if the page cannot be found
*/
public function page(string $id)
public function page(string $id): Page|null
{
return Find::page($id);
}
@@ -133,39 +118,26 @@ class Api extends BaseApi
* Returns the subpages for the given
* parent. The subpages can be filtered
* by status (draft, listed, unlisted, published, all)
*
* @param string|null $parentId
* @param string|null $status
* @return \Kirby\Cms\Pages
*/
public function pages(string $parentId = null, string $status = null)
public function pages(string|null $parentId = null, string|null $status = null): Pages
{
$parent = $parentId === null ? $this->site() : $this->page($parentId);
switch ($status) {
case 'all':
return $parent->childrenAndDrafts();
case 'draft':
case 'drafts':
return $parent->drafts();
case 'listed':
return $parent->children()->listed();
case 'unlisted':
return $parent->children()->unlisted();
case 'published':
default:
return $parent->children();
}
return match ($status) {
'all' => $parent->childrenAndDrafts(),
'draft', 'drafts' => $parent->drafts(),
'listed' => $parent->children()->listed(),
'unlisted' => $parent->children()->unlisted(),
'published' => $parent->children(),
default => $parent->children()
};
}
/**
* Search for direct subpages of the
* given parent
*
* @param string|null $parent
* @return \Kirby\Cms\Pages
*/
public function searchPages(string $parent = null)
public function searchPages(string|null $parent = null): Pages
{
$pages = $this->pages($parent, $this->requestQuery('status'));
@@ -180,9 +152,8 @@ class Api extends BaseApi
* Returns the current Session instance
*
* @param array $options Additional options, see the session component
* @return \Kirby\Session\Session
*/
public function session(array $options = [])
public function session(array $options = []): Session
{
return $this->kirby->session(array_merge([
'detect' => true
@@ -192,10 +163,9 @@ class Api extends BaseApi
/**
* Setter for the parent Kirby instance
*
* @param \Kirby\Cms\App $kirby
* @return $this
*/
protected function setKirby(App $kirby)
protected function setKirby(App $kirby): static
{
$this->kirby = $kirby;
return $this;
@@ -203,10 +173,8 @@ class Api extends BaseApi
/**
* Returns the site object
*
* @return \Kirby\Cms\Site
*/
public function site()
public function site(): Site
{
return $this->kirby->site();
}
@@ -217,10 +185,9 @@ class Api extends BaseApi
* id is passed
*
* @param string|null $id User's id
* @return \Kirby\Cms\User|null
* @throws \Kirby\Exception\NotFoundException if the user for the given id cannot be found
*/
public function user(string $id = null)
public function user(string|null $id = null): User|null
{
try {
return Find::user($id);
@@ -235,10 +202,8 @@ class Api extends BaseApi
/**
* Returns the users collection
*
* @return \Kirby\Cms\Users
*/
public function users()
public function users(): Users
{
return $this->kirby->users();
}
+97 -106
View File
@@ -2,8 +2,10 @@
namespace Kirby\Cms;
use Closure;
use Kirby\Data\Data;
use Kirby\Exception\ErrorPageException;
use Kirby\Exception\Exception;
use Kirby\Exception\InvalidArgumentException;
use Kirby\Exception\LogicException;
use Kirby\Exception\NotFoundException;
@@ -23,6 +25,7 @@ use Kirby\Toolkit\Config;
use Kirby\Toolkit\Controller;
use Kirby\Toolkit\Properties;
use Kirby\Toolkit\Str;
use Kirby\Uuid\Uuid;
use Throwable;
/**
@@ -435,7 +438,7 @@ class App
$salt = $this->option('content.salt', $default);
if (is_a($salt, 'Closure') === true) {
if ($salt instanceof Closure) {
$salt = $salt($model);
}
@@ -496,7 +499,11 @@ class App
// registry controller
if ($controller = $this->extension('controllers', $name)) {
return is_a($controller, 'Kirby\Toolkit\Controller') ? $controller : new Controller($controller);
if ($controller instanceof Controller) {
return $controller;
}
return new Controller($controller);
}
return null;
@@ -520,7 +527,7 @@ class App
* @param string|null $check Pass a token here to compare it to the one in the session
* @return string|bool Either the token or a boolean check result
*/
public function csrf(?string $check = null)
public function csrf(string|null $check = null)
{
$session = $this->session();
@@ -633,28 +640,26 @@ class App
*/
public function file(string $path, $parent = null, bool $drafts = true)
{
// find by global UUID
if (Uuid::is($path, 'file') === true) {
// prefer files of parent, when parent given
return Uuid::for($path, $parent?->files())->model();
}
$parent = $parent ?? $this->site();
$id = dirname($path);
$filename = basename($path);
if (is_a($parent, 'Kirby\Cms\User') === true) {
if ($parent instanceof User) {
return $parent->file($filename);
}
if (is_a($parent, 'Kirby\Cms\File') === true) {
if ($parent instanceof File) {
$parent = $parent->parent();
}
if ($id === '.') {
if ($file = $parent->file($filename)) {
return $file;
}
if ($file = $this->site()->file($filename)) {
return $file;
}
return null;
return $parent->file($filename) ?? $this->site()->file($filename);
}
if ($page = $this->page($id, $parent, $drafts)) {
@@ -680,7 +685,7 @@ class App
*
* @todo merge with App::file()
*/
public function image(?string $path = null)
public function image(string|null $path = null)
{
if ($path === null) {
return $this->site()->page()->image();
@@ -693,23 +698,13 @@ class App
$uri = null;
}
switch ($uri) {
case '/':
$parent = $this->site();
break;
case null:
$parent = $this->site()->page();
break;
default:
$parent = $this->site()->page($uri);
break;
}
$parent = match ($uri) {
'/' => $this->site(),
null => $this->site()->page(),
default => $this->site()->page($uri)
};
if ($parent) {
return $parent->image($filename);
}
return null;
return $parent?->image($filename);
}
/**
@@ -718,18 +713,19 @@ class App
* @param \Kirby\Cms\App|null $instance
* @param bool $lazy If `true`, the instance is only returned if already existing
* @return static|null
* @psalm-return ($lazy is false ? static : static|null)
*/
public static function instance(self $instance = null, bool $lazy = false)
{
if ($instance === null) {
if ($lazy === true) {
return static::$instance;
} else {
return static::$instance ?? new static();
}
if ($instance !== null) {
return static::$instance = $instance;
}
return static::$instance = $instance;
if ($lazy === true) {
return static::$instance;
}
return static::$instance ?? new static();
}
/**
@@ -746,8 +742,8 @@ class App
$response = $this->response();
// any direct exception will be turned into an error page
if (is_a($input, 'Throwable') === true) {
if (is_a($input, 'Kirby\Exception\Exception') === true) {
if ($input instanceof Throwable) {
if ($input instanceof Exception) {
$code = $input->getHttpCode();
} else {
$code = $input->getCode();
@@ -778,7 +774,7 @@ class App
}
// (Modified) global response configuration, e.g. in routes
if (is_a($input, 'Kirby\Cms\Responder') === true) {
if ($input instanceof Responder) {
// return the passed object unmodified (without injecting headers
// from the global object) to allow a complete response override
// https://github.com/getkirby/kirby/pull/4144#issuecomment-1034766726
@@ -786,37 +782,41 @@ class App
}
// Responses
if (is_a($input, 'Kirby\Http\Response') === true) {
if ($input instanceof Response) {
$data = $input->toArray();
// inject headers from the global response configuration
// lazily (only if they are not already set);
// the case-insensitive nature of headers will be
// handled by PHP's `header()` function
$data['headers'] = array_merge($response->headers(), $data['headers']);
$data['headers'] = array_merge(
$response->headers(),
$data['headers']
);
return new Response($data);
}
// Pages
if (is_a($input, 'Kirby\Cms\Page')) {
if ($input instanceof Page) {
try {
$html = $input->render();
} catch (ErrorPageException $e) {
return $this->io($e);
}
if ($input->isErrorPage() === true) {
if ($response->code() === null) {
if (
$input->isErrorPage() === true &&
$response->code() === null
) {
$response->code(404);
}
}
return $response->send($html);
}
// Files
if (is_a($input, 'Kirby\Cms\File')) {
if ($input instanceof File) {
return $response->redirect($input->mediaUrl(), 307)->send();
}
@@ -844,7 +844,7 @@ class App
* @param array $data
* @return string
*/
public function kirbytag($type, ?string $value = null, array $attr = [], array $data = []): string
public function kirbytag($type, string|null $value = null, array $attr = [], array $data = []): string
{
if (is_array($type) === true) {
$kirbytag = $type;
@@ -895,24 +895,13 @@ class App
* @internal
* @param string|null $text
* @param array $options
* @param bool $inline (deprecated: use $options['markdown']['inline'] instead)
* @return string
* @todo remove $inline parameter in in 3.8.0
*/
public function kirbytext(string $text = null, array $options = [], bool $inline = false): string
public function kirbytext(string $text = null, array $options = []): string
{
// warning for deprecated fourth parameter
// @codeCoverageIgnoreStart
if (func_num_args() === 3) {
Helpers::deprecated('Cms\App::kirbytext(): the $inline parameter is deprecated and will be removed in Kirby 3.8.0. Use $options[\'markdown\'][\'inline\'] instead.');
}
// @codeCoverageIgnoreEnd
$options['markdown']['inline'] ??= $inline;
$text = $this->apply('kirbytext:before', compact('text'), 'text');
$text = $this->kirbytags($text, $options);
$text = $this->markdown($text, $options['markdown']);
$text = $this->markdown($text, $options['markdown'] ?? []);
if ($this->option('smartypants', false) !== false) {
$text = $this->smartypants($text);
@@ -953,22 +942,15 @@ class App
* @param string|null $languageCode
* @return string|null
*/
public function languageCode(string $languageCode = null): ?string
public function languageCode(string $languageCode = null): string|null
{
if ($language = $this->language($languageCode)) {
return $language->code();
}
return null;
return $this->language($languageCode)?->code();
}
/**
* Returns all available site languages
*
* @param bool
* @return \Kirby\Cms\Languages
*/
public function languages(bool $clone = true)
public function languages(bool $clone = true): Languages
{
if ($this->languages !== null) {
return $clone === true ? clone $this->languages : $this->languages;
@@ -1006,34 +988,18 @@ class App
*
* @internal
* @param string|null $text
* @param bool|array $options Boolean inline value is deprecated, use `['inline' => true]` instead
* @param array $options
* @return string
* @todo remove boolean $options in in 3.8.0
*/
public function markdown(string $text = null, $options = null): string
public function markdown(string $text = null, array $options = null): string
{
// support for the old syntax to enable inline mode as second argument
// @codeCoverageIgnoreStart
if (is_bool($options) === true) {
Helpers::deprecated('Cms\App::markdown(): Passing a boolean as second parameter has been deprecated and won\'t be supported anymore in Kirby 3.8.0. Instead pass array with the key "inline" set to true or false.');
$options = [
'inline' => $options
];
}
// @codeCoverageIgnoreEnd
// merge global options with local options
$options = array_merge(
$this->options['markdown'] ?? [],
(array)$options
);
// TODO: remove passing the $inline parameter in 3.8.0
// $options['inline'] is set to `false` to avoid the deprecation
// warning in the component; this can also be removed in 3.8.0
$inline = $options['inline'] ??= false;
return ($this->component('markdown'))($this, $text, $options, $inline);
return ($this->component('markdown'))($this, $text, $options);
}
/**
@@ -1111,19 +1077,27 @@ class App
*/
protected function optionsFromEnvironment(array $props = []): array
{
$globalUrl = $this->options['url'] ?? null;
$root = $this->root('config');
// create the environment based on the URL setup
// first load `config/env.php` to access its `url` option
$envOptions = F::load($root . '/env.php', []);
// use the option from the main `config.php`,
// but allow the `env.php` to override it
$globalUrl = $envOptions['url'] ?? $this->options['url'] ?? null;
// create the URL setup based on hostname and server IP address
$this->environment = new Environment([
'allowed' => $globalUrl,
'cli' => $props['cli'] ?? null,
], $props['server'] ?? null);
// merge into one clean options array
$options = $this->environment()->options($this->root('config'));
$this->options = array_replace_recursive($this->options, $options);
// merge into one clean options array;
// the `env.php` options always override everything else
$hostAddrOptions = $this->environment()->options($root);
$this->options = array_replace_recursive($this->options, $hostAddrOptions, $envOptions);
// reload the environment if the environment config has overridden
// reload the environment if the host/address config has overridden
// the `url` option; this ensures that the base URL is correct
$envUrl = $this->options['url'] ?? null;
if ($envUrl !== $globalUrl) {
@@ -1201,12 +1175,17 @@ class App
* @param bool $drafts
* @return \Kirby\Cms\Page|null
*/
public function page(?string $id = null, $parent = null, bool $drafts = true)
public function page(string|null $id = null, $parent = null, bool $drafts = true)
{
if ($id === null) {
return null;
}
// find by global UUID
if (Uuid::is($id, 'page') === true) {
return Uuid::for($id, $parent?->childrenAndDrafts())->model();
}
$parent = $parent ?? $this->site();
if ($page = $parent->find($id)) {
@@ -1252,6 +1231,10 @@ class App
*/
public function render(string $path = null, string $method = null)
{
if (($_ENV['KIRBY_RENDER'] ?? true) === false) {
return null;
}
return $this->io($this->call($path, $method));
}
@@ -1308,7 +1291,10 @@ class App
// search for a draft if the page cannot be found
if (!$page && $draft = $site->draft($path)) {
if ($this->user() || $draft->isVerified($this->request()->get('token'))) {
if (
$this->user() ||
$draft->isVerified($this->request()->get('token'))
) {
$page = $draft;
}
}
@@ -1335,7 +1321,7 @@ class App
}
return $response->body($output);
} catch (NotFoundException $e) {
} catch (NotFoundException) {
return null;
}
}
@@ -1378,7 +1364,7 @@ class App
* @param string $type
* @return string|null
*/
public function root(string $type = 'index'): ?string
public function root(string $type = 'index'): string|null
{
return $this->roots->__get($type);
}
@@ -1572,12 +1558,16 @@ class App
* @deprecated 3.7.0 Use `$kirby->environment()` instead
*
* @return \Kirby\Http\Environment
* @todo Start throwing deprecation warnings in 3.8.0
* @deprecated Will be removed in Kirby 3.9.0
* @todo Remove in 3.9.0
* @codeCoverageIgnore
*/
public function server()
{
// @codeCoverageIgnoreStart
Helpers::deprecated('$kirby->server() has been deprecated and will be removed in Kirby 3.9.0. Use $kirby->environment() instead.');
// @codeCoverageIgnoreEnd
return $this->environment();
}
@@ -1628,13 +1618,13 @@ class App
* Uses the snippet component to create
* and return a template snippet
*
* @internal
* @param mixed $name
* @param array|object $data Variables or an object that becomes `$item`
* @param bool $return On `false`, directly echo the snippet
* @return string|null
* @psalm-return ($return is true ? string : null)
*/
public function snippet($name, $data = [], bool $return = true): ?string
public function snippet($name, $data = [], bool $return = true): string|null
{
if (is_object($data) === true) {
$data = ['item' => $data];
@@ -1740,6 +1730,7 @@ class App
* @param string $type
* @param bool $object If set to `true`, the URL is converted to an object
* @return string|\Kirby\Http\Uri|null
* @psalm-return ($object is false ? string|null : \Kirby\Http\Uri)
*/
public function url(string $type = 'index', bool $object = false)
{
@@ -1777,11 +1768,11 @@ class App
* @return string|null
* @throws \Kirby\Exception\LogicException if the Kirby version cannot be detected
*/
public static function version(): ?string
public static function version(): string|null
{
try {
return static::$version = static::$version ?? Data::read(dirname(__DIR__, 2) . '/composer.json')['version'] ?? null;
} catch (Throwable $e) {
} catch (Throwable) {
throw new LogicException('The Kirby version cannot be detected. The composer.json is probably missing or not readable.');
}
}
+6 -4
View File
@@ -2,6 +2,7 @@
namespace Kirby\Cms;
use Kirby\Cache\Cache;
use Kirby\Cache\NullCache;
use Kirby\Exception\InvalidArgumentException;
@@ -54,7 +55,7 @@ trait AppCaches
$cache = new $className($options);
// check if it is a usable cache object
if (is_a($cache, 'Kirby\Cache\Cache') !== true) {
if ($cache instanceof Cache === false) {
throw new InvalidArgumentException([
'key' => 'app.invalid.cacheType',
'data' => ['type' => $type]
@@ -72,7 +73,8 @@ trait AppCaches
*/
protected function cacheOptions(string $key): array
{
$options = $this->option($this->cacheOptionsKey($key), false);
$options = $this->option($this->cacheOptionsKey($key), null);
$options ??= $this->core()->caches()[$key] ?? false;
if ($options === false) {
return [
@@ -94,9 +96,9 @@ trait AppCaches
if ($options === true) {
return $defaults;
} else {
return array_merge($defaults, $options);
}
return array_merge($defaults, $options);
}
/**
+6 -3
View File
@@ -2,9 +2,12 @@
namespace Kirby\Cms;
use Closure;
use Kirby\Exception\Exception;
use Kirby\Filesystem\F;
use Kirby\Http\Response;
use Kirby\Toolkit\I18n;
use Throwable;
use Whoops\Handler\CallbackHandler;
use Whoops\Handler\Handler;
use Whoops\Handler\PlainTextHandler;
@@ -84,7 +87,7 @@ trait AppErrors
$handler = new CallbackHandler(function ($exception, $inspector, $run) {
$fatal = $this->option('fatal');
if (is_a($fatal, 'Closure') === true) {
if ($fatal instanceof Closure) {
echo $fatal($this, $exception);
} else {
include $this->root('kirby') . '/views/fatal.php';
@@ -109,11 +112,11 @@ trait AppErrors
protected function handleJsonErrors(): void
{
$handler = new CallbackHandler(function ($exception, $inspector, $run) {
if (is_a($exception, 'Kirby\Exception\Exception') === true) {
if ($exception instanceof Exception) {
$httpCode = $exception->getHttpCode();
$code = $exception->getCode();
$details = $exception->getDetails();
} elseif (is_a($exception, '\Throwable') === true) {
} elseif ($exception instanceof Throwable) {
$httpCode = 500;
$code = $exception->getCode();
$details = null;

Some files were not shown because too many files have changed in this diff Show More