Upgrade to 3.6.5

This commit is contained in:
Bastian Allgeier
2022-04-19 14:59:34 +02:00
parent fee3f5253d
commit 5c64df9e2b
30 changed files with 266 additions and 279 deletions

View File

@@ -1,6 +0,0 @@
{
"recommendations": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode"
]
}

View File

@@ -1,4 +0,0 @@
{
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true
}

View File

@@ -28,7 +28,7 @@ Please post all bug reports in our [issue tracker](https://github.com/getkirby/k
If you have ideas for a feature or enhancement for Kirby, please use our [feedback platform](https://feedback.getkirby.com).
**Translations, bug fixes, code contributions ...**
Read about how to contribute to the development in our [contributing guide](/.github/CONTRIBUTING.md).
Read about how to contribute to the development in our [contributing guide](/CONTRIBUTING.md).

View File

@@ -3,7 +3,7 @@
"description": "The Kirby 3 core",
"license": "proprietary",
"type": "kirby-cms",
"version": "3.6.4",
"version": "3.6.5",
"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": "c466eb7751b8b96b729b80a221d1641e",
"content-hash": "b17823edbb5fd9c0dd25e555fbb192eb",
"packages": [
{
"name": "claviska/simpleimage",

View File

@@ -112,11 +112,11 @@ return function (App $app) {
* Converts the field value to a timestamp or a formatted date
*
* @param \Kirby\Cms\Field $field
* @param string|null $format PHP date formatting string
* @param string|\IntlDateFormatter|null $format PHP date formatting string
* @param string|null $fallback Fallback string for `strtotime` (since 3.2)
* @return string|int
*/
'toDate' => function (Field $field, string $format = null, string $fallback = null) use ($app) {
'toDate' => function (Field $field, $format = null, string $fallback = null) use ($app) {
if (empty($field->value) === true && $fallback === null) {
return null;
}

View File

@@ -1,7 +1,7 @@
{
"account.changeName": "Modifier votre nom",
"account.delete": "Supprimer votre compte",
"account.delete.confirm": "Voulez-vous vraiment supprimer votre compte ? Vous serez déconnecté immédiatement. Votre compte ne pourra pas être récupéré.",
"account.delete.confirm": "Voulez-vous vraiment supprimer votre compte ? Vous serez déconnecté immédiatement. Votre compte ne pourra pas être récupéré.",
"add": "Ajouter",
"author": "Auteur",
@@ -61,7 +61,7 @@
"error.avatar.dimensions.invalid": "Veuillez choisir une image de profil de largeur et hauteur inférieures à 3000 pixels",
"error.avatar.mime.forbidden": "L'image du profil utilisateur doit être un fichier JPEG ou PNG",
"error.blueprint.notFound": "Le blueprint « {name} » na pu être chargé",
"error.blueprint.notFound": "Le blueprint « {name} » na pu être chargé",
"error.blocks.max.plural": "Vous ne devez pas ajouter plus de {max} blocs",
"error.blocks.max.singular": "Vous ne devez pas ajouter plus d'un bloc",
@@ -69,29 +69,29 @@
"error.blocks.min.singular": "Vous devez ajouter au moins un bloc",
"error.blocks.validation": "Il y a une erreur dans le bloc {index}",
"error.email.preset.notFound": "La configuration de courriel « {name} » na pu être trouvé",
"error.email.preset.notFound": "La configuration de courriel « {name} » na pu être trouvé ",
"error.field.converter.invalid": "Convertisseur « {converter} » incorrect",
"error.field.converter.invalid": "Convertisseur « {converter} » incorrect",
"error.file.changeName.empty": "Le nom ne peut être vide",
"error.file.changeName.permission": "Vous nêtes pas autorisé à modifier le nom de « {filename} »",
"error.file.duplicate": "Un fichier nommé « {filename} » existe déjà",
"error.file.extension.forbidden": "Lextension « {extension} » nest pas autorisée",
"error.file.changeName.permission": "Vous nêtes pas autorisé à modifier le nom de « {filename} »",
"error.file.duplicate": "Un fichier nommé « {filename} » existe déjà",
"error.file.extension.forbidden": "Lextension « {extension} » nest pas autorisée",
"error.file.extension.invalid": "Extension non valide : {extension}",
"error.file.extension.missing": "Lextension pour « {filename} » est manquante",
"error.file.extension.missing": "Lextension pour « {filename} » est manquante",
"error.file.maxheight": "La hauteur de l'image ne doit pas excéder {height} pixels",
"error.file.maxsize": "Le fichier est trop volumineux",
"error.file.maxwidth": "La largeur de l'image ne doit pas excéder {width} pixels",
"error.file.mime.differs": "Le fichier transféré doit être du même type de média « {mime} »",
"error.file.mime.forbidden": "Le type de média « {mime} » nest pas autorisé",
"error.file.mime.differs": "Le fichier transféré doit être du même type de média « {mime} »",
"error.file.mime.forbidden": "Le type de média « {mime} » nest pas autorisé",
"error.file.mime.invalid": "Type de média non valide : {mime}",
"error.file.mime.missing": "Le type de média de « {filename} » na pu être détecté",
"error.file.mime.missing": "Le type de média de « {filename} » na pu être détecté",
"error.file.minheight": "La hauteur de l'image doit être au moins {height} pixels",
"error.file.minsize": "Le fichier n'est pas assez volumineux",
"error.file.minwidth": "La largeur de l'image doit être au moins {width} pixels",
"error.file.name.missing": "Veuillez entrer un titre",
"error.file.notFound": "Le fichier « {filename} » na pu être trouvé",
"error.file.orientation": "L'orientation de l'image doit être \"{orientation}\"",
"error.file.notFound": "Le fichier « {filename} » na pu être trouvé",
"error.file.orientation": "L'orientation de l'image doit être « {orientation} »",
"error.file.type.forbidden": "Vous nêtes pas autorisé à transférer des fichiers {type}",
"error.file.type.invalid": "Type de fichier non valide : {type}",
"error.file.undefined": "Le fichier na pu être trouvé",
@@ -113,43 +113,43 @@
"error.offline": "Le Panel est actuellement hors ligne",
"error.page.changeSlug.permission": "Vous nêtes pas autorisé à modifier lidentifiant dURL pour « {slug} »",
"error.page.changeSlug.permission": "Vous nêtes pas autorisé à modifier lidentifiant dURL pour « {slug} »",
"error.page.changeStatus.incomplete": "La page comporte des erreurs et ne peut pas être publiée",
"error.page.changeStatus.permission": "Le statut de cette page ne peut être modifié",
"error.page.changeStatus.toDraft.invalid": "La page « {slug} » ne peut être convertie en brouillon",
"error.page.changeTemplate.invalid": "Le modèle de la page « {slug} » ne peut être changé",
"error.page.changeTemplate.permission": "Vous nêtes pas autorisé à changer le modèle de « {slug} »",
"error.page.changeStatus.toDraft.invalid": "La page « {slug} » ne peut être convertie en brouillon",
"error.page.changeTemplate.invalid": "Le modèle de la page « {slug} » ne peut être changé",
"error.page.changeTemplate.permission": "Vous nêtes pas autorisé à changer le modèle de « {slug} »",
"error.page.changeTitle.empty": "Le titre ne peut être vide",
"error.page.changeTitle.permission": "Vous nêtes pas autorisé à modifier le titre de « {slug} »",
"error.page.create.permission": "Vous nêtes pas autorisé à créer « {slug} »",
"error.page.delete": "La page « {slug} » ne peut être supprimée",
"error.page.changeTitle.permission": "Vous nêtes pas autorisé à modifier le titre de « {slug} »",
"error.page.create.permission": "Vous nêtes pas autorisé à créer « {slug} »",
"error.page.delete": "La page « {slug} » ne peut être supprimée",
"error.page.delete.confirm": "Veuillez saisir le titre de la page pour confirmer",
"error.page.delete.hasChildren": "La page comporte des sous-pages et ne peut pas être supprimée",
"error.page.delete.permission": "Vous nêtes pas autorisé à supprimer « {slug} »",
"error.page.draft.duplicate": "Un brouillon avec lidentifiant dURL « {slug} » existe déjà",
"error.page.duplicate": "Une page avec lidentifiant dURL « {slug} » existe déjà",
"error.page.duplicate.permission": "Vous n'êtes pas autorisé à dupliquer « {slug} »",
"error.page.notFound": "La page « {slug} » na pu être trouvée",
"error.page.delete.permission": "Vous nêtes pas autorisé à supprimer « {slug} »",
"error.page.draft.duplicate": "Un brouillon avec lidentifiant dURL « {slug} » existe déjà",
"error.page.duplicate": "Une page avec lidentifiant dURL « {slug} » existe déjà",
"error.page.duplicate.permission": "Vous n'êtes pas autorisé à dupliquer « {slug} »",
"error.page.notFound": "La page « {slug} » na pu être trouvée",
"error.page.num.invalid": "Veuillez saisir un numéro de position valide. Les numéros ne doivent pas être négatifs.",
"error.page.slug.invalid": "Veuillez entrer un identifiant dURL valide",
"error.page.slug.maxlength": "Lidentifiant dURL doit faire moins de \"{length}\" caractères",
"error.page.sort.permission": "La page « {slug} » ne peut être réordonnée",
"error.page.slug.maxlength": "Lidentifiant dURL doit faire moins de « {length} » caractères",
"error.page.sort.permission": "La page « {slug} » ne peut être réordonnée",
"error.page.status.invalid": "Veuillez choisir un statut de page valide",
"error.page.undefined": "La page na pu être trouvée",
"error.page.update.permission": "Vous nêtes pas autorisé à modifier « {slug} »",
"error.page.update.permission": "Vous nêtes pas autorisé à modifier « {slug} »",
"error.section.files.max.plural": "Vous ne pouvez ajouter plus de {max} fichier(s) à la section « {section} »",
"error.section.files.max.singular": "Vous ne pouvez ajouter plus dun fichier à la section « {section} »",
"error.section.files.min.plural": "La section « {section}\" » requiert au moins {min} fichiers",
"error.section.files.min.singular": "La section « {section}\" » requiert au moins un fichier",
"error.section.files.max.plural": "Vous ne pouvez ajouter plus de {max} fichier(s) à la section « {section} »",
"error.section.files.max.singular": "Vous ne pouvez ajouter plus dun fichier à la section « {section} »",
"error.section.files.min.plural": "La section « {section} » requiert au moins {min} fichiers",
"error.section.files.min.singular": "La section « {section} » requiert au moins un fichier",
"error.section.pages.max.plural": "Vous ne pouvez ajouter plus de {max} pages à la section « {section} »",
"error.section.pages.max.singular": "Vous ne pouvez ajouter plus dune page à la section « {section} »",
"error.section.pages.min.plural": "La section « {section}\" » requiert au moins {min} pages",
"error.section.pages.min.singular": "La section « {section}\" » requiert au moins une page",
"error.section.pages.max.plural": "Vous ne pouvez ajouter plus de {max} pages à la section « {section} »",
"error.section.pages.max.singular": "Vous ne pouvez ajouter plus dune page à la section « {section} »",
"error.section.pages.min.plural": "La section « {section} » requiert au moins {min} pages",
"error.section.pages.min.singular": "La section « {section} » requiert au moins une page",
"error.section.notLoaded": "La section « {name} » na pu être chargée",
"error.section.type.invalid": "Le type de section « {type} » est incorrect",
"error.section.notLoaded": "La section « {name} » na pu être chargée",
"error.section.type.invalid": "Le type de section « {type} » est incorrect",
"error.site.changeTitle.empty": "Le titre ne peut être vide",
"error.site.changeTitle.permission": "Vous nêtes pas autorisé à modifier le titre du site",
@@ -157,46 +157,46 @@
"error.template.default.notFound": "Le modèle par défaut nexiste pas",
"error.unexpected": "Une erreur inattendue est survenue ! Activez le mode de débogage pour plus d'informations : https://getkirby.com/docs/reference/system/options/debug",
"error.unexpected": "Une erreur inattendue est survenue ! Activez le mode de débogage pour plus d'informations : https://getkirby.com/docs/reference/system/options/debug",
"error.user.changeEmail.permission": "Vous nêtes pas autorisé à modifier le courriel de lutilisateur «{name}»",
"error.user.changeLanguage.permission": "Vous nêtes pas autorisé à changer la langue de lutilisateur «{name}»",
"error.user.changeName.permission": "Vous nêtes pas autorisé à modifier le nom de lutilisateur «{name}»",
"error.user.changePassword.permission": "Vous nêtes pas autorisé à changer le mot de passe de lutilisateur «{name}»",
"error.user.changeEmail.permission": "Vous nêtes pas autorisé à modifier le courriel de lutilisateur « {name} »",
"error.user.changeLanguage.permission": "Vous nêtes pas autorisé à changer la langue de lutilisateur « {name} »",
"error.user.changeName.permission": "Vous nêtes pas autorisé à modifier le nom de lutilisateur « {name} »",
"error.user.changePassword.permission": "Vous nêtes pas autorisé à changer le mot de passe de lutilisateur « {name} »",
"error.user.changeRole.lastAdmin": "Le rôle du dernier administrateur ne peut être modifié",
"error.user.changeRole.permission": "Vous nêtes pas autorisé à changer le rôle de lutilisateur «{name}»",
"error.user.changeRole.permission": "Vous nêtes pas autorisé à changer le rôle de lutilisateur « {name} »",
"error.user.changeRole.toAdmin": "Vous nêtes pas autorisé à attribuer le rôle dadministrateur aux utilisateurs",
"error.user.create.permission": "Vous nêtes pas autorisé à créer cet utilisateur",
"error.user.delete": "Lutilisateur «{name}» ne peut être supprimé",
"error.user.delete": "Lutilisateur « {name} » ne peut être supprimé",
"error.user.delete.lastAdmin": "Le dernier administrateur ne peut être supprimé",
"error.user.delete.lastUser": "Le dernier utilisateur ne peut être supprimé",
"error.user.delete.permission": "Vous nêtes pas autorisé à supprimer lutilisateur «{name}»",
"error.user.duplicate": "Un utilisateur avec le courriel «{email}» existe déjà",
"error.user.delete.permission": "Vous nêtes pas autorisé à supprimer lutilisateur « {name} »",
"error.user.duplicate": "Un utilisateur avec le courriel « {email} » existe déjà",
"error.user.email.invalid": "Veuillez saisir un courriel valide",
"error.user.language.invalid": "Veuillez saisir une langue valide",
"error.user.notFound": "Lutilisateur «{name}» na pu être trouvé",
"error.user.notFound": "Lutilisateur « {name} » na pu être trouvé",
"error.user.password.invalid": "Veuillez saisir un mot de passe valide. Les mots de passe doivent comporter au moins 8 caractères.",
"error.user.password.notSame": "Les mots de passe ne sont pas identiques",
"error.user.password.undefined": "Cet utilisateur na pas de mot de passe",
"error.user.password.wrong": "Mot de passe incorrect",
"error.user.role.invalid": "Veuillez saisir un rôle valide",
"error.user.undefined": "Lutilisateur na pu être trouvé",
"error.user.update.permission": "Vous nêtes pas autorisé à modifier lutilisateur «{name}»",
"error.user.update.permission": "Vous nêtes pas autorisé à modifier lutilisateur « {name} »",
"error.validation.accepted": "Veuillez confirmer",
"error.validation.alpha": "Veuillez saisir uniquement des caractères alphabétiques minuscules",
"error.validation.alphanum": "Veuillez ne saisir que des minuscules de a à z et des chiffres de 0 à 9",
"error.validation.between": "Veuillez saisir une valeur entre « {min} » et « {max} »",
"error.validation.between": "Veuillez saisir une valeur entre « {min} » et « {max} »",
"error.validation.boolean": "Veuillez confirmer ou refuser",
"error.validation.contains": "Veuillez saisir une valeur contenant « {needle} »",
"error.validation.contains": "Veuillez saisir une valeur contenant « {needle} »",
"error.validation.date": "Veuillez saisir une date valide",
"error.validation.date.after": "Veuillez saisir une date après {date}",
"error.validation.date.before": "Veuillez saisir une date avant {date}",
"error.validation.date.between": "Veuillez saisir une date entre {min} et {max}",
"error.validation.denied": "Veuillez refuser",
"error.validation.different": "La valeur ne doit pas être « {other} »",
"error.validation.different": "La valeur ne doit pas être « {other} »",
"error.validation.email": "Veuillez saisir un courriel valide",
"error.validation.endswith": "La valeur doit se terminer par « {end} »",
"error.validation.endswith": "La valeur doit se terminer par « {end} »",
"error.validation.filename": "Veuillez saisir un nom de fichier valide",
"error.validation.in": "Veuillez saisir lun des éléments suivants: ({in})",
"error.validation.integer": "Veuillez saisir un entier valide",
@@ -210,14 +210,14 @@
"error.validation.minlength": "Veuillez saisir une valeur plus longue (min. {min} caractères)",
"error.validation.minwords": "Veuillez saisir au moins {min} mot(s)",
"error.validation.more": "Veuillez saisir une valeur supérieure à {min}",
"error.validation.notcontains": "Veuillez saisir une valeur ne contenant pas « {needle} »",
"error.validation.notcontains": "Veuillez saisir une valeur ne contenant pas « {needle} »",
"error.validation.notin": "Veuillez ne saisir aucun des éléments suivants: ({notIn})",
"error.validation.option": "Veuillez sélectionner une option valide",
"error.validation.num": "Veuillez saisir un nombre valide",
"error.validation.required": "Veuillez saisir quelque chose",
"error.validation.same": "Veuillez saisir « {other} »",
"error.validation.size": "La grandeur de la valeur doit être « {size} »",
"error.validation.startswith": "La valeur doit commencer par « {start} »",
"error.validation.same": "Veuillez saisir « {other} »",
"error.validation.size": "La grandeur de la valeur doit être « {size} »",
"error.validation.startswith": "La valeur doit commencer par « {start} »",
"error.validation.time": "Veuillez saisir une heure valide",
"error.validation.time.after": "Veuillez entrer une heure après {time}",
"error.validation.time.before": "Veuillez entrer une heure avant {time}",
@@ -232,9 +232,9 @@
"field.blocks.code.name": "Code",
"field.blocks.code.language": "Langue",
"field.blocks.code.placeholder": "Votre code…",
"field.blocks.delete.confirm": "Voulez-vous vraiment supprimer ce bloc ?",
"field.blocks.delete.confirm.all": "Voulez-vous vraiment supprimer tous les blocs ?",
"field.blocks.delete.confirm.selected": "Voulez-vous vraiment supprimer les blocs sélectionnés ?",
"field.blocks.delete.confirm": "Voulez-vous vraiment supprimer ce bloc ?",
"field.blocks.delete.confirm.all": "Voulez-vous vraiment supprimer tous les blocs ?",
"field.blocks.delete.confirm.selected": "Voulez-vous vraiment supprimer les blocs sélectionnés ?",
"field.blocks.empty": "Pas encore de blocs",
"field.blocks.fieldsets.label": "Veuillez sélectionner un type de bloc…",
"field.blocks.fieldsets.paste": "Presser <kbd>{{ shortcut }}</kbd> pour coller/importer des blocks depuis votre presse-papier",
@@ -275,17 +275,17 @@
"field.files.empty": "Pas encore de fichier sélectionné",
"field.layout.delete": "Supprimer cette disposition",
"field.layout.delete.confirm": "Voulez-vous vraiment supprimer cette disposition ?",
"field.layout.delete.confirm": "Voulez-vous vraiment supprimer cette disposition ?",
"field.layout.empty": "Pas encore de rangées",
"field.layout.select": "Choisir une disposition",
"field.pages.empty": "Pas encore de page sélectionnée",
"field.structure.delete.confirm": "Voulez-vous vraiment supprimer cette ligne?",
"field.structure.delete.confirm": "Voulez-vous vraiment supprimer cette ligne ?",
"field.structure.empty": "Pas encore dentrée",
"field.users.empty": "Pas encore dutilisateur sélectionné",
"file.blueprint": "Ce fichier na pas encore de blueprint. Vous pouvez en définir les paramètres dans <strong>/site/blueprints/files/{blueprint}.yml</strong>",
"file.delete.confirm": "Voulez-vous vraiment supprimer <br><strong>{filename}</strong>&nbsp;?",
"file.delete.confirm": "Voulez-vous vraiment supprimer <br><strong>{filename}</strong> ?",
"file.sort": "Modifier la position",
"files": "Fichiers",
@@ -315,9 +315,9 @@
"language": "Langue",
"language.code": "Code",
"language.convert": "Choisir comme langue par défaut",
"language.convert.confirm": "<p>Souhaitez-vous vraiment convertir <strong>{name}</strong> vers la langue par défaut&nbsp;? Cette action ne peut pas être annulée.</p><p>Si <strong>{name}</strong> a un contenu non traduit, il ny aura plus de solution de secours possible et certaines parties de votre site pourraient être vides.</p>",
"language.convert.confirm": "<p>Souhaitez-vous vraiment convertir <strong>{name}</strong> vers la langue par défaut ? Cette action ne peut pas être annulée.</p><p>Si <strong>{name}</strong> a un contenu non traduit, il ny aura plus de solution de secours possible et certaines parties de votre site pourraient être vides.</p>",
"language.create": "Ajouter une nouvelle langue",
"language.delete.confirm": "Voulez-vous vraiment supprimer la langue <strong>{name}</strong>, ainsi que toutes ses traductions&nbsp;? Cette action ne peut être annulée&nbsp;!",
"language.delete.confirm": "Voulez-vous vraiment supprimer la langue <strong>{name}</strong>, ainsi que toutes ses traductions ? Cette action ne peut être annulée !",
"language.deleted": "La langue a été supprimée",
"language.direction": "Sens de lecture",
"language.direction.ltr": "De gauche à droite",
@@ -367,7 +367,7 @@
"login.reset": "Réinitialiser le mot de passe",
"login.toggleText.code.email": "Se connecter par courriel",
"login.toggleText.code.email-password": "Se connecter avec un mot de passe",
"login.toggleText.password-reset.email": "Mot de passe oublié ?",
"login.toggleText.password-reset.email": "Mot de passe oublié ?",
"login.toggleText.password-reset.email-password": "← Retour à la connexion",
"logout": "Se déconnecter",
@@ -414,7 +414,7 @@
"page.changeStatus.position": "Veuillez sélectionner une position",
"page.changeStatus.select": "Sélectionner un nouveau statut",
"page.changeTemplate": "Changer de modèle",
"page.delete.confirm": "Voulez-vous vraiment supprimer <strong>{title}</strong>&nbsp;?",
"page.delete.confirm": "Voulez-vous vraiment supprimer <strong>{title}</strong> ?",
"page.delete.confirm.subpages": "<strong>Cette page contient des sous-pages</strong>. <br>Toutes les sous-pages seront également supprimées.",
"page.delete.confirm.title": "Veuillez saisir le titre de la page pour confirmer",
"page.draft.create": "Créer un brouillon",
@@ -450,7 +450,7 @@
"replace": "Remplacer",
"retry": "Essayer à nouveau",
"revert": "Revenir",
"revert.confirm": "Voulez-vous vraiment <strong>supprimer toutes les modifications non-enregistrées</strong> ?",
"revert.confirm": "Voulez-vous vraiment <strong>supprimer toutes les modifications non-enregistrées</strong> ?",
"role": "Rôle",
"role.admin.description": "Ladministrateur dispose de tous les droits",
@@ -539,7 +539,7 @@
"user.changeRole.select": "Sélectionner un nouveau rôle",
"user.create": "Ajouter un nouvel utilisateur",
"user.delete": "Supprimer cet utilisateur",
"user.delete.confirm": "Voulez-vous vraiment supprimer <br><strong>{email}</strong>?",
"user.delete.confirm": "Voulez-vous vraiment supprimer <br><strong>{email}</strong> ?",
"users": "Utilisateurs",

View File

@@ -157,7 +157,7 @@
"error.template.default.notFound": "Het standaard template bestaat niet",
"error.unexpected": "An unexpected error occurred! Enable debug mode for more info: https://getkirby.com/docs/reference/system/options/debug",
"error.unexpected": "Een onverwacht fout heeft plaats gevonden! Schakel debug-modus in voor meer informatie: https://getkirby.com/docs/reference/system/options/debug",
"error.user.changeEmail.permission": "Je hebt geen rechten om het e-mailadres van gebruiker \"{name}\" te wijzigen",
"error.user.changeLanguage.permission": "Je hebt geen rechten om de taal voor gebruiker \"{name}\" te wijzigen",

View File

@@ -1,22 +0,0 @@
module.exports = {
extends: [
"eslint:recommended",
"plugin:cypress/recommended",
"plugin:vue/recommended",
"prettier"
],
rules: {
"vue/attributes-order": "error",
"vue/component-definition-name-casing": "off",
"vue/html-closing-bracket-newline": [
"error",
{
singleline: "never",
multiline: "always"
}
],
"vue/multi-word-component-names": "off",
"vue/require-default-prop": "off",
"vue/require-prop-types": "error"
}
};

View File

@@ -1,3 +0,0 @@
{
"trailingComma": "none"
}

File diff suppressed because one or more lines are too long

View File

@@ -1,115 +0,0 @@
/* eslint-env node */
import fs from "fs";
import path from "path";
import { defineConfig } from "vite";
import { createVuePlugin } from "vite-plugin-vue2";
import postcssAutoprefixer from "autoprefixer";
import postcssCsso from "postcss-csso";
import postcssDirPseudoClass from "postcss-dir-pseudo-class";
import postcssLogical from "postcss-logical";
import pluginRewriteAll from "vite-plugin-rewrite-all";
let custom;
try {
custom = require("./vite.config.custom.js");
} catch (err) {
custom = {};
}
export default defineConfig(({ command }) => {
// Tell Kirby that we are in dev mode
if (command === "serve") {
// Create the flag file on start
const runningPath = __dirname + "/.vite-running";
fs.closeSync(fs.openSync(runningPath, "w"));
// Delete the flag file on any kind of exit
for (const eventType of ["exit", "SIGINT", "uncaughtException"]) {
process.on(eventType, function (err) {
if (fs.existsSync(runningPath) === true) {
fs.unlinkSync(runningPath);
}
if (eventType === "uncaughtException") {
console.error(err);
}
process.exit();
});
}
}
const proxy = {
target: process.env.VUE_APP_DEV_SERVER || "http://sandbox.test",
changeOrigin: true,
secure: false
};
return {
plugins: [createVuePlugin(), pluginRewriteAll()],
define: {
// Fix vuelidate error
"process.env.BUILD": JSON.stringify("production")
},
build: {
minify: "terser",
cssCodeSplit: false,
rollupOptions: {
input: "./src/index.js",
output: {
entryFileNames: "js/[name].js",
chunkFileNames: "js/[name].js",
assetFileNames: "[ext]/[name].[ext]"
}
}
},
optimizeDeps: {
entries: "src/**/*.{js,vue}",
exclude: [
"vitest"
]
},
css: {
postcss: {
plugins: [
postcssLogical(),
postcssDirPseudoClass(),
postcssCsso(),
postcssAutoprefixer()
]
}
},
resolve: {
alias: [
{
find: "vue",
replacement: "vue/dist/vue.esm.js"
},
{
find: "@",
replacement: path.resolve(__dirname, "src")
}
]
},
server: {
proxy: {
"/api": proxy,
"/env": proxy,
"/media": proxy
},
...custom
},
test: {
environment: "jsdom",
include: ["**/*.test.js"],
coverage: {
all: true,
exclude: ["**/*.e2e.js", "**/*.test.js"],
extension: ["js", "vue"],
src: "src",
reporter: ["text", "lcov"]
},
setupFiles: ["vitest.setup.js"]
}
};
});

View File

@@ -1,4 +0,0 @@
import Vue from "vue";
Vue.config.productionTip = false;
Vue.config.devtools = false;

View File

@@ -10,6 +10,7 @@ use Kirby\Exception\NotFoundException;
use Kirby\Filesystem\Dir;
use Kirby\Filesystem\F;
use Kirby\Http\Request;
use Kirby\Http\Response;
use Kirby\Http\Router;
use Kirby\Http\Server;
use Kirby\Http\Uri;
@@ -709,14 +710,25 @@ class App
return $this->io(new NotFoundException());
}
// Response Configuration
// (Modified) global response configuration, e.g. in routes
if (is_a($input, 'Kirby\Cms\Responder') === true) {
// 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
return $input->send();
}
// Responses
if (is_a($input, 'Kirby\Http\Response') === true) {
return $input;
$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']);
return new Response($data);
}
// Pages

View File

@@ -353,12 +353,12 @@ class File extends ModelWithContent
/**
* Get the file's last modification time.
*
* @param string|null $format
* @param string|null $handler date or strftime
* @param string|\IntlDateFormatter|null $format
* @param string|null $handler date, intl or strftime
* @param string|null $languageCode
* @return mixed
*/
public function modified(string $format = null, string $handler = null, string $languageCode = null)
public function modified($format = null, string $handler = null, string $languageCode = null)
{
$file = $this->modifiedFile();
$content = $this->modifiedContent($languageCode);

View File

@@ -80,8 +80,24 @@ class FileRules
*/
public static function create(File $file, BaseFile $upload): bool
{
// We want to ensure that we are not creating duplicate files.
// If a file with the same name already exists
if ($file->exists() === true) {
if ($file->sha1() !== $upload->sha1()) {
// $file will be based on the props of the new file,
// to compare templates, we need to get the props of
// the already existing file from meta content file
$existing = $file->parent()->file($file->filename());
// if the new upload is the exact same file
// and uses the same template, we can continue
if (
$file->sha1() === $upload->sha1() &&
$file->template() === $existing->template()
) {
return true;
}
// otherwise throw an error for duplicate file
throw new DuplicateException([
'key' => 'file.duplicate',
'data' => [
@@ -89,7 +105,6 @@ class FileRules
]
]);
}
}
if ($file->permissions()->create() !== true) {
throw new PermissionException('The file cannot be created');

View File

@@ -775,7 +775,11 @@ class Query
// apply it to the dataset and retrieve all rows. make sure to use Collection as the iterator to be able to attach the pagination object
$iterator = $this->iterator;
$collection = $this->offset($pagination->offset())->limit($pagination->limit())->iterator('Collection')->all();
$collection = $this
->offset($pagination->offset())
->limit($pagination->limit())
->iterator('Kirby\Toolkit\Collection')
->all();
$this->iterator($iterator);
@@ -968,6 +972,11 @@ class Query
$this->bindings($sql['bindings']);
} elseif (is_callable($args[0]) === true) {
$query = clone $this;
// since the callback uses its own where condition
// it is necessary to clear/reset the cloned where condition
$query->where = null;
call_user_func($args[0], $query);
// copy over the bindings from the nested query

View File

@@ -853,8 +853,14 @@ abstract class Sql
$query = [];
$bindings = [];
foreach ($values as $key => $value) {
$fields[] = $this->columnName($table, $key, $enforceQualified);
foreach ($values as $column => $value) {
$key = $this->columnName($table, $column, $enforceQualified);
if ($key === null) {
continue;
}
$fields[] = $key;
if (in_array($value, static::$literals, true) === true) {
$query[] = $value ?: 'null';
@@ -896,6 +902,10 @@ abstract class Sql
foreach ($values as $column => $value) {
$key = $this->columnName($table, $column, $enforceQualified);
if ($key === null) {
continue;
}
if (in_array($value, static::$literals, true) === true) {
$query[] = $key . ' = ' . ($value ?: 'null');
continue;

View File

@@ -137,7 +137,7 @@ class Sqlite extends Sql
public function tables(): array
{
return [
'query' => 'SELECT name FROM sqlite_master WHERE type = "table"',
'query' => 'SELECT name FROM sqlite_master WHERE type = "table" OR type = "view"',
'bindings' => []
];
}

View File

@@ -463,11 +463,11 @@ class F
* Get the file's last modification time.
*
* @param string $file
* @param string $format
* @param string $handler date or strftime
* @param string|\IntlDateFormatter|null $format
* @param string $handler date, intl or strftime
* @return mixed
*/
public static function modified(string $file, string $format = null, string $handler = 'date')
public static function modified(string $file, $format = null, string $handler = 'date')
{
if (file_exists($file) !== true) {
return false;

View File

@@ -372,11 +372,11 @@ class File
/**
* Returns the file's last modification time
*
* @param string $format
* @param string|null $handler date or strftime
* @param string|\IntlDateFormatter|null $format
* @param string|null $handler date, intl or strftime
* @return mixed
*/
public function modified(?string $format = null, ?string $handler = null)
public function modified($format = null, ?string $handler = null)
{
$kirby = $this->kirby();

View File

@@ -16,6 +16,11 @@ use Throwable;
*/
class File extends Model
{
/**
* @var \Kirby\Cms\File
*/
protected $model;
/**
* Breadcrumb array
*
@@ -423,11 +428,11 @@ class File extends Model
return [
'next' => function () use ($file, $siblings): ?array {
$next = $siblings->nth($siblings->indexOf($file) + 1);
return $next ? $next->panel()->toLink('filename') : null;
return $this->toPrevNextLink($next, 'filename');
},
'prev' => function () use ($file, $siblings): ?array {
$prev = $siblings->nth($siblings->indexOf($file) - 1);
return $prev ? $prev->panel()->toLink('filename') : null;
return $this->toPrevNextLink($prev, 'filename');
}
];
}

View File

@@ -3,6 +3,7 @@
namespace Kirby\Panel;
use Kirby\Form\Form;
use Kirby\Http\Uri;
use Kirby\Toolkit\A;
/**
@@ -387,6 +388,36 @@ abstract class Model
];
}
/**
* Returns link url and tooltip
* for optional sibling model and
* preserves tab selection
*
* @internal
*
* @param \Kirby\Cms\ModelWithContent|null $model
* @param string $tooltip
* @return array
*/
protected function toPrevNextLink($model = null, string $tooltip = 'title'): ?array
{
if ($model === null) {
return null;
}
$data = $model->panel()->toLink($tooltip);
if ($tab = get('tab')) {
$uri = new Uri($data['link'], [
'query' => ['tab' => $tab]
]);
$data['link'] = $uri->toString();
}
return $data;
}
/**
* Returns the url to the editing view
* in the Panel

View File

@@ -14,6 +14,11 @@ namespace Kirby\Panel;
*/
class Page extends Model
{
/**
* @var \Kirby\Cms\Page
*/
protected $model;
/**
* Breadcrumb array
*
@@ -309,14 +314,8 @@ class Page extends Model
};
return [
'next' => function () use ($siblings) {
$next = $siblings('next')->first();
return $next ? $next->panel()->toLink('title') : null;
},
'prev' => function () use ($siblings) {
$prev = $siblings('prev')->last();
return $prev ? $prev->panel()->toLink('title') : null;
}
'next' => fn () => $this->toPrevNextLink($siblings('next')->first()),
'prev' => fn () => $this->toPrevNextLink($siblings('prev')->last())
];
}

View File

@@ -14,6 +14,11 @@ namespace Kirby\Panel;
*/
class Site extends Model
{
/**
* @var \Kirby\Cms\Site
*/
protected $model;
/**
* Returns the setup for a dropdown option
* which is used in the changes dropdown

View File

@@ -14,6 +14,11 @@ namespace Kirby\Panel;
*/
class User extends Model
{
/**
* @var \Kirby\Cms\User
*/
protected $model;
/**
* Breadcrumb array
*
@@ -193,14 +198,8 @@ class User extends Model
$user = $this->model;
return [
'next' => function () use ($user) {
$next = $user->next();
return $next ? $next->panel()->toLink('username') : null;
},
'prev' => function () use ($user) {
$prev = $user->prev();
return $prev ? $prev->panel()->toLink('username') : null;
}
'next' => fn () => $this->toPrevNextLink($user->next(), 'username'),
'prev' => fn () => $this->toPrevNextLink($user->prev(), 'username')
];
}

View File

@@ -726,4 +726,37 @@ class A
return $array;
}
}
/**
* Filter the array using the given callback
* using both value and key
* @since 3.6.5
*
* @param array $array
* @param callable $callback
* @return array
*/
public static function filter(array $array, callable $callback): array
{
return array_filter($array, $callback, ARRAY_FILTER_USE_BOTH);
}
/**
* Remove key(s) from an array
* @since 3.6.5
*
* @param array $array
* @param int|string|array $keys
* @return array
*/
public static function without(array $array, $keys): array
{
if (is_int($keys) || is_string($keys)) {
$keys = static::wrap($keys);
}
return static::filter($array, function ($value, $key) use ($keys) {
return in_array($key, $keys, true) === false;
});
}
}

View File

@@ -75,7 +75,12 @@ class Pagination
$params = [];
if (is_array($a) === true) {
if (is_a($a, static::class) === true) {
/**
* First argument is a pagination/self object
*/
return $a;
} elseif (is_array($a) === true) {
/**
* First argument is an option array

View File

@@ -2,7 +2,9 @@
namespace Kirby\Toolkit;
use DateTime;
use Exception;
use IntlDateFormatter;
use Kirby\Exception\InvalidArgumentException;
/**
@@ -264,17 +266,33 @@ class Str
* according to locale settings
*
* @param int|null $time
* @param string|null $format
* @param string $handler date or strftime
* @param string|\IntlDateFormatter|null $format
* @param string $handler date, intl or strftime
* @return string|int
*/
public static function date(?int $time = null, ?string $format = null, string $handler = 'date')
public static function date(?int $time = null, $format = null, string $handler = 'date')
{
if (is_null($format) === true) {
return $time;
}
// separately handle strftime to be able
// $format is an IntlDateFormatter instance
if (is_a($format, 'IntlDateFormatter') === true) {
return $format->format($time ?? time());
}
// `intl` handler
if ($handler === 'intl') {
$datetime = new DateTime();
if ($time !== null) {
$datetime->setTimestamp($time);
}
return IntlDateFormatter::formatObject($datetime, $format);
}
// handle `strftime` to be able
// to suppress deprecation warning
// TODO: remove strftime support for PHP 9.0
if ($handler === 'strftime') {

View File

@@ -1,7 +1,7 @@
<?php return array(
'root' => array(
'pretty_version' => '3.6.4',
'version' => '3.6.4.0',
'pretty_version' => '3.6.5',
'version' => '3.6.5.0',
'type' => 'kirby-cms',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
@@ -29,8 +29,8 @@
'dev_requirement' => false,
),
'getkirby/cms' => array(
'pretty_version' => '3.6.4',
'version' => '3.6.4.0',
'pretty_version' => '3.6.5',
'version' => '3.6.5.0',
'type' => 'kirby-cms',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),