Upgrade to 3.7.1

This commit is contained in:
Bastian Allgeier
2022-07-12 13:33:21 +02:00
parent 7931eb5e47
commit 1ad1eaf387
377 changed files with 63981 additions and 63824 deletions

View File

@@ -6,10 +6,19 @@
root = true
[*.php]
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = tab
indent_size = 2
trim_trailing_whitespace = true
indent_style = space
[*.php]
indent_size = 4
insert_final_newline = true
[*.yml]
indent_style = space
[*.md]
trim_trailing_whitespace = false

View File

@@ -3,7 +3,7 @@
"description": "The Kirby 3 core",
"license": "proprietary",
"type": "kirby-cms",
"version": "3.7.0.2",
"version": "3.7.1",
"keywords": [
"kirby",
"cms",

2
kirby/composer.lock generated
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": "538cd92719a152cbecaaaec5cde21f03",
"content-hash": "1d71d8053b544a0d3380bc67234ff81d",
"packages": [
{
"name": "claviska/simpleimage",

View File

@@ -177,7 +177,7 @@
"error.user.duplicate": "Пользователь с Email \"{email}\" уже есть",
"error.user.email.invalid": "Пожалуйста, введите правильный адрес эл. почты",
"error.user.language.invalid": "Введите правильный язык",
"error.user.notFound": "\u0410\u043a\u043a\u0430\u0443\u043d\u0442 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d",
"error.user.notFound": "Пользователь \"{name}\" не найден",
"error.user.password.invalid": "Пожалуйста, введите правильный пароль. Он должен состоять минимум из 8 символов.",
"error.user.password.notSame": "\u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0435 \u043f\u0430\u0440\u043e\u043b\u044c",
"error.user.password.undefined": "У пользователя нет пароля",
@@ -238,11 +238,11 @@
"field.blocks.delete.confirm": "Вы действительно хотите удалить этот блок?",
"field.blocks.delete.confirm.all": "Вы действительно хотите удалить все блоки?",
"field.blocks.delete.confirm.selected": "Вы действительно хотите удалить эти блоки?",
"field.blocks.empty": "Еще нет блоков",
"field.blocks.empty": "Блоков нет",
"field.blocks.fieldsets.label": "Пожалуйста, выберите тип блока…",
"field.blocks.fieldsets.paste": "Нажмите <kbd>{{ shortcut }}</kbd> чтобы вставить/импортировать блоки из буфера памяти",
"field.blocks.gallery.name": "Галерея",
"field.blocks.gallery.images.empty": "Еще нет изображений",
"field.blocks.gallery.images.empty": "Изображений нет",
"field.blocks.gallery.images.label": "Изображения",
"field.blocks.heading.level": "Уровень",
"field.blocks.heading.name": "Заголовок",
@@ -275,17 +275,17 @@
"field.blocks.video.url.label": "Ссылка на видео",
"field.blocks.video.url.placeholder": "https://youtube.com/?v=",
"field.files.empty": "Еще не выбраны файлы",
"field.files.empty": "Файлы не выбраны",
"field.layout.delete": "Удалить разметку",
"field.layout.delete.confirm": "Вы действительно хотите удалить эту разметку?",
"field.layout.empty": "Еще нет строк",
"field.layout.empty": "Строк нет",
"field.layout.select": "Выберите разметку",
"field.pages.empty": "Еще не выбраны страницы",
"field.pages.empty": "Страницы не выбраны",
"field.structure.delete.confirm": "Вы точно хотите удалить эту запись?",
"field.structure.empty": "Еще нет записей",
"field.users.empty": "Еще нет пользователей",
"field.structure.empty": "Записей нет",
"field.users.empty": "Пользователей нет",
"file.blueprint": "У файла пока нет разметки. Вы можете определить новые секции и поля разметки в <strong>/site/blueprints/files/{blueprint}.yml</strong>",
"file.delete.confirm": "Вы точно хотите удалить файл <br><strong>{filename}</strong>?",
@@ -297,7 +297,7 @@
"hide": "Скрыть",
"hour": "Час",
"import": "Импортировать",
"info": "Info",
"info": "Информация",
"insert": "\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c",
"insert.after": "Вставить ниже",
"insert.before": "Вставить выше",
@@ -333,14 +333,14 @@
"languages": "Языки",
"languages.default": "Главный язык",
"languages.empty": "Еще нет языков",
"languages.empty": "Языков нет",
"languages.secondary": "Дополнительные языки",
"languages.secondary.empty": "Еще нет дополнительных языков",
"languages.secondary.empty": "Дополнительных языков нет",
"license": "Лицензия",
"license.buy": "Купить лицензию",
"license.register": "Зарегистрировать",
"license.manage": "Manage your licenses",
"license.manage": "Управление лицензиями",
"license.register.help": "После покупки вы получили по эл. почте код лицензии. Пожалуйста скопируйте и вставьте сюда чтобы зарегистрировать.",
"license.register.label": "Пожалуйста вставьте код лицензии",
"license.register.success": "Спасибо за поддержку Kirby",
@@ -353,7 +353,7 @@
"loading": "Загрузка",
"lock.unsaved": "Несохраненные изменения",
"lock.unsaved.empty": "Больше нет несохраненных изменений",
"lock.unsaved.empty": "Несохраненных изменений больше нет",
"lock.isLocked": "Несохраненные изменения пользователя <strong>{email}</strong>",
"lock.file.isLocked": "В данный момент этот файл редактирует {email}, поэтому его нельзя изменить.",
"lock.page.isLocked": "В данный момент эту страницу редактирует {email}, поэтому его нельзя изменить.",
@@ -406,7 +406,7 @@
"open": "Открыть",
"open.newWindow": "Открывать в новом окне",
"options": "Опции",
"options.none": "Нет параметров",
"options.none": "Параметров нет",
"orientation": "Ориентация",
"orientation.landscape": "Горизонтальная",
@@ -424,7 +424,7 @@
"page.delete.confirm.subpages": "<strong>У этой страницы есть внутренние страницы</strong>.<br>Все внутренние страницы так же будут удалены.",
"page.delete.confirm.title": "Напишите название страницы, чтобы подтвердить",
"page.draft.create": "Создать черновик",
"page.duplicate.appendix": "Скопировать",
"page.duplicate.appendix": "(копия)",
"page.duplicate.files": "Копировать файлы",
"page.duplicate.pages": "Копировать страницы",
"page.sort": "Изменить позицию",
@@ -437,7 +437,7 @@
"page.status.unlisted.description": "Страница доступна только по URL",
"pages": "Страницы",
"pages.empty": "Еще нет страниц",
"pages.empty": "Страниц нет",
"pages.status.draft": "Черновики",
"pages.status.listed": "Опубликовано",
"pages.status.unlisted": "Скрытая",
@@ -462,7 +462,7 @@
"role.admin.description": "Администратор имеет все права",
"role.admin.title": "Администратор",
"role.all": "Все",
"role.empty": "Нет пользователей с такой ролью",
"role.empty": "Пользователей с такой ролью нет",
"role.description.placeholder": "Без описания",
"role.nobody.description": "Эта роль применяется если у пользователя нет никаких прав",
"role.nobody.title": "Никто",
@@ -485,7 +485,7 @@
"slug": "Понятная ссылка",
"sort": "Сортировать",
"stats.empty": "Нет уведомлений",
"stats.empty": "Статистики нет",
"system.issues.content": "Похоже, к папке content есть несанкционированный доступ",
"system.issues.debug": "Включен режим отладки (debugging). Используйте его только при разработке.",
"system.issues.git": "Похоже, к папке .git есть несанкционированный доступ",
@@ -524,9 +524,9 @@
"translation.locale": "ru_RU",
"upload": "Закачать",
"upload.error.cantMove": "Загруженный файл не может быть перемещен",
"upload.error.cantMove": "Не удается переместить загруженный файл",
"upload.error.cantWrite": "Не получилось записать файл на диск",
"upload.error.default": "Не получилось загрузить файл",
"upload.error.default": "Не удалось загрузить файл",
"upload.error.extension": "Загрузка файла не удалась из за расширения",
"upload.error.formSize": "Загруженный файл больше чем MAX_FILE_SIZE настройка в форме",
"upload.error.iniPostSize": "Загружаемый файл больше чем post_max_size настройка в php.ini",

11
kirby/panel/cypress.config.js Executable file
View File

@@ -0,0 +1,11 @@
const { defineConfig } = require("cypress");
module.exports = defineConfig({
video: false,
e2e: {
baseUrl: "http://sandbox.test",
specPattern: "src/**/*.e2e.js",
supportFile: false
}
});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1112,15 +1112,29 @@ class App
*/
protected function optionsFromEnvironment(array $props = []): array
{
$globalUrl = $this->options['url'] ?? null;
// create the environment based on the URL setup
$this->environment = new Environment([
'allowed' => $this->options['url'] ?? null,
'allowed' => $globalUrl,
'cli' => $props['cli'] ?? null,
], $props['server'] ?? null);
// merge into one clean options array
$options = $this->environment()->options($this->root('config'));
return $this->options = array_replace_recursive($this->options, $options);
$this->options = array_replace_recursive($this->options, $options);
// reload the environment if the environment config has overridden
// the `url` option; this ensures that the base URL is correct
$envUrl = $this->options['url'] ?? null;
if ($envUrl !== $globalUrl) {
$this->environment->detect([
'allowed' => $envUrl,
'cli' => $props['cli'] ?? null
], $props['server'] ?? null);
}
return $this->options;
}
/**

View File

@@ -886,13 +886,26 @@ trait AppPlugins
}
$dir = $root . '/' . $dirname;
$entry = $dir . '/index.php';
if (is_dir($dir) !== true || is_file($entry) !== true) {
if (is_dir($dir) !== true) {
continue;
}
$entry = $dir . '/index.php';
$script = $dir . '/index.js';
$styles = $dir . '/index.css';
if (is_file($entry) === true) {
F::loadOnce($entry);
} elseif (is_file($script) === true || is_file($styles) === true) {
// if no PHP file is present but an index.js or index.css,
// register as anonymous plugin (without actual extensions)
// to be picked up by the Panel\Document class when
// rendering the Panel view
static::plugin('plugins/' . $dirname, ['root' => $dir]);
} else {
continue;
}
$loaded[] = $dir;
}

View File

@@ -255,7 +255,11 @@ class Block extends Item
$kirby = $this->parent()->kirby();
return (string)$kirby->snippet('blocks/' . $this->type(), $this->controller(), true);
} catch (Throwable $e) {
if ($kirby->option('debug') === true) {
return '<p>Block error: "' . $e->getMessage() . '" in block type: "' . $this->type() . '"</p>';
}
return '';
}
}
}

View File

@@ -71,8 +71,9 @@ class Collection extends BaseCollection
*
* @param string $id
* @param object $object
* @return void
*/
public function __set(string $id, $object)
public function __set(string $id, $object): void
{
$this->data[$id] = $object;
}

View File

@@ -40,9 +40,11 @@ class Structure extends Collection
*
* @param string $id
* @param array|StructureObject $props
* @return void
*
* @throws \Kirby\Exception\InvalidArgumentException
*/
public function __set(string $id, $props)
public function __set(string $id, $props): void
{
if (is_a($props, 'Kirby\Cms\StructureObject') === true) {
$object = $props;
@@ -59,6 +61,6 @@ class Structure extends Collection
]);
}
return parent::__set($object->id(), $object);
parent::__set($object->id(), $object);
}
}

