Upgrade to 3.9.2
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
"description": "The Kirby 3 core",
|
||||
"license": "proprietary",
|
||||
"type": "kirby-cms",
|
||||
"version": "3.9.1",
|
||||
"version": "3.9.2",
|
||||
"keywords": [
|
||||
"kirby",
|
||||
"cms",
|
||||
|
2
kirby/composer.lock
generated
2
kirby/composer.lock
generated
@@ -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": "befcfd99f474ab4c303eb4b9fa9262ad",
|
||||
"content-hash": "4da7bfec5d96803f96d1aca050d9b6c3",
|
||||
"packages": [
|
||||
{
|
||||
"name": "claviska/simpleimage",
|
||||
|
@@ -66,7 +66,8 @@ return function (App $app) {
|
||||
try {
|
||||
$blocks = Blocks::parse($field->value());
|
||||
$blocks = Blocks::factory($blocks, [
|
||||
'parent' => $field->parent()
|
||||
'parent' => $field->parent(),
|
||||
'field' => $field,
|
||||
]);
|
||||
return $blocks->filter('isHidden', false);
|
||||
} catch (Throwable) {
|
||||
@@ -192,7 +193,8 @@ return function (App $app) {
|
||||
*/
|
||||
'toLayouts' => function (Field $field) {
|
||||
return Layouts::factory(Layouts::parse($field->value()), [
|
||||
'parent' => $field->parent()
|
||||
'parent' => $field->parent(),
|
||||
'field' => $field,
|
||||
]);
|
||||
},
|
||||
|
||||
@@ -276,10 +278,10 @@ return function (App $app) {
|
||||
* Converts the field value to a Unix timestamp
|
||||
*
|
||||
* @param \Kirby\Cms\Field $field
|
||||
* @return int
|
||||
* @return int|false
|
||||
*/
|
||||
'toTimestamp' => function (Field $field): int {
|
||||
return strtotime($field->value);
|
||||
'toTimestamp' => function (Field $field): int|false {
|
||||
return strtotime($field->value ?? '');
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -394,7 +396,7 @@ return function (App $app) {
|
||||
// Obsolete elements, script tags, image maps and form elements have
|
||||
// been excluded for safety reasons and as they are most likely not
|
||||
// needed in most cases.
|
||||
$field->value = strip_tags($field->value, Html::$inlineList);
|
||||
$field->value = strip_tags($field->value ?? '', Html::$inlineList);
|
||||
return $field;
|
||||
},
|
||||
|
||||
@@ -481,7 +483,7 @@ return function (App $app) {
|
||||
* @return \Kirby\Cms\Field
|
||||
*/
|
||||
'nl2br' => function (Field $field) {
|
||||
$field->value = nl2br($field->value, false);
|
||||
$field->value = nl2br($field->value ?? '', false);
|
||||
return $field;
|
||||
},
|
||||
|
||||
|
@@ -57,6 +57,11 @@ return [
|
||||
// search
|
||||
if ($this->search === true && empty($this->searchterm()) === false) {
|
||||
$files = $files->search($this->searchterm());
|
||||
|
||||
// disable flip and sortBy while searching
|
||||
// to show most relevant results
|
||||
$this->flip = false;
|
||||
$this->sortBy = null;
|
||||
}
|
||||
|
||||
// sort
|
||||
|
@@ -94,6 +94,11 @@ return [
|
||||
// search
|
||||
if ($this->search === true && empty($this->searchterm()) === false) {
|
||||
$pages = $pages->search($this->searchterm());
|
||||
|
||||
// disable flip and sortBy while searching
|
||||
// to show most relevant results
|
||||
$this->flip = false;
|
||||
$this->sortBy = null;
|
||||
}
|
||||
|
||||
// sort
|
||||
|
@@ -388,7 +388,7 @@
|
||||
"login.toggleText.password-reset.email": "Forgot your password?",
|
||||
"login.toggleText.password-reset.email-password": "← Back to login",
|
||||
|
||||
"logout": "Tancar sessi\u00f3",
|
||||
"logout": "Tancar sessió",
|
||||
|
||||
"menu": "Menú",
|
||||
"meridiem": "AM/PM",
|
||||
|
@@ -388,7 +388,7 @@
|
||||
"login.toggleText.password-reset.email": "Zapomenuté heslo?",
|
||||
"login.toggleText.password-reset.email-password": "← Zpět na přihlášení",
|
||||
|
||||
"logout": "Odhl\u00e1sit se",
|
||||
"logout": "Odhlásit se",
|
||||
|
||||
"menu": "Menu",
|
||||
"meridiem": "AM/PM",
|
||||
|
@@ -77,7 +77,7 @@
|
||||
"error.email.preset.notFound": "Die E-Mailvorlage \"{name}\" wurde nicht gefunden",
|
||||
|
||||
"error.field.converter.invalid": "Ungültiger Konverter: \"{converter}\"",
|
||||
"error.field.type.missing": "Feld \"{ name }\": Der Feld Typ \"{ type }\" existiert nicht",
|
||||
"error.field.type.missing": "Feld \"{ name }\": Der Feldtyp \"{ type }\" existiert nicht",
|
||||
|
||||
"error.file.changeName.empty": "Bitte gib einen Namen an",
|
||||
"error.file.changeName.permission": "Du darfst den Dateinamen von \"{filename}\" nicht ändern",
|
||||
@@ -110,7 +110,7 @@
|
||||
"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 im \"{field}\" Feld in Block {blockIndex} mit dem Block Typ \"{fieldset}\" in Layout {layoutIndex}",
|
||||
"error.layout.validation.block": "Fehler im \"{field}\" Feld in Block {blockIndex} mit dem Blocktyp \"{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",
|
||||
@@ -165,7 +165,7 @@
|
||||
|
||||
"error.template.default.notFound": "Die \"Default\"-Vorlage existiert nicht",
|
||||
|
||||
"error.unexpected": "Ein unerwarteter Fehler ist aufgetreten. Aktiviere den Debug Modus für weitere Informationen: https://getkirby.com/docs/reference/system/options/debug",
|
||||
"error.unexpected": "Ein unerwarteter Fehler ist aufgetreten. Aktiviere den Debug-Modus für weitere Informationen: https://getkirby.com/docs/reference/system/options/debug",
|
||||
|
||||
"error.user.changeEmail.permission": "Du kannst die E-Mailadresse für den Account \"{name}\" nicht ändern",
|
||||
"error.user.changeLanguage.permission": "Du kannst die Sprache für den Account \"{name}\" nicht ändern",
|
||||
|
@@ -388,7 +388,7 @@
|
||||
"login.toggleText.password-reset.email": "Forgot your password?",
|
||||
"login.toggleText.password-reset.email-password": "← Back to login",
|
||||
|
||||
"logout": "\u0391\u03c0\u03bf\u03c3\u03cd\u03bd\u03b4\u03b5\u03c3\u03b7",
|
||||
"logout": "Αποσύνδεση",
|
||||
|
||||
"menu": "Μενού",
|
||||
"meridiem": "Π.Μ./Μ.Μ",
|
||||
|
@@ -388,7 +388,7 @@
|
||||
"login.toggleText.password-reset.email": "¿Olvidaste tu contraseña?",
|
||||
"login.toggleText.password-reset.email-password": "← Volver al inicio de sesión",
|
||||
|
||||
"logout": "Cerrar sesi\u00f3n",
|
||||
"logout": "Cerrar sesión",
|
||||
|
||||
"menu": "Menù",
|
||||
"meridiem": "AM/PM",
|
||||
|
@@ -12,7 +12,7 @@
|
||||
"close": "Cerrar",
|
||||
"confirm": "Confirmar",
|
||||
"collapse": "Colapsar",
|
||||
"collapse.all": "Colapsar todos",
|
||||
"collapse.all": "Colapsar todo",
|
||||
"copy": "Copiar",
|
||||
"copy.all": "Copiar todo",
|
||||
"create": "Crear",
|
||||
@@ -32,7 +32,7 @@
|
||||
"debugging": "Depuración",
|
||||
|
||||
"delete": "Eliminar",
|
||||
"delete.all": "Eliminar todos",
|
||||
"delete.all": "Eliminar todo",
|
||||
|
||||
"dialog.files.empty": "No hay archivos para seleccionar",
|
||||
"dialog.pages.empty": "No hay páginas para seleccionar",
|
||||
@@ -86,14 +86,14 @@
|
||||
"error.file.extension.invalid": "Extensión inválida: {extension}",
|
||||
"error.file.extension.missing": "Falta la extensión para \"{filename}\"",
|
||||
"error.file.maxheight": "La altura de la imagen no debe exceder {height} pixeles",
|
||||
"error.file.maxsize": "El archivo es muy grande",
|
||||
"error.file.maxsize": "El archivo es demasiado grande",
|
||||
"error.file.maxwidth": "El ancho de la imagen no debe exceder {width} pixeles",
|
||||
"error.file.mime.differs": "El archivo cargado debe ser del mismo tipo mime \"{mime}\"",
|
||||
"error.file.mime.forbidden": "Los medios tipo \"{mime}\" no están permitidos",
|
||||
"error.file.mime.invalid": "Tipo invalido de mime: {mime}",
|
||||
"error.file.mime.invalid": "Tipo de mime inválido: {mime}",
|
||||
"error.file.mime.missing": "El tipo de medio para \"{filename}\" no puede ser detectado",
|
||||
"error.file.minheight": "La altura de la imagen debe ser de al menos {height} pixeles",
|
||||
"error.file.minsize": "El archivo es muy pequeño",
|
||||
"error.file.minsize": "El archivo es demasiado pequeño",
|
||||
"error.file.minwidth": "El ancho de la imagen debe ser de al menos {width} pixeles",
|
||||
"error.file.name.missing": "El nombre de archivo no debe estar vacío",
|
||||
"error.file.notFound": "El archivo \"{filename}\" no puede ser encontrado",
|
||||
@@ -519,7 +519,7 @@
|
||||
"system.updateStatus.update": "Actualización gratuita {version} disponible",
|
||||
"system.updateStatus.upgrade": "Actualización {versión} disponible",
|
||||
|
||||
"title": "Titulo",
|
||||
"title": "Título",
|
||||
"template": "Plantilla",
|
||||
"today": "Hoy",
|
||||
|
||||
|
@@ -388,7 +388,7 @@
|
||||
"login.toggleText.password-reset.email": "Mot de passe oublié ?",
|
||||
"login.toggleText.password-reset.email-password": "← Retour à la connexion",
|
||||
|
||||
"logout": "Se déconnecter",
|
||||
"logout": "Déconnexion",
|
||||
|
||||
"menu": "Menu",
|
||||
"meridiem": "AM/PM",
|
||||
|
@@ -388,7 +388,7 @@
|
||||
"login.toggleText.password-reset.email": "암호 찾기",
|
||||
"login.toggleText.password-reset.email-password": "로그인 화면으로",
|
||||
|
||||
"logout": "\ub85c\uadf8\uc544\uc6c3",
|
||||
"logout": "로그아웃",
|
||||
|
||||
"menu": "메뉴",
|
||||
"meridiem": "오전/오후",
|
||||
|
@@ -388,7 +388,7 @@
|
||||
"login.toggleText.password-reset.email": "Zapomniałeś/-aś hasła?",
|
||||
"login.toggleText.password-reset.email-password": "← Powrót do logowania",
|
||||
|
||||
"logout": "Wyloguj",
|
||||
"logout": "Wyloguj się",
|
||||
|
||||
"menu": "Menu",
|
||||
"meridiem": "AM/PM",
|
||||
|
@@ -388,7 +388,7 @@
|
||||
"login.toggleText.password-reset.email": "Şifrenizi mi unuttunuz?",
|
||||
"login.toggleText.password-reset.email-password": "← Girişe geri dön",
|
||||
|
||||
"logout": "Güvenli Çıkış",
|
||||
"logout": "Oturumu kapat",
|
||||
|
||||
"menu": "Menü",
|
||||
"meridiem": "AM/PM",
|
||||
|
2
kirby/panel/dist/js/index.js
vendored
2
kirby/panel/dist/js/index.js
vendored
File diff suppressed because one or more lines are too long
@@ -482,28 +482,23 @@ class App
|
||||
|
||||
/**
|
||||
* Try to find a controller by name
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $contentType
|
||||
* @return \Kirby\Toolkit\Controller|null
|
||||
*/
|
||||
protected function controllerLookup(string $name, string $contentType = 'html')
|
||||
protected function controllerLookup(string $name, string $contentType = 'html'): Controller|null
|
||||
{
|
||||
if ($contentType !== null && $contentType !== 'html') {
|
||||
$name .= '.' . $contentType;
|
||||
}
|
||||
|
||||
// controller on disk
|
||||
if ($controller = Controller::load($this->root('controllers') . '/' . $name . '.php')) {
|
||||
return $controller;
|
||||
}
|
||||
// controller from site root
|
||||
$controller = Controller::load($this->root('controllers') . '/' . $name . '.php');
|
||||
// controller from extension
|
||||
$controller ??= $this->extension('controllers', $name);
|
||||
|
||||
// registry controller
|
||||
if ($controller = $this->extension('controllers', $name)) {
|
||||
if ($controller instanceof Controller) {
|
||||
return $controller;
|
||||
}
|
||||
|
||||
if ($controller !== null) {
|
||||
return new Controller($controller);
|
||||
}
|
||||
|
||||
|
@@ -4,6 +4,7 @@ namespace Kirby\Cms;
|
||||
|
||||
use Closure;
|
||||
use Kirby\Exception\DuplicateException;
|
||||
use Kirby\Filesystem\Asset;
|
||||
use Kirby\Filesystem\Dir;
|
||||
use Kirby\Filesystem\F;
|
||||
use Kirby\Filesystem\Mime;
|
||||
@@ -45,6 +46,7 @@ trait AppPlugins
|
||||
// other plugin types
|
||||
'api' => [],
|
||||
'areas' => [],
|
||||
'assetMethods' => [],
|
||||
'authChallenges' => [],
|
||||
'blockMethods' => [],
|
||||
'blockModels' => [],
|
||||
@@ -147,6 +149,17 @@ trait AppPlugins
|
||||
return $this->extensions['areas'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers additional asset methods
|
||||
*
|
||||
* @param array $methods
|
||||
* @return array
|
||||
*/
|
||||
protected function extendAssetMethods(array $methods): array
|
||||
{
|
||||
return $this->extensions['assetMethods'] = Asset::$methods = array_merge(Asset::$methods, $methods);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers additional authentication challenges
|
||||
*
|
||||
|
@@ -73,6 +73,13 @@ class Block extends Item
|
||||
{
|
||||
parent::__construct($params);
|
||||
|
||||
// @deprecated import old builder format
|
||||
// @todo block.converter remove eventually
|
||||
// @codeCoverageIgnoreStart
|
||||
$params = BlockConverter::builderBlock($params);
|
||||
$params = BlockConverter::editorBlock($params);
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
if (isset($params['type']) === false) {
|
||||
throw new InvalidArgumentException('The block type is missing');
|
||||
}
|
||||
|
285
kirby/src/Cms/BlockConverter.php
Normal file
285
kirby/src/Cms/BlockConverter.php
Normal file
@@ -0,0 +1,285 @@
|
||||
<?php
|
||||
|
||||
namespace Kirby\Cms;
|
||||
|
||||
/**
|
||||
* Converts the data from the old builder and editor fields
|
||||
* to the format supported by the new block field.
|
||||
* @since 3.9.0
|
||||
* @deprecated
|
||||
*
|
||||
* @todo block.converter remove eventually
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @package Kirby Cms
|
||||
* @author Bastian Allgeier <bastian@getkirby.com>
|
||||
* @link https://getkirby.com
|
||||
* @copyright Bastian Allgeier GmbH
|
||||
* @license https://getkirby.com/license
|
||||
*/
|
||||
class BlockConverter
|
||||
{
|
||||
public static function builderBlock(array $params): array
|
||||
{
|
||||
if (isset($params['_key']) === false) {
|
||||
return $params;
|
||||
}
|
||||
|
||||
$params['type'] = $params['_key'];
|
||||
$params['content'] = $params;
|
||||
unset($params['_uid']);
|
||||
|
||||
return $params;
|
||||
}
|
||||
|
||||
public static function editorBlock(array $params): array
|
||||
{
|
||||
if (static::isEditorBlock($params) === false) {
|
||||
return $params;
|
||||
}
|
||||
|
||||
$method = 'editor' . $params['type'];
|
||||
|
||||
if (method_exists(static::class, $method) === true) {
|
||||
$params = static::$method($params);
|
||||
} else {
|
||||
$params = static::editorCustom($params);
|
||||
}
|
||||
|
||||
return $params;
|
||||
}
|
||||
|
||||
public static function editorBlocks(array $blocks = []): array
|
||||
{
|
||||
if (empty($blocks) === true) {
|
||||
return $blocks;
|
||||
}
|
||||
|
||||
if (static::isEditorBlock($blocks[0]) === false) {
|
||||
return $blocks;
|
||||
}
|
||||
|
||||
$list = [];
|
||||
$listStart = null;
|
||||
|
||||
foreach ($blocks as $index => $block) {
|
||||
if (in_array($block['type'], ['ul', 'ol']) === true) {
|
||||
$prev = $blocks[$index-1] ?? null;
|
||||
$next = $blocks[$index+1] ?? null;
|
||||
|
||||
// new list starts here
|
||||
if (!$prev || $prev['type'] !== $block['type']) {
|
||||
$listStart = $index;
|
||||
}
|
||||
|
||||
// add the block to the list
|
||||
$list[] = $block;
|
||||
|
||||
// list ends here
|
||||
if (!$next || $next['type'] !== $block['type']) {
|
||||
$blocks[$listStart] = [
|
||||
'content' => [
|
||||
'text' =>
|
||||
'<' . $block['type'] . '>' .
|
||||
implode(array_map(
|
||||
fn ($item) => '<li>' . $item['content'] . '</li>',
|
||||
$list
|
||||
)) .
|
||||
'</' . $block['type'] . '>',
|
||||
],
|
||||
'type' => 'list'
|
||||
];
|
||||
|
||||
$start = $listStart + 1;
|
||||
$end = $listStart + count($list);
|
||||
|
||||
for ($x = $start; $x <= $end; $x++) {
|
||||
$blocks[$x] = false;
|
||||
}
|
||||
|
||||
$listStart = null;
|
||||
$list = [];
|
||||
}
|
||||
} else {
|
||||
$blocks[$index] = static::editorBlock($block);
|
||||
}
|
||||
}
|
||||
|
||||
return array_filter($blocks);
|
||||
}
|
||||
|
||||
public static function editorBlockquote(array $params): array
|
||||
{
|
||||
return [
|
||||
'content' => [
|
||||
'text' => $params['content']
|
||||
],
|
||||
'type' => 'quote'
|
||||
];
|
||||
}
|
||||
|
||||
public static function editorCode(array $params): array
|
||||
{
|
||||
return [
|
||||
'content' => [
|
||||
'language' => $params['attrs']['language'] ?? null,
|
||||
'code' => $params['content']
|
||||
],
|
||||
'type' => 'code'
|
||||
];
|
||||
}
|
||||
|
||||
public static function editorCustom(array $params): array
|
||||
{
|
||||
return [
|
||||
'content' => array_merge(
|
||||
$params['attrs'] ?? [],
|
||||
[
|
||||
'body' => $params['content'] ?? null
|
||||
]
|
||||
),
|
||||
'type' => $params['type'] ?? 'unknown'
|
||||
];
|
||||
}
|
||||
|
||||
public static function editorH1(array $params): array
|
||||
{
|
||||
return static::editorHeading($params, 'h1');
|
||||
}
|
||||
|
||||
public static function editorH2(array $params): array
|
||||
{
|
||||
return static::editorHeading($params, 'h2');
|
||||
}
|
||||
|
||||
public static function editorH3(array $params): array
|
||||
{
|
||||
return static::editorHeading($params, 'h3');
|
||||
}
|
||||
|
||||
public static function editorH4(array $params): array
|
||||
{
|
||||
return static::editorHeading($params, 'h4');
|
||||
}
|
||||
|
||||
public static function editorH5(array $params): array
|
||||
{
|
||||
return static::editorHeading($params, 'h5');
|
||||
}
|
||||
|
||||
public static function editorH6(array $params): array
|
||||
{
|
||||
return static::editorHeading($params, 'h6');
|
||||
}
|
||||
|
||||
public static function editorHr(array $params): array
|
||||
{
|
||||
return [
|
||||
'content' => [],
|
||||
'type' => 'line'
|
||||
];
|
||||
}
|
||||
|
||||
public static function editorHeading(array $params, string $level = 'h1'): array
|
||||
{
|
||||
return [
|
||||
'content' => [
|
||||
'level' => $level,
|
||||
'text' => $params['content']
|
||||
],
|
||||
'type' => 'heading'
|
||||
];
|
||||
}
|
||||
|
||||
public static function editorImage(array $params): array
|
||||
{
|
||||
// internal image
|
||||
if (isset($params['attrs']['id']) === true) {
|
||||
return [
|
||||
'content' => [
|
||||
'alt' => $params['attrs']['alt'] ?? null,
|
||||
'caption' => $params['attrs']['caption'] ?? null,
|
||||
'image' => $params['attrs']['id'] ?? $params['attrs']['src'] ?? null,
|
||||
'location' => 'kirby',
|
||||
'ratio' => $params['attrs']['ratio'] ?? null,
|
||||
],
|
||||
'type' => 'image'
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'content' => [
|
||||
'alt' => $params['attrs']['alt'] ?? null,
|
||||
'caption' => $params['attrs']['caption'] ?? null,
|
||||
'src' => $params['attrs']['src'] ?? null,
|
||||
'location' => 'web',
|
||||
'ratio' => $params['attrs']['ratio'] ?? null,
|
||||
],
|
||||
'type' => 'image'
|
||||
];
|
||||
}
|
||||
|
||||
public static function editorKirbytext(array $params): array
|
||||
{
|
||||
return [
|
||||
'content' => [
|
||||
'text' => $params['content']
|
||||
],
|
||||
'type' => 'markdown'
|
||||
];
|
||||
}
|
||||
|
||||
public static function editorOl(array $params): array
|
||||
{
|
||||
return [
|
||||
'content' => [
|
||||
'text' => $params['content']
|
||||
],
|
||||
'type' => 'list'
|
||||
];
|
||||
}
|
||||
|
||||
public static function editorParagraph(array $params): array
|
||||
{
|
||||
return [
|
||||
'content' => [
|
||||
'text' => '<p>' . $params['content'] . '</p>'
|
||||
],
|
||||
'type' => 'text'
|
||||
];
|
||||
}
|
||||
|
||||
public static function editorUl(array $params): array
|
||||
{
|
||||
return [
|
||||
'content' => [
|
||||
'text' => $params['content']
|
||||
],
|
||||
'type' => 'list'
|
||||
];
|
||||
}
|
||||
|
||||
public static function editorVideo(array $params): array
|
||||
{
|
||||
return [
|
||||
'content' => [
|
||||
'caption' => $params['attrs']['caption'] ?? null,
|
||||
'url' => $params['attrs']['src'] ?? null
|
||||
],
|
||||
'type' => 'video'
|
||||
];
|
||||
}
|
||||
|
||||
public static function isEditorBlock(array $params): bool
|
||||
{
|
||||
if (isset($params['attrs']) === true) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (is_string($params['content'] ?? null) === true) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
@@ -2,9 +2,12 @@
|
||||
|
||||
namespace Kirby\Cms;
|
||||
|
||||
use Exception;
|
||||
use Kirby\Data\Json;
|
||||
use Kirby\Data\Yaml;
|
||||
use Kirby\Parsley\Parsley;
|
||||
use Kirby\Parsley\Schema\Blocks as BlockSchema;
|
||||
use Kirby\Toolkit\A;
|
||||
use Kirby\Toolkit\Str;
|
||||
use Throwable;
|
||||
|
||||
@@ -58,6 +61,12 @@ class Blocks extends Items
|
||||
{
|
||||
$items = static::extractFromLayouts($items);
|
||||
|
||||
// @deprecated old editor format
|
||||
// @todo block.converter remove eventually
|
||||
// @codeCoverageIgnoreStart
|
||||
$items = BlockConverter::editorBlocks($items);
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
return parent::factory($items, $params);
|
||||
}
|
||||
|
||||
@@ -73,8 +82,13 @@ class Blocks extends Items
|
||||
return [];
|
||||
}
|
||||
|
||||
if (
|
||||
// no columns = no layout
|
||||
if (array_key_exists('columns', $input[0]) === false) {
|
||||
array_key_exists('columns', $input[0]) === false ||
|
||||
// @deprecated checks if this is a block for the builder plugin
|
||||
// @todo block.converter remove eventually
|
||||
array_key_exists('_key', $input[0]) === true
|
||||
) {
|
||||
return $input;
|
||||
}
|
||||
|
||||
@@ -115,8 +129,33 @@ class Blocks extends Items
|
||||
try {
|
||||
$input = Json::decode((string)$input);
|
||||
} catch (Throwable) {
|
||||
// @deprecated try to import the old YAML format
|
||||
// @todo block.converter remove eventually
|
||||
// @codeCoverageIgnoreStart
|
||||
try {
|
||||
$yaml = Yaml::decode((string)$input);
|
||||
$first = A::first($yaml);
|
||||
|
||||
// check for valid yaml
|
||||
if (
|
||||
empty($yaml) === true ||
|
||||
(
|
||||
isset($first['_key']) === false &&
|
||||
isset($first['type']) === false
|
||||
)
|
||||
) {
|
||||
throw new Exception('Invalid YAML');
|
||||
} else {
|
||||
$input = $yaml;
|
||||
}
|
||||
} catch (Throwable $e) {
|
||||
// the next 2 lines remain after removing block.converter
|
||||
// @codeCoverageIgnoreEnd
|
||||
$parser = new Parsley((string)$input, new BlockSchema());
|
||||
$input = $parser->blocks();
|
||||
// @codeCoverageIgnoreStart
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -179,7 +179,7 @@ class File extends ModelWithContent
|
||||
public function contentFileData(array $data, string $languageCode = null): array
|
||||
{
|
||||
return A::append($data, [
|
||||
'template' => $this->template(),
|
||||
'template' => $data['template'] ?? $this->template(),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@@ -26,6 +26,8 @@ class Item
|
||||
|
||||
public const ITEMS_CLASS = Items::class;
|
||||
|
||||
protected Field|null $field;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
@@ -57,6 +59,7 @@ class Item
|
||||
|
||||
$this->id = $params['id'] ?? Str::uuid();
|
||||
$this->params = $params;
|
||||
$this->field = $params['field'] ?? null;
|
||||
$this->parent = $params['parent'] ?? App::instance()->site();
|
||||
$this->siblings = $params['siblings'] ?? new $siblingsClass();
|
||||
}
|
||||
@@ -72,6 +75,14 @@ class Item
|
||||
return new static($params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the parent field if known
|
||||
*/
|
||||
public function field(): Field|null
|
||||
{
|
||||
return $this->field;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the unique item id (UUID v4)
|
||||
*
|
||||
|
@@ -19,6 +19,8 @@ class Items extends Collection
|
||||
{
|
||||
public const ITEM_CLASS = Item::class;
|
||||
|
||||
protected Field|null $field;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
@@ -39,6 +41,7 @@ class Items extends Collection
|
||||
{
|
||||
$this->options = $options;
|
||||
$this->parent = $options['parent'] ?? App::instance()->site();
|
||||
$this->field = $options['field'] ?? null;
|
||||
|
||||
parent::__construct($objects, $this->parent);
|
||||
}
|
||||
@@ -54,6 +57,7 @@ class Items extends Collection
|
||||
public static function factory(array $items = null, array $params = [])
|
||||
{
|
||||
$options = array_merge([
|
||||
'field' => null,
|
||||
'options' => [],
|
||||
'parent' => App::instance()->site(),
|
||||
], $params);
|
||||
@@ -74,6 +78,7 @@ class Items extends Collection
|
||||
continue;
|
||||
}
|
||||
|
||||
$params['field'] = $options['field'];
|
||||
$params['options'] = $options['options'];
|
||||
$params['parent'] = $options['parent'];
|
||||
$params['siblings'] = $collection;
|
||||
@@ -85,6 +90,14 @@ class Items extends Collection
|
||||
return $collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the parent field if known
|
||||
*/
|
||||
public function field(): Field|null
|
||||
{
|
||||
return $this->field;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the items to an array
|
||||
*
|
||||
|
@@ -56,6 +56,7 @@ class Layout extends Item
|
||||
parent::__construct($params);
|
||||
|
||||
$this->columns = LayoutColumns::factory($params['columns'] ?? [], [
|
||||
'field' => $this->field,
|
||||
'parent' => $this->parent
|
||||
]);
|
||||
|
||||
|
@@ -41,6 +41,7 @@ class LayoutColumn extends Item
|
||||
parent::__construct($params);
|
||||
|
||||
$this->blocks = Blocks::factory($params['blocks'] ?? [], [
|
||||
'field' => $this->field,
|
||||
'parent' => $this->parent
|
||||
]);
|
||||
|
||||
|
@@ -98,6 +98,9 @@ class Layouts extends Items
|
||||
}
|
||||
}
|
||||
|
||||
return Blocks::factory($blocks);
|
||||
return Blocks::factory($blocks, [
|
||||
'field' => $this->field,
|
||||
'parent' => $this->parent
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@@ -523,7 +523,7 @@ trait PageActions
|
||||
// clean up the slug
|
||||
$props['slug'] = Str::slug($props['slug'] ?? $props['content']['title'] ?? null);
|
||||
$props['template'] = $props['model'] = strtolower($props['template'] ?? 'default');
|
||||
$props['isDraft'] = ($props['draft'] ?? true);
|
||||
$props['isDraft'] ??= $props['draft'] ?? true;
|
||||
|
||||
// make sure that a UUID gets generated and
|
||||
// added to content right away
|
||||
|
@@ -204,7 +204,12 @@ class PageRules
|
||||
]);
|
||||
}
|
||||
|
||||
if (count($page->blueprints()) <= 1) {
|
||||
$blueprints = $page->blueprints();
|
||||
|
||||
if (
|
||||
count($blueprints) <= 1 ||
|
||||
in_array($template, array_column($blueprints, 'name')) === false
|
||||
) {
|
||||
throw new LogicException([
|
||||
'key' => 'page.changeTemplate.invalid',
|
||||
'data' => ['slug' => $page->slug()]
|
||||
|
@@ -154,10 +154,10 @@ class Pages extends Collection
|
||||
*
|
||||
* @param array $pages
|
||||
* @param \Kirby\Cms\Model|null $model
|
||||
* @param bool $draft
|
||||
* @param bool|null $draft
|
||||
* @return static
|
||||
*/
|
||||
public static function factory(array $pages, Model $model = null, bool $draft = false)
|
||||
public static function factory(array $pages, Model $model = null, bool $draft = null)
|
||||
{
|
||||
$model ??= App::instance()->site();
|
||||
$children = new static([], $model);
|
||||
@@ -175,7 +175,7 @@ class Pages extends Collection
|
||||
$props['kirby'] = $kirby;
|
||||
$props['parent'] = $parent;
|
||||
$props['site'] = $site;
|
||||
$props['isDraft'] = $draft;
|
||||
$props['isDraft'] = $draft ?? $props['isDraft'] ?? $props['draft'] ?? false;
|
||||
|
||||
$page = Page::factory($props);
|
||||
|
||||
|
@@ -3,6 +3,8 @@
|
||||
namespace Kirby\Filesystem;
|
||||
|
||||
use Kirby\Cms\FileModifications;
|
||||
use Kirby\Cms\HasMethods;
|
||||
use Kirby\Exception\BadMethodCallException;
|
||||
|
||||
/**
|
||||
* Anything in your public path can be converted
|
||||
@@ -20,6 +22,7 @@ class Asset
|
||||
{
|
||||
use IsFile;
|
||||
use FileModifications;
|
||||
use HasMethods;
|
||||
|
||||
/**
|
||||
* Relative file path
|
||||
@@ -38,6 +41,31 @@ class Asset
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic caller for asset methods
|
||||
*
|
||||
* @throws \Kirby\Exception\BadMethodCallException
|
||||
*/
|
||||
public function __call(string $method, array $arguments = [])
|
||||
{
|
||||
// public property access
|
||||
if (isset($this->$method) === true) {
|
||||
return $this->$method;
|
||||
}
|
||||
|
||||
// asset method proxy
|
||||
if (method_exists($this->asset(), $method)) {
|
||||
return $this->asset()->$method(...$arguments);
|
||||
}
|
||||
|
||||
// asset methods
|
||||
if ($this->hasMethod($method)) {
|
||||
return $this->callMethod($method, $arguments);
|
||||
}
|
||||
|
||||
throw new BadMethodCallException('The method: "' . $method . '" does not exist');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a unique id for the asset
|
||||
*/
|
||||
|
@@ -57,7 +57,7 @@ class Dir
|
||||
string $dir,
|
||||
string $target,
|
||||
bool $recursive = true,
|
||||
array|bool $ignore = []
|
||||
array|false $ignore = []
|
||||
): bool {
|
||||
if (is_dir($dir) === false) {
|
||||
throw new Exception('The directory "' . $dir . '" does not exist');
|
||||
@@ -139,19 +139,32 @@ class Dir
|
||||
|
||||
/**
|
||||
* Read the directory and all subdirectories
|
||||
*
|
||||
* @todo Remove support for `$ignore = null` in a major release
|
||||
* @param array|false|null $ignore Array of absolut file paths;
|
||||
* `false` to disable `Dir::$ignore` list
|
||||
* (passing null is deprecated)
|
||||
*/
|
||||
public static function index(
|
||||
string $dir,
|
||||
bool $recursive = false,
|
||||
array|null $ignore = null,
|
||||
array|false|null $ignore = [],
|
||||
string $path = null
|
||||
): array {
|
||||
$result = [];
|
||||
$dir = realpath($dir);
|
||||
$items = static::read($dir);
|
||||
$items = static::read($dir, $ignore === false ? [] : null);
|
||||
|
||||
foreach ($items as $item) {
|
||||
$root = $dir . '/' . $item;
|
||||
|
||||
if (
|
||||
is_array($ignore) === true &&
|
||||
in_array($root, $ignore) === true
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$entry = $path !== null ? $path . '/' . $item : $item;
|
||||
$result[] = $entry;
|
||||
|
||||
|
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Kirby\Image;
|
||||
|
||||
use Kirby\Cms\Content;
|
||||
use Kirby\Exception\LogicException;
|
||||
use Kirby\Filesystem\File;
|
||||
use Kirby\Toolkit\Html;
|
||||
@@ -114,8 +115,13 @@ class Image extends File
|
||||
{
|
||||
// if no alt text explicitly provided,
|
||||
// try to infer from model content file
|
||||
if ($alt = $this->model?->alt()) {
|
||||
$attr['alt'] ??= $alt;
|
||||
if (
|
||||
$this->model !== null &&
|
||||
method_exists($this->model, 'content') === true &&
|
||||
$this->model->content() instanceof Content &&
|
||||
$this->model->content()->get('alt')->isNotEmpty() === true
|
||||
) {
|
||||
$attr['alt'] ??= $this->model->content()->get('alt')->value();
|
||||
}
|
||||
|
||||
if ($url = $this->url()) {
|
||||
|
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Kirby\Option;
|
||||
|
||||
use Kirby\Cms\Field;
|
||||
use Kirby\Cms\ModelWithContent;
|
||||
use Kirby\Cms\Nest;
|
||||
use Kirby\Data\Json;
|
||||
@@ -108,45 +109,38 @@ class OptionsApi extends OptionsProvider
|
||||
// load data from URL and convert from JSON to array
|
||||
$data = $this->load($model);
|
||||
|
||||
// @codeCoverageIgnoreStart
|
||||
if ($data === null) {
|
||||
throw new NotFoundException('Options could not be loaded from API: ' . $model->toSafeString($this->url));
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
// optionally query a substructure inside the data array
|
||||
if ($this->query !== null) {
|
||||
// turn data into Nest so that it can be queried
|
||||
// or field methods applied to the data
|
||||
$data = Nest::create($data);
|
||||
|
||||
// actually apply the query and turn the result back into an array
|
||||
$data = Query::factory($this->query)->resolve($data)->toArray();
|
||||
}
|
||||
// optionally query a substructure inside the data array
|
||||
$data = Query::factory($this->query)->resolve($data);
|
||||
$options = [];
|
||||
|
||||
// create options by resolving text and value query strings
|
||||
// for each item from the data
|
||||
$options = array_map(
|
||||
function ($item, $key) use ($model, $safeMode) {
|
||||
foreach ($data as $key => $item) {
|
||||
// convert simple `key: value` API data
|
||||
if (is_string($item) === true) {
|
||||
$item = [
|
||||
'key' => $key,
|
||||
'value' => $item
|
||||
];
|
||||
$item = new Field(null, $key, $item);
|
||||
}
|
||||
|
||||
$safeMethod = $safeMode === true ? 'toSafeString' : 'toString';
|
||||
|
||||
return [
|
||||
$options[] = [
|
||||
// value is always a raw string
|
||||
'value' => $model->toString($this->value, ['item' => $item]),
|
||||
// text is only a raw string when using {< >}
|
||||
// or when the safe mode is explicitly disabled (select field)
|
||||
'text' => $model->$safeMethod($this->text, ['item' => $item])
|
||||
];
|
||||
},
|
||||
// separately pass values and keys to have the keys available in the callback
|
||||
$data,
|
||||
array_keys($data)
|
||||
);
|
||||
}
|
||||
|
||||
// create Options object and render this subsequently
|
||||
return $this->options = Options::factory($options);
|
||||
|
@@ -51,7 +51,7 @@ class Query
|
||||
/**
|
||||
* Creates a new Query object
|
||||
*/
|
||||
public static function factory(string $query): static
|
||||
public static function factory(string|null $query): static
|
||||
{
|
||||
return new static(query: $query);
|
||||
}
|
||||
|
@@ -4,6 +4,7 @@ namespace Kirby\Toolkit;
|
||||
|
||||
use Closure;
|
||||
use Exception;
|
||||
use InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* The `A` class provides a set of handy methods
|
||||
@@ -161,6 +162,33 @@ class A
|
||||
return implode($separator, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes an array and makes it associative by an argument.
|
||||
* If the argument is a callable, it will be used to map the array.
|
||||
* If it is a string, it will be used as a key to pluck from the array.
|
||||
*
|
||||
* <code>
|
||||
* $array = [['id'=>1], ['id'=>2], ['id'=>3]];
|
||||
* $keyed = A::keyBy($array, 'id');
|
||||
*
|
||||
* // Now you can access the array by the id
|
||||
* </code>
|
||||
*
|
||||
* @param array $array
|
||||
* @param string|callable $keyBy
|
||||
* @return array
|
||||
*/
|
||||
public static function keyBy(array $array, string|callable $keyBy): array
|
||||
{
|
||||
$keys = is_callable($keyBy) ? static::map($array, $keyBy) : static::pluck($array, $keyBy);
|
||||
|
||||
if (count($keys) !== count($array)) {
|
||||
throw new InvalidArgumentException('The "key by" argument must be a valid key or a callable');
|
||||
}
|
||||
|
||||
return array_combine($keys, $array);
|
||||
}
|
||||
|
||||
public const MERGE_OVERWRITE = 0;
|
||||
public const MERGE_APPEND = 1;
|
||||
public const MERGE_REPLACE = 2;
|
||||
@@ -404,15 +432,14 @@ class A
|
||||
* @param int $limit The number of elements the array should
|
||||
* contain after filling it up.
|
||||
* @param mixed $fill The element, which should be used to
|
||||
* fill the array
|
||||
* fill the array. If it's a callable, it
|
||||
* will be called with the current index
|
||||
* @return array The filled-up result array
|
||||
*/
|
||||
public static function fill(array $array, int $limit, $fill = 'placeholder'): array
|
||||
{
|
||||
$diff = $limit - count($array);
|
||||
|
||||
for ($x = 0; $x < $diff; $x++) {
|
||||
$array[] = $fill;
|
||||
for ($x = count($array); $x < $limit; $x++) {
|
||||
$array[] = is_callable($fill) ? $fill($x) : $fill;
|
||||
}
|
||||
|
||||
return $array;
|
||||
|
@@ -8,11 +8,11 @@ use DOMDocument;
|
||||
use DOMDocumentType;
|
||||
use DOMElement;
|
||||
use DOMNode;
|
||||
use DOMNodeList;
|
||||
use DOMProcessingInstruction;
|
||||
use DOMText;
|
||||
use DOMXPath;
|
||||
use Kirby\Cms\App;
|
||||
use Kirby\Exception\Exception;
|
||||
use Kirby\Exception\InvalidArgumentException;
|
||||
|
||||
/**
|
||||
@@ -122,20 +122,16 @@ class Dom
|
||||
|
||||
/**
|
||||
* Returns the HTML body if one exists
|
||||
*
|
||||
* @return \DOMElement|null
|
||||
*/
|
||||
public function body()
|
||||
public function body(): DOMElement|null
|
||||
{
|
||||
return $this->body ??= $this->query('/html/body')[0] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the document object
|
||||
*
|
||||
* @return \DOMDocument
|
||||
*/
|
||||
public function document()
|
||||
public function document(): DOMDocument
|
||||
{
|
||||
return $this->doc;
|
||||
}
|
||||
@@ -143,9 +139,6 @@ class Dom
|
||||
/**
|
||||
* Extracts all URLs wrapped in a url() wrapper. E.g. for style attributes.
|
||||
* @internal
|
||||
*
|
||||
* @param string $value
|
||||
* @return array
|
||||
*/
|
||||
public static function extractUrls(string $value): array
|
||||
{
|
||||
@@ -170,12 +163,12 @@ class Dom
|
||||
* Checks for allowed attributes according to the allowlist
|
||||
* @internal
|
||||
*
|
||||
* @param \DOMAttr $attr
|
||||
* @param array $options
|
||||
* @return true|string If not allowed, an error message is returned
|
||||
*/
|
||||
public static function isAllowedAttr(DOMAttr $attr, array $options)
|
||||
{
|
||||
public static function isAllowedAttr(
|
||||
DOMAttr $attr,
|
||||
array $options
|
||||
): bool|string {
|
||||
$allowedTags = $options['allowedTags'];
|
||||
|
||||
// check if the attribute is in the list of global allowed attributes
|
||||
@@ -218,12 +211,12 @@ class Dom
|
||||
* Checks for allowed attributes according to the global allowlist
|
||||
* @internal
|
||||
*
|
||||
* @param \DOMAttr $attr
|
||||
* @param array $options
|
||||
* @return true|string If not allowed, an error message is returned
|
||||
*/
|
||||
public static function isAllowedGlobalAttr(DOMAttr $attr, array $options)
|
||||
{
|
||||
public static function isAllowedGlobalAttr(
|
||||
DOMAttr $attr,
|
||||
array $options
|
||||
): bool|string {
|
||||
$allowedAttrs = $options['allowedAttrs'];
|
||||
|
||||
if ($allowedAttrs === true) {
|
||||
@@ -256,12 +249,12 @@ class Dom
|
||||
* Checks if the URL is acceptable for URL attributes
|
||||
* @internal
|
||||
*
|
||||
* @param string $url
|
||||
* @param array $options
|
||||
* @return true|string If not allowed, an error message is returned
|
||||
*/
|
||||
public static function isAllowedUrl(string $url, array $options)
|
||||
{
|
||||
public static function isAllowedUrl(
|
||||
string $url,
|
||||
array $options
|
||||
): bool|string {
|
||||
$url = Str::lower($url);
|
||||
|
||||
// allow empty URL values
|
||||
@@ -393,8 +386,6 @@ class Dom
|
||||
* Otherwise DOMDocument won't be available and the Dom cannot
|
||||
* work at all.
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public static function isSupported(): bool
|
||||
@@ -404,9 +395,6 @@ class Dom
|
||||
|
||||
/**
|
||||
* Returns the XML or HTML markup contained in the node
|
||||
*
|
||||
* @param \DOMNode $node
|
||||
* @return string
|
||||
*/
|
||||
public function innerMarkup(DOMNode $node): string
|
||||
{
|
||||
@@ -425,14 +413,16 @@ class Dom
|
||||
* the allowed namespaces
|
||||
* @internal
|
||||
*
|
||||
* @param array $list
|
||||
* @param \DOMNode $node
|
||||
* @param array $options See `Dom::sanitize()`
|
||||
* @param \Closure|null Comparison callback that returns whether the expected and real name match
|
||||
* @return string|false Matched name in the list or `false`
|
||||
*/
|
||||
public static function listContainsName(array $list, DOMNode $node, array $options, Closure|null $compare = null)
|
||||
{
|
||||
public static function listContainsName(
|
||||
array $list,
|
||||
DOMNode $node,
|
||||
array $options,
|
||||
Closure|null $compare = null
|
||||
): string|false {
|
||||
$allowedNamespaces = $options['allowedNamespaces'];
|
||||
$localName = $node->localName;
|
||||
$compare ??= fn ($expected, $real): bool => $expected === $real;
|
||||
@@ -474,13 +464,19 @@ class Dom
|
||||
}
|
||||
|
||||
// try if we can find an exact namespaced match
|
||||
if ($namespaceUri === $node->namespaceURI && $compare($itemLocal, $localName) === true) {
|
||||
if (
|
||||
$namespaceUri === $node->namespaceURI &&
|
||||
$compare($itemLocal, $localName) === true
|
||||
) {
|
||||
return $item;
|
||||
}
|
||||
|
||||
// also try to match the fully-qualified name
|
||||
// if the document doesn't define the namespace
|
||||
if ($node->namespaceURI === null && $compare($item, $node->nodeName) === true) {
|
||||
if (
|
||||
$node->namespaceURI === null &&
|
||||
$compare($item, $node->nodeName) === true
|
||||
) {
|
||||
return $item;
|
||||
}
|
||||
}
|
||||
@@ -490,9 +486,6 @@ class Dom
|
||||
|
||||
/**
|
||||
* Removes a node from the document
|
||||
*
|
||||
* @param \DOMNode $node
|
||||
* @return void
|
||||
*/
|
||||
public static function remove(DOMNode $node): void
|
||||
{
|
||||
@@ -502,12 +495,12 @@ class Dom
|
||||
/**
|
||||
* Executes an XPath query in the document
|
||||
*
|
||||
* @param string $query
|
||||
* @param \DOMNode|null $node Optional context node for relative queries
|
||||
* @return \DOMNodeList|false
|
||||
*/
|
||||
public function query(string $query, ?DOMNode $node = null)
|
||||
{
|
||||
public function query(
|
||||
string $query,
|
||||
DOMNode|null $node = null
|
||||
): DOMNodeList|false {
|
||||
return (new DOMXPath($this->doc))->query($query, $node);
|
||||
}
|
||||
|
||||
@@ -602,7 +595,6 @@ class Dom
|
||||
* is exported with an XML declaration/
|
||||
* full HTML markup even if the input
|
||||
* didn't have them
|
||||
* @return string
|
||||
*/
|
||||
public function toString(bool $normalize = false): string
|
||||
{
|
||||
@@ -623,9 +615,6 @@ class Dom
|
||||
/**
|
||||
* Removes a node from the document but keeps its children
|
||||
* by moving them one level up
|
||||
*
|
||||
* @param \DOMNode $node
|
||||
* @return void
|
||||
*/
|
||||
public static function unwrap(DOMNode $node): void
|
||||
{
|
||||
@@ -648,7 +637,6 @@ class Dom
|
||||
* @param bool $normalize If set to `true`, the document
|
||||
* is exported with full HTML markup
|
||||
* even if the input didn't have it
|
||||
* @return string
|
||||
*/
|
||||
protected function exportHtml(bool $normalize = false): string
|
||||
{
|
||||
@@ -688,11 +676,13 @@ class Dom
|
||||
* @param bool $normalize If set to `true`, the document
|
||||
* is exported with an XML declaration
|
||||
* even if the input didn't have it
|
||||
* @return string
|
||||
*/
|
||||
protected function exportXml(bool $normalize = false): string
|
||||
{
|
||||
if (Str::contains($this->code, '<?xml ', true) === false && $normalize === false) {
|
||||
if (
|
||||
Str::contains($this->code, '<?xml ', true) === false &&
|
||||
$normalize === false
|
||||
) {
|
||||
// the input didn't contain an XML declaration;
|
||||
// only return child nodes, which omits it
|
||||
$result = [];
|
||||
@@ -714,13 +704,14 @@ class Dom
|
||||
/**
|
||||
* Sanitizes an attribute
|
||||
*
|
||||
* @param \DOMAttr $attr
|
||||
* @param array $options See `Dom::sanitize()`
|
||||
* @param array $errors Array to store additional errors in by reference
|
||||
* @return void
|
||||
*/
|
||||
protected function sanitizeAttr(DOMAttr $attr, array $options, array &$errors): void
|
||||
{
|
||||
protected function sanitizeAttr(
|
||||
DOMAttr $attr,
|
||||
array $options,
|
||||
array &$errors
|
||||
): void {
|
||||
$element = $attr->ownerElement;
|
||||
$name = $attr->nodeName;
|
||||
$value = $attr->value;
|
||||
@@ -762,13 +753,14 @@ class Dom
|
||||
/**
|
||||
* Sanitizes the doctype
|
||||
*
|
||||
* @param \DOMDocumentType $doctype
|
||||
* @param array $options See `Dom::sanitize()`
|
||||
* @param array $errors Array to store additional errors in by reference
|
||||
* @return void
|
||||
*/
|
||||
protected function sanitizeDoctype(DOMDocumentType $doctype, array $options, array &$errors): void
|
||||
{
|
||||
protected function sanitizeDoctype(
|
||||
DOMDocumentType $doctype,
|
||||
array $options,
|
||||
array &$errors
|
||||
): void {
|
||||
try {
|
||||
$this->validateDoctype($doctype, $options);
|
||||
} catch (InvalidArgumentException $e) {
|
||||
@@ -780,13 +772,14 @@ class Dom
|
||||
/**
|
||||
* Sanitizes a single DOM element and its attribute
|
||||
*
|
||||
* @param \DOMElement $element
|
||||
* @param array $options See `Dom::sanitize()`
|
||||
* @param array $errors Array to store additional errors in by reference
|
||||
* @return void
|
||||
*/
|
||||
protected function sanitizeElement(DOMElement $element, array $options, array &$errors): void
|
||||
{
|
||||
protected function sanitizeElement(
|
||||
DOMElement $element,
|
||||
array $options,
|
||||
array &$errors
|
||||
): void {
|
||||
$name = $element->nodeName;
|
||||
|
||||
// check defined namespaces (`xmlns` attributes);
|
||||
@@ -862,13 +855,14 @@ class Dom
|
||||
/**
|
||||
* Sanitizes a single XML processing instruction
|
||||
*
|
||||
* @param \DOMProcessingInstruction $pi
|
||||
* @param array $options See `Dom::sanitize()`
|
||||
* @param array $errors Array to store additional errors in by reference
|
||||
* @return void
|
||||
*/
|
||||
protected function sanitizePI(DOMProcessingInstruction $pi, array $options, array &$errors): void
|
||||
{
|
||||
protected function sanitizePI(
|
||||
DOMProcessingInstruction $pi,
|
||||
array $options,
|
||||
array &$errors
|
||||
): void {
|
||||
$name = $pi->nodeName;
|
||||
|
||||
// check for allow-listed processing instructions
|
||||
@@ -884,15 +878,18 @@ class Dom
|
||||
/**
|
||||
* Validates the document type
|
||||
*
|
||||
* @param \DOMDocumentType $doctype
|
||||
* @param array $options See `Dom::sanitize()`
|
||||
* @return void
|
||||
*
|
||||
* @throws \Kirby\Exception\InvalidArgumentException If the doctype is not valid
|
||||
*/
|
||||
protected function validateDoctype(DOMDocumentType $doctype, array $options): void
|
||||
{
|
||||
if (empty($doctype->publicId) === false || empty($doctype->systemId) === false) {
|
||||
protected function validateDoctype(
|
||||
DOMDocumentType $doctype,
|
||||
array $options
|
||||
): void {
|
||||
if (
|
||||
empty($doctype->publicId) === false ||
|
||||
empty($doctype->systemId) === false
|
||||
) {
|
||||
throw new InvalidArgumentException('The doctype must not reference external files');
|
||||
}
|
||||
|
||||
|
17
kirby/vendor/autoload.php
vendored
17
kirby/vendor/autoload.php
vendored
@@ -3,8 +3,21 @@
|
||||
// autoload.php @generated by Composer
|
||||
|
||||
if (PHP_VERSION_ID < 50600) {
|
||||
echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
|
||||
exit(1);
|
||||
if (!headers_sent()) {
|
||||
header('HTTP/1.1 500 Internal Server Error');
|
||||
}
|
||||
$err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
|
||||
if (!ini_get('display_errors')) {
|
||||
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
|
||||
fwrite(STDERR, $err);
|
||||
} elseif (!headers_sent()) {
|
||||
echo $err;
|
||||
}
|
||||
}
|
||||
trigger_error(
|
||||
$err,
|
||||
E_USER_ERROR
|
||||
);
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/composer/autoload_real.php';
|
||||
|
21
kirby/vendor/composer/ClassLoader.php
vendored
21
kirby/vendor/composer/ClassLoader.php
vendored
@@ -42,6 +42,9 @@ namespace Composer\Autoload;
|
||||
*/
|
||||
class ClassLoader
|
||||
{
|
||||
/** @var \Closure(string):void */
|
||||
private static $includeFile;
|
||||
|
||||
/** @var ?string */
|
||||
private $vendorDir;
|
||||
|
||||
@@ -106,6 +109,7 @@ class ClassLoader
|
||||
public function __construct($vendorDir = null)
|
||||
{
|
||||
$this->vendorDir = $vendorDir;
|
||||
self::initializeIncludeClosure();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -425,7 +429,8 @@ class ClassLoader
|
||||
public function loadClass($class)
|
||||
{
|
||||
if ($file = $this->findFile($class)) {
|
||||
includeFile($file);
|
||||
$includeFile = self::$includeFile;
|
||||
$includeFile($file);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -555,6 +560,14 @@ class ClassLoader
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
private static function initializeIncludeClosure()
|
||||
{
|
||||
if (self::$includeFile !== null) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -564,9 +577,9 @@ class ClassLoader
|
||||
*
|
||||
* @param string $file
|
||||
* @return void
|
||||
* @private
|
||||
*/
|
||||
function includeFile($file)
|
||||
{
|
||||
self::$includeFile = \Closure::bind(static function($file) {
|
||||
include $file;
|
||||
}, null, null);
|
||||
}
|
||||
}
|
||||
|
1
kirby/vendor/composer/autoload_classmap.php
vendored
1
kirby/vendor/composer/autoload_classmap.php
vendored
@@ -51,6 +51,7 @@ return array(
|
||||
'Kirby\\Cms\\Auth\\EmailChallenge' => $baseDir . '/src/Cms/Auth/EmailChallenge.php',
|
||||
'Kirby\\Cms\\Auth\\Status' => $baseDir . '/src/Cms/Auth/Status.php',
|
||||
'Kirby\\Cms\\Block' => $baseDir . '/src/Cms/Block.php',
|
||||
'Kirby\\Cms\\BlockConverter' => $baseDir . '/src/Cms/BlockConverter.php',
|
||||
'Kirby\\Cms\\Blocks' => $baseDir . '/src/Cms/Blocks.php',
|
||||
'Kirby\\Cms\\Blueprint' => $baseDir . '/src/Cms/Blueprint.php',
|
||||
'Kirby\\Cms\\Collection' => $baseDir . '/src/Cms/Collection.php',
|
||||
|
25
kirby/vendor/composer/autoload_real.php
vendored
25
kirby/vendor/composer/autoload_real.php
vendored
@@ -31,25 +31,18 @@ class ComposerAutoloaderInita8011b477bb239488e5d139cdeb7b31e
|
||||
|
||||
$loader->register(true);
|
||||
|
||||
$includeFiles = \Composer\Autoload\ComposerStaticInita8011b477bb239488e5d139cdeb7b31e::$files;
|
||||
foreach ($includeFiles as $fileIdentifier => $file) {
|
||||
composerRequirea8011b477bb239488e5d139cdeb7b31e($fileIdentifier, $file);
|
||||
}
|
||||
|
||||
return $loader;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $fileIdentifier
|
||||
* @param string $file
|
||||
* @return void
|
||||
*/
|
||||
function composerRequirea8011b477bb239488e5d139cdeb7b31e($fileIdentifier, $file)
|
||||
{
|
||||
$filesToLoad = \Composer\Autoload\ComposerStaticInita8011b477bb239488e5d139cdeb7b31e::$files;
|
||||
$requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
|
||||
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
||||
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
|
||||
|
||||
require $file;
|
||||
}
|
||||
}, null, null);
|
||||
foreach ($filesToLoad as $fileIdentifier => $file) {
|
||||
$requireFile($fileIdentifier, $file);
|
||||
}
|
||||
|
||||
return $loader;
|
||||
}
|
||||
}
|
||||
|
1
kirby/vendor/composer/autoload_static.php
vendored
1
kirby/vendor/composer/autoload_static.php
vendored
@@ -151,6 +151,7 @@ class ComposerStaticInita8011b477bb239488e5d139cdeb7b31e
|
||||
'Kirby\\Cms\\Auth\\EmailChallenge' => __DIR__ . '/../..' . '/src/Cms/Auth/EmailChallenge.php',
|
||||
'Kirby\\Cms\\Auth\\Status' => __DIR__ . '/../..' . '/src/Cms/Auth/Status.php',
|
||||
'Kirby\\Cms\\Block' => __DIR__ . '/../..' . '/src/Cms/Block.php',
|
||||
'Kirby\\Cms\\BlockConverter' => __DIR__ . '/../..' . '/src/Cms/BlockConverter.php',
|
||||
'Kirby\\Cms\\Blocks' => __DIR__ . '/../..' . '/src/Cms/Blocks.php',
|
||||
'Kirby\\Cms\\Blueprint' => __DIR__ . '/../..' . '/src/Cms/Blueprint.php',
|
||||
'Kirby\\Cms\\Collection' => __DIR__ . '/../..' . '/src/Cms/Collection.php',
|
||||
|
8
kirby/vendor/composer/installed.php
vendored
8
kirby/vendor/composer/installed.php
vendored
@@ -1,8 +1,8 @@
|
||||
<?php return array(
|
||||
'root' => array(
|
||||
'name' => 'getkirby/cms',
|
||||
'pretty_version' => '3.9.1',
|
||||
'version' => '3.9.1.0',
|
||||
'pretty_version' => '3.9.2',
|
||||
'version' => '3.9.2.0',
|
||||
'reference' => NULL,
|
||||
'type' => 'kirby-cms',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
@@ -38,8 +38,8 @@
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'getkirby/cms' => array(
|
||||
'pretty_version' => '3.9.1',
|
||||
'version' => '3.9.1.0',
|
||||
'pretty_version' => '3.9.2',
|
||||
'version' => '3.9.2.0',
|
||||
'reference' => NULL,
|
||||
'type' => 'kirby-cms',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
|
Reference in New Issue
Block a user