View File

@@ -146,7 +146,8 @@ abstract class Sql
'varchar' => '{{ name }} varchar(255) {{ null }} {{ default }} {{ unique }}',
'text' => '{{ name }} TEXT {{ unique }}',
'int' => '{{ name }} INT(11) UNSIGNED {{ null }} {{ default }} {{ unique }}',
'timestamp' => '{{ name }} TIMESTAMP {{ null }} {{ default }} {{ unique }}'
'timestamp' => '{{ name }} TIMESTAMP {{ null }} {{ default }} {{ unique }}',
'bool' => '{{ name }} TINYINT(1) {{ null }} {{ default }} {{ unique }}'
];
}

View File

@@ -44,7 +44,8 @@ class Sqlite extends Sql
'varchar' => '{{ name }} TEXT {{ null }} {{ default }} {{ unique }}',
'text' => '{{ name }} TEXT {{ null }} {{ default }} {{ unique }}',
'int' => '{{ name }} INTEGER {{ null }} {{ default }} {{ unique }}',
'timestamp' => '{{ name }} INTEGER {{ null }} {{ default }} {{ unique }}'
'timestamp' => '{{ name }} INTEGER {{ null }} {{ default }} {{ unique }}',
'bool' => '{{ name }} INTEGER {{ null }} {{ default }} {{ unique }}'
];
}

View File

@@ -23,9 +23,9 @@ class Fields extends Collection
*
* @param string $name
* @param object|array $field
* @return $this
* @return void
*/
public function __set(string $name, $field)
public function __set(string $name, $field): void
{
if (is_array($field) === true) {
// use the array key as name if the name is not set
@@ -33,7 +33,7 @@ class Fields extends Collection
$field = Field::factory($field['type'], $field, $this);
}
return parent::__set($field->name(), $field);
parent::__set($field->name(), $field);
}
/**

View File

@@ -326,24 +326,32 @@ class Environment
/**
* Sets the host name, port and protocol without configuration
*
* @param bool $insecure Include the `Host` and `X-Forwarded-*` headers in the search
* @param bool $insecure Include the `Host`, `Forwarded` and `X-Forwarded-*` headers in the search
* @return void
*/
protected function detectAuto(bool $insecure = false): void
{
// proxy server setup
if (
$insecure === true &&
empty($this->info['HTTP_X_FORWARDED_HOST']) === false
) {
if ($insecure === true) {
$forwarded = $this->detectForwarded();
$host = $forwarded['host'];
$port = $forwarded['port'];
$https = $forwarded['https'];
if ($host || $port || $https) {
$this->isBehindProxy = true;
$this->host = $this->detectForwardedHost();
$this->https = $this->detectForwardedHttps();
$this->port = $this->detectForwardedPort();
// if a port or scheme is defined but no host, assume
// that the host is the same as PHP's own hostname
// (which is often the case with reverse proxies)
$this->host = $host ?? $this->detectHost($insecure);
$this->port = $port;
$this->https = $https;
return;
}
}
// local server setup
$this->isBehindProxy = false;
@@ -389,6 +397,7 @@ class Environment
return true;
}
// @codeCoverageIgnoreStart
$term = getenv('TERM');
if (substr(PHP_SAPI, 0, 3) === 'cgi' && $term && $term !== 'unknown') {
@@ -396,10 +405,83 @@ class Environment
}
return false;
// @codeCoverageIgnoreEnd
}
/**
* Detects the host, protocol, port and client IP
* from the `Forwarded` and `X-Forwarded-*` headers
*
* @return array
*/
protected function detectForwarded(): array
{
$data = [
'for' => null,
'host' => null,
'https' => false,
'port' => null
];
// prefer the standardized `Forwarded` header if defined
$forwarded = $this->get('HTTP_FORWARDED');
if ($forwarded) {
// only use the first (outermost) proxy by using the first set of values
// before the first comma (but only a comma outside of quotes)
if (Str::contains($forwarded, ',') === true) {
$forwarded = preg_split('/"[^"]*"(*SKIP)(*F)|,/', $forwarded)[0];
}
// split into separate key=value;key=value fields by semicolon,
// but only split outside of quotes
$rawFields = preg_split('/"[^"]*"(*SKIP)(*F)|;/', $forwarded);
// split key and value into an associative array
$fields = [];
foreach ($rawFields as $field) {
$key = Str::lower(Str::before($field, '='));
$value = Str::after($field, '=');
// trim the surrounding quotes
if (Str::substr($value, 0, 1) === '"') {
$value = Str::substr($value, 1, -1);
}
$fields[$key] = $value;
}
// assemble the normalized data
if (isset($fields['host']) === true) {
$parts = $this->detectPortInHost($fields['host']);
$data['host'] = $parts['host'];
$data['port'] = $parts['port'];
}
if (isset($fields['proto']) === true) {
$data['https'] = $this->detectHttpsProtocol($fields['proto']);
}
if ($data['port'] === null && $data['https'] === true) {
$data['port'] = 443;
}
$data['for'] = $parts['for'] ?? null;
return $data;
}
// no success, try the `X-Forwarded-*` headers
$data['host'] = $this->detectForwardedHost();
$data['https'] = $this->detectForwardedHttps();
$data['port'] = $this->detectForwardedPort($data['https']);
$data['for'] = $this->get('HTTP_X_FORWARDED_FOR');
return $data;
}
/**
* Detects the host name of the reverse proxy
* from the `X-Forwarded-Host` header
*
* @return string|null
*/
@@ -414,7 +496,8 @@ class Environment
}
/**
* Detects the protocol of the reverse proxy
* Detects the protocol of the reverse proxy from the
* `X-Forwarded-SSL` or `X-Forwarded-Proto` header
*
* @return bool
*/
@@ -432,11 +515,13 @@ class Environment
}
/**
* Detects the port of the reverse proxy
* Detects the port of the reverse proxy from the
* `X-Forwarded-Host` or `X-Forwarded-Port` header
*
* @param bool $https Whether HTTPS was detected
* @return int|null
*/
protected function detectForwardedPort(): ?int
protected function detectForwardedPort(bool $https): ?int
{
// based on forwarded port
$port = $this->get('HTTP_X_FORWARDED_PORT');
@@ -451,7 +536,7 @@ class Environment
}
// based on the detected https state
if ($this->https === true) {
if ($https === true) {
return 443;
}
@@ -789,6 +874,10 @@ class Environment
$this->get('HTTP_CLIENT_IP')
];
if ($this->get('HTTP_FORWARDED')) {
$ips[] = $this->detectForwarded()['for'];
}
// remove duplicates and empty ips
$ips = array_unique(array_filter($ips));

View File

@@ -167,8 +167,9 @@ class Uri
*
* @param string $property
* @param mixed $value
* @return void
*/
public function __set(string $property, $value)
public function __set(string $property, $value): void
{
if (method_exists($this, 'set' . $property) === true) {
$this->{'set' . $property}($value);

View File

@@ -95,17 +95,15 @@ class Collection extends Iterator implements Countable
*
* @param string $key string or array
* @param mixed $value
* @return $this
* @return void
*/
public function __set(string $key, $value)
public function __set(string $key, $value): void
{
if ($this->caseSensitive === true) {
$this->data[$key] = $value;
} else {
$this->data[strtolower($key)] = $value;
}
return $this;
}
/**

View File

@@ -141,9 +141,16 @@ class I18n
$locale ??= static::locale();
if (is_array($key) === true) {
// try to use actual locale
if (isset($key[$locale])) {
return $key[$locale];
}
// try to use language code, e.g. `es` when locale is `es_ES`
$lang = Str::before($locale, '_');
if (isset($key[$lang])) {
return $key[$lang];
}
// use fallback
if (is_array($fallback)) {
return $fallback[$locale] ?? $fallback['en'] ?? reset($fallback);
}
@@ -218,6 +225,12 @@ class I18n
return static::$translations[$locale] = (static::$load)($locale);
}
// try to use language code, e.g. `es` when locale is `es_ES`
$lang = Str::before($locale, '_');
if (isset(static::$translations[$lang]) === true) {
return static::$translations[$lang];
}
return static::$translations[$locale] = [];
}

View File

@@ -1,8 +1,8 @@
<?php return array(
'root' => array(
'name' => 'getkirby/cms',
'pretty_version' => '3.7.0.2',
'version' => '3.7.0.2',
'pretty_version' => '3.7.1',
'version' => '3.7.1.0',
'reference' => NULL,
'type' => 'kirby-cms',
'install_path' => __DIR__ . '/../../',
@@ -29,8 +29,8 @@
'dev_requirement' => false,
),
'getkirby/cms' => array(
'pretty_version' => '3.7.0.2',
'version' => '3.7.0.2',
'pretty_version' => '3.7.1',
'version' => '3.7.1.0',
'reference' => NULL,
'type' => 'kirby-cms',
'install_path' => __DIR__ . '/../../',