Upgrade to 3.4.3

This commit is contained in:
Bastian Allgeier
2020-09-15 10:25:09 +02:00
parent 54b9ba3047
commit d8e797dd9b
108 changed files with 1750 additions and 523 deletions

View File

@@ -1,7 +1,7 @@
{ {
"name": "getkirby/cms", "name": "getkirby/cms",
"description": "The Kirby 3 core", "description": "The Kirby 3 core",
"version": "3.4.2", "version": "3.4.3",
"license": "proprietary", "license": "proprietary",
"keywords": ["kirby", "cms", "core"], "keywords": ["kirby", "cms", "core"],
"homepage": "https://getkirby.com", "homepage": "https://getkirby.com",

34
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", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "eb962e577ae2a9c4e6c5f19bb605e459", "content-hash": "3c8b128ea6de49c70f9ec3056bcb18a2",
"packages": [ "packages": [
{ {
"name": "claviska/simpleimage", "name": "claviska/simpleimage",
@@ -108,23 +108,23 @@
}, },
{ {
"name": "getkirby/composer-installer", "name": "getkirby/composer-installer",
"version": "1.1.4", "version": "1.2.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/getkirby/composer-installer.git", "url": "https://github.com/getkirby/composer-installer.git",
"reference": "2d6b8f5601a31caeeea45623e1643fbb437eb94e" "reference": "240a8b2c275d61b66601feb58222b7d34bc6cf1e"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/getkirby/composer-installer/zipball/2d6b8f5601a31caeeea45623e1643fbb437eb94e", "url": "https://api.github.com/repos/getkirby/composer-installer/zipball/240a8b2c275d61b66601feb58222b7d34bc6cf1e",
"reference": "2d6b8f5601a31caeeea45623e1643fbb437eb94e", "reference": "240a8b2c275d61b66601feb58222b7d34bc6cf1e",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"composer-plugin-api": "^1.0" "composer-plugin-api": "^1.0 || ^2.0"
}, },
"require-dev": { "require-dev": {
"composer/composer": "^1.8", "composer/composer": "^1.8 || 2.0.*@dev",
"phpunit/phpunit": "^7.0" "phpunit/phpunit": "^7.0"
}, },
"type": "composer-plugin", "type": "composer-plugin",
@@ -142,7 +142,7 @@
], ],
"description": "Kirby's custom Composer installer for the Kirby CMS and for Kirby plugins", "description": "Kirby's custom Composer installer for the Kirby CMS and for Kirby plugins",
"homepage": "https://getkirby.com", "homepage": "https://getkirby.com",
"time": "2019-02-11T20:27:36+00:00" "time": "2020-09-13T14:43:34+00:00"
}, },
{ {
"name": "laminas/laminas-escaper", "name": "laminas/laminas-escaper",
@@ -195,31 +195,27 @@
}, },
{ {
"name": "laminas/laminas-zendframework-bridge", "name": "laminas/laminas-zendframework-bridge",
"version": "1.0.4", "version": "1.1.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/laminas/laminas-zendframework-bridge.git", "url": "https://github.com/laminas/laminas-zendframework-bridge.git",
"reference": "fcd87520e4943d968557803919523772475e8ea3" "reference": "6ede70583e101030bcace4dcddd648f760ddf642"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-zendframework-bridge/zipball/fcd87520e4943d968557803919523772475e8ea3", "url": "https://api.github.com/repos/laminas/laminas-zendframework-bridge/zipball/6ede70583e101030bcace4dcddd648f760ddf642",
"reference": "fcd87520e4943d968557803919523772475e8ea3", "reference": "6ede70583e101030bcace4dcddd648f760ddf642",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": "^5.6 || ^7.0" "php": "^5.6 || ^7.0 || ^8.0"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.1", "phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.1 || ^9.3",
"squizlabs/php_codesniffer": "^3.5" "squizlabs/php_codesniffer": "^3.5"
}, },
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": {
"dev-master": "1.0.x-dev",
"dev-develop": "1.1.x-dev"
},
"laminas": { "laminas": {
"module": "Laminas\\ZendFrameworkBridge" "module": "Laminas\\ZendFrameworkBridge"
} }
@@ -243,7 +239,7 @@
"laminas", "laminas",
"zf" "zf"
], ],
"time": "2020-05-20T16:45:56+00:00" "time": "2020-09-14T14:23:00+00:00"
}, },
{ {
"name": "league/color-extractor", "name": "league/color-extractor",

View File

@@ -1,5 +1,6 @@
<?php <?php
// @codeCoverageIgnoreStart
return [ return [
// cms classes // cms classes
'asset' => 'Kirby\Cms\Asset', 'asset' => 'Kirby\Cms\Asset',
@@ -58,3 +59,4 @@ return [
'v' => 'Kirby\Toolkit\V', 'v' => 'Kirby\Toolkit\V',
'xml' => 'Kirby\Toolkit\Xml' 'xml' => 'Kirby\Toolkit\Xml'
]; ];
// @codeCoverageIgnoreEnd

View File

@@ -26,6 +26,24 @@ return [
return $this->page($id)->delete($this->requestBody('force', false)); return $this->page($id)->delete($this->requestBody('force', false));
} }
], ],
[
'pattern' => 'pages/(:any)/blueprint',
'method' => 'GET',
'action' => function (string $id) {
return $this->page($id)->blueprint();
}
],
[
'pattern' => [
'pages/(:any)/blueprints',
// Deprecated: remove in 3.6.0
'pages/(:any)/children/blueprints',
],
'method' => 'GET',
'action' => function (string $id) {
return $this->page($id)->blueprints($this->requestQuery('section'));
}
],
[ [
'pattern' => 'pages/(:any)/children', 'pattern' => 'pages/(:any)/children',
'method' => 'GET', 'method' => 'GET',
@@ -40,13 +58,6 @@ return [
return $this->page($id)->createChild($this->requestBody()); return $this->page($id)->createChild($this->requestBody());
} }
], ],
[
'pattern' => 'pages/(:any)/children/blueprints',
'method' => 'GET',
'action' => function (string $id) {
return $this->page($id)->blueprints($this->requestQuery('section'));
}
],
[ [
'pattern' => 'pages/(:any)/children/search', 'pattern' => 'pages/(:any)/children/search',
'method' => 'GET|POST', 'method' => 'GET|POST',

View File

@@ -32,13 +32,6 @@ return [
return $this->site()->createChild($this->requestBody()); return $this->site()->createChild($this->requestBody());
} }
], ],
[
'pattern' => 'site/children/blueprints',
'method' => 'GET',
'action' => function () {
return $this->site()->blueprints($this->requestQuery('section'));
}
],
[ [
'pattern' => 'site/children/search', 'pattern' => 'site/children/search',
'method' => 'POST', 'method' => 'POST',
@@ -46,6 +39,24 @@ return [
return $this->site()->children()->query($this->requestBody()); return $this->site()->children()->query($this->requestBody());
} }
], ],
[
'pattern' => 'site/blueprint',
'method' => 'GET',
'action' => function () {
return $this->site()->blueprint();
}
],
[
'pattern' => [
'site/blueprints',
// Deprecated: remove in 3.6.0
'site/children/blueprints',
],
'method' => 'GET',
'action' => function () {
return $this->site()->blueprints($this->requestQuery('section'));
}
],
[ [
'pattern' => 'site/find', 'pattern' => 'site/find',
'method' => 'POST', 'method' => 'POST',

View File

@@ -84,6 +84,20 @@ return [
return $this->user($id)->avatar()->delete(); return $this->user($id)->avatar()->delete();
} }
], ],
[
'pattern' => 'users/(:any)/blueprint',
'method' => 'GET',
'action' => function (string $id) {
return $this->user($id)->blueprint();
}
],
[
'pattern' => 'users/(:any)/blueprints',
'method' => 'GET',
'action' => function (string $id) {
return $this->user($id)->blueprints($this->requestQuery('section'));
}
],
[ [
'pattern' => 'users/(:any)/email', 'pattern' => 'users/(:any)/email',
'method' => 'PATCH', 'method' => 'PATCH',
@@ -91,6 +105,15 @@ return [
return $this->user($id)->changeEmail($this->requestBody('email')); return $this->user($id)->changeEmail($this->requestBody('email'));
} }
], ],
[
'pattern' => 'users/(:any)/fields/(:any)/(:all?)',
'method' => 'ALL',
'action' => function (string $id, string $fieldName, string $path = null) {
if ($user = $this->user($id)) {
return $this->fieldApi($user, $fieldName, $path);
}
}
],
[ [
'pattern' => 'users/(:any)/language', 'pattern' => 'users/(:any)/language',
'method' => 'PATCH', 'method' => 'PATCH',
@@ -134,14 +157,4 @@ return [
} }
} }
], ],
[
'pattern' => 'users/(:any)/fields/(:any)/(:all?)',
'method' => 'ALL',
'action' => function (string $id, string $fieldName, string $path = null) {
if ($user = $this->user($id)) {
return $this->fieldApi($user, $fieldName, $path);
}
}
]
]; ];

View File

@@ -601,36 +601,7 @@ function r($condition, $value, $alternative = null)
} }
/** /**
* Rounds the minutes of the given date * Returns the current site object
* by the defined step
*
* @param string $date
* @param int $step
* @return string|null
*/
function timestamp(string $date = null, int $step = null): ?string
{
if (V::date($date) === false) {
return null;
}
$date = strtotime($date);
if ($step === null) {
return $date;
}
$hours = date('H', $date);
$minutes = date('i', $date);
$minutes = floor($minutes / $step) * $step;
$minutes = str_pad($minutes, 2, 0, STR_PAD_LEFT);
$date = date('Y-m-d', $date) . ' ' . $hours . ':' . $minutes;
return strtotime($date);
}
/**
* Returns the currrent site object
* *
* @return \Kirby\Cms\Site * @return \Kirby\Cms\Site
*/ */
@@ -767,6 +738,35 @@ function tc($key, int $count)
return I18n::translateCount($key, $count); return I18n::translateCount($key, $count);
} }
/**
* Rounds the minutes of the given date
* by the defined step
*
* @param string $date
* @param int $step
* @return string|null
*/
function timestamp(string $date = null, int $step = null): ?string
{
if (V::date($date) === false) {
return null;
}
$date = strtotime($date);
if ($step === null) {
return $date;
}
$hours = date('H', $date);
$minutes = date('i', $date);
$minutes = floor($minutes / $step) * $step;
$minutes = str_pad($minutes, 2, 0, STR_PAD_LEFT);
$date = date('Y-m-d', $date) . ' ' . $hours . ':' . $minutes;
return strtotime($date);
}
/** /**
* Translate by key and then replace * Translate by key and then replace
* placeholders in the text * placeholders in the text

View File

@@ -572,6 +572,9 @@ class ParsedownExtra extends Parsedown
# http://stackoverflow.com/q/11309194/200145 # http://stackoverflow.com/q/11309194/200145
$elementMarkup = mb_convert_encoding($elementMarkup, 'HTML-ENTITIES', 'UTF-8'); $elementMarkup = mb_convert_encoding($elementMarkup, 'HTML-ENTITIES', 'UTF-8');
# Ensure that saveHTML() is not remove new line characters. New lines will be split by this character.
$DOMDocument->formatOutput = true;
# http://stackoverflow.com/q/4879946/200145 # http://stackoverflow.com/q/4879946/200145
$DOMDocument->loadHTML($elementMarkup); $DOMDocument->loadHTML($elementMarkup);

View File

@@ -309,7 +309,7 @@
"page.duplicate.pages": "Kopírovat stránky", "page.duplicate.pages": "Kopírovat stránky",
"page.status": "Stav", "page.status": "Stav",
"page.status.draft": "Koncept", "page.status.draft": "Koncept",
"page.status.draft.description": "The page is in draft mode and only visible for logged in editors or via secret link", "page.status.draft.description": "Stránka je ve stavu konceptu a je viditelná pouze pro přihlášené editory, nebo přes tajný odkaz",
"page.status.listed": "Veřejná", "page.status.listed": "Veřejná",
"page.status.listed.description": "Stránka je zveřejněná pro všechny", "page.status.listed.description": "Stránka je zveřejněná pro všechny",
"page.status.unlisted": "Neveřejná", "page.status.unlisted": "Neveřejná",
@@ -331,7 +331,7 @@
"replace": "Nahradit", "replace": "Nahradit",
"retry": "Zkusit znovu", "retry": "Zkusit znovu",
"revert": "Zahodit", "revert": "Zahodit",
"revert.confirm": "Do you really want to <strong>delete all unsaved changes</strong>?", "revert.confirm": "Opravdu chcete <strong>smazat všechny provedené změny</strong>?",
"role": "Role", "role": "Role",
"role.admin.description": "Administrátor má všechna práva", "role.admin.description": "Administrátor má všechna práva",

View File

@@ -31,7 +31,7 @@
"dialog.files.empty": "Keine verfügbaren Dateien", "dialog.files.empty": "Keine verfügbaren Dateien",
"dialog.pages.empty": "Keine verfügbaren Seiten", "dialog.pages.empty": "Keine verfügbaren Seiten",
"dialog.users.empty": "Keine verfügbaren Benutzer*innen", "dialog.users.empty": "Keine verfügbaren Accounts",
"email": "E-Mail", "email": "E-Mail",
"email.placeholder": "mail@beispiel.de", "email.placeholder": "mail@beispiel.de",
@@ -122,31 +122,31 @@
"error.site.changeTitle.empty": "Bitte gib einen Titel an", "error.site.changeTitle.empty": "Bitte gib einen Titel an",
"error.site.changeTitle.permission": "Du kannst den Titel der Seite nicht ändern", "error.site.changeTitle.permission": "Du kannst den Titel der Seite nicht ändern",
"error.site.update.permission": "Du darfst die Seite nicht editieren", "error.site.update.permission": "Du darfst die Seite nicht bearbeiten",
"error.template.default.notFound": "Die \"Default\"-Vorlage existiert nicht", "error.template.default.notFound": "Die \"Default\"-Vorlage existiert nicht",
"error.user.changeEmail.permission": "Du kannst die E-Mailadresse für den Benutzer \"{name}\" nicht ändern", "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 Benutzer \"{name}\" nicht ändern", "error.user.changeLanguage.permission": "Du kannst die Sprache für den Account \"{name}\" nicht ändern",
"error.user.changeName.permission": "Du kannst den Namen für den Benutzer \"{name}\" nicht ändern", "error.user.changeName.permission": "Du kannst den Namen für den Account \"{name}\" nicht ändern",
"error.user.changePassword.permission": "Du kannst das Passwort für den Benutzer \"{name}\" nicht ändern", "error.user.changePassword.permission": "Du kannst das Passwort für den Account \"{name}\" nicht ändern",
"error.user.changeRole.lastAdmin": "Die Rolle des letzten Administrators kann nicht geändert werden", "error.user.changeRole.lastAdmin": "Die Rolle des letzten Accounts mit Administrationsrechten kann nicht geändert werden",
"error.user.changeRole.permission": "Du kannst die Rolle für den Benutzer \"{name}\" nicht ändern", "error.user.changeRole.permission": "Du kannst die Rolle für den Benutzer \"{name}\" nicht ändern",
"error.user.changeRole.toAdmin": "Du darfst die Admin Rolle nicht an andere Benutzer*innen vergeben", "error.user.changeRole.toAdmin": "Du darfst die Admin Rolle nicht an andere Accounts vergeben",
"error.user.create.permission": "Du kannst diesen Benutzer nicht anlegen", "error.user.create.permission": "Du darfst diesen Account nicht anlegen",
"error.user.delete": "Der Benutzer \"{name}\" konnte nicht gelöscht werden", "error.user.delete": "Der Account \"{name}\" konnte nicht gelöscht werden",
"error.user.delete.lastAdmin": "Du kannst den letzten Admin nicht l\u00f6schen", "error.user.delete.lastAdmin": "Du kannst den letzten Account mit Administrationsrechten nicht löschen",
"error.user.delete.lastUser": "Der letzte Benutzer kann nicht gelöscht werden", "error.user.delete.lastUser": "Der letzte Account kann nicht gelöscht werden",
"error.user.delete.permission": "Du darfst den Benutzer \"{name}\" nicht löschen", "error.user.delete.permission": "Du darfst den Account \"{name}\" nicht löschen",
"error.user.duplicate": "Ein Benutzer mit der E-Mailadresse \"{email}\" besteht bereits", "error.user.duplicate": "Ein Account mit der E-Mailadresse \"{email}\" besteht bereits",
"error.user.email.invalid": "Bitte gib eine gültige E-Mailadresse an", "error.user.email.invalid": "Bitte gib eine gültige E-Mailadresse an",
"error.user.language.invalid": "Bitte gib eine gültige Sprache an", "error.user.language.invalid": "Bitte gib eine gültige Sprache an",
"error.user.notFound": "Der Benutzer \"{name}\" wurde nicht gefunden", "error.user.notFound": "Der Account \"{name}\" wurde nicht gefunden",
"error.user.password.invalid": "Bitte gib ein gültiges Passwort ein. Passwörter müssen mindestens 8 Zeichen lang sein.", "error.user.password.invalid": "Bitte gib ein gültiges Passwort ein. Passwörter müssen mindestens 8 Zeichen lang sein.",
"error.user.password.notSame": "Die Passwörter stimmen nicht überein", "error.user.password.notSame": "Die Passwörter stimmen nicht überein",
"error.user.password.undefined": "Der Benutzer hat kein Passwort", "error.user.password.undefined": "Der Account hat kein Passwort",
"error.user.role.invalid": "Bitte gib eine gültige Rolle an", "error.user.role.invalid": "Bitte gib eine gültige Rolle an",
"error.user.update.permission": "Du darfst den den Benutzer \"{name}\" nicht editieren", "error.user.update.permission": "Du darfst den den Account \"{name}\" nicht bearbeiten",
"error.validation.accepted": "Bitte bestätige", "error.validation.accepted": "Bitte bestätige",
"error.validation.alpha": "Bitte gib nur Zeichen zwischen A und Z ein", "error.validation.alpha": "Bitte gib nur Zeichen zwischen A und Z ein",
@@ -191,7 +191,7 @@
"field.pages.empty": "Keine Seiten ausgewählt", "field.pages.empty": "Keine Seiten ausgewählt",
"field.structure.delete.confirm": "Willst du diesen Eintrag wirklich l\u00f6schen?", "field.structure.delete.confirm": "Willst du diesen Eintrag wirklich l\u00f6schen?",
"field.structure.empty": "Es bestehen keine Eintr\u00e4ge.", "field.structure.empty": "Es bestehen keine Eintr\u00e4ge.",
"field.users.empty": "Keine Benutzer ausgewählt", "field.users.empty": "Keine Accounts ausgewählt",
"file.delete.confirm": "Willst du die Datei <strong>{filename}</strong> <br>wirklich löschen?", "file.delete.confirm": "Willst du die Datei <strong>{filename}</strong> <br>wirklich löschen?",
@@ -255,7 +255,7 @@
"lock.file.isLocked": "Die Datei wird von {email} bearbeitet und kann nicht geändert werden.", "lock.file.isLocked": "Die Datei wird von {email} bearbeitet und kann nicht geändert werden.",
"lock.page.isLocked": "Die Seite wird von {email} bearbeitet und kann nicht geändert werden.", "lock.page.isLocked": "Die Seite wird von {email} bearbeitet und kann nicht geändert werden.",
"lock.unlock": "Entsperren", "lock.unlock": "Entsperren",
"lock.isUnlocked": "Deine ungespeicherten Änderungen wurden von einem anderen Benutzer überschrieben. Du kannst sie herunterladen, um sie manuell einzufügen. ", "lock.isUnlocked": "Deine ungespeicherten Änderungen wurden von einem anderen Account überschrieben. Du kannst sie herunterladen, um sie manuell einzufügen. ",
"login": "Anmelden", "login": "Anmelden",
"login.remember": "Angemeldet bleiben", "login.remember": "Angemeldet bleiben",
@@ -309,9 +309,9 @@
"page.duplicate.pages": "Seiten kopieren", "page.duplicate.pages": "Seiten kopieren",
"page.status": "Status", "page.status": "Status",
"page.status.draft": "Entwurf", "page.status.draft": "Entwurf",
"page.status.draft.description": "Die Seite ist im Entwurfsmodus und ist nur für angemeldete Benutzer*innen oder über den geheimen Link sichtbar", "page.status.draft.description": "Die Seite ist im Entwurfsmodus und ist nur nach Anmeldung oder über den geheimen Link sichtbar",
"page.status.listed": "Öffentlich", "page.status.listed": "Öffentlich",
"page.status.listed.description": "Die Seite ist öffentlich für alle Besucher", "page.status.listed.description": "Die Seite ist öffentlich für alle",
"page.status.unlisted": "Ungelistet", "page.status.unlisted": "Ungelistet",
"page.status.unlisted.description": "Die Seite kann nur über die URL aufgerufen werden", "page.status.unlisted.description": "Die Seite kann nur über die URL aufgerufen werden",
@@ -334,10 +334,10 @@
"revert.confirm": "Willst du wirklich alle ungespeicherten Änderungen verwerfen? ", "revert.confirm": "Willst du wirklich alle ungespeicherten Änderungen verwerfen? ",
"role": "Rolle", "role": "Rolle",
"role.admin.description": "Administrator*innen haben alle Rechte", "role.admin.description": "Admins haben alle Rechte",
"role.admin.title": "Administrator*in", "role.admin.title": "Admin",
"role.all": "Alle", "role.all": "Alle",
"role.empty": "Keine Benutzer mit dieser Rolle", "role.empty": "Keine Accounts mit dieser Rolle",
"role.description.placeholder": "Keine Beschreibung", "role.description.placeholder": "Keine Beschreibung",
"role.nobody.description": "Dies ist die Platzhalterrolle ohne Rechte", "role.nobody.description": "Dies ist die Platzhalterrolle ohne Rechte",
"role.nobody.title": "Niemand", "role.nobody.title": "Niemand",
@@ -394,21 +394,21 @@
"url": "Url", "url": "Url",
"url.placeholder": "https://beispiel.de", "url.placeholder": "https://beispiel.de",
"user": "Benutzer", "user": "Account",
"user.blueprint": "Du kannst zusätzliche Felder und Bereiche für diese Benutzerrolle in <strong>/site/blueprints/users/{role}.yml</strong> anlegen", "user.blueprint": "Du kannst zusätzliche Felder und Bereiche für diese Rolle in <strong>/site/blueprints/users/{role}.yml</strong> anlegen",
"user.changeEmail": "E-Mail ändern", "user.changeEmail": "E-Mail ändern",
"user.changeLanguage": "Sprache ändern", "user.changeLanguage": "Sprache ändern",
"user.changeName": "Benutzer umbenennen", "user.changeName": "Account umbenennen",
"user.changePassword": "Passwort ändern", "user.changePassword": "Passwort ändern",
"user.changePassword.new": "Neues Passwort", "user.changePassword.new": "Neues Passwort",
"user.changePassword.new.confirm": "Wiederhole das Passwort …", "user.changePassword.new.confirm": "Wiederhole das Passwort …",
"user.changeRole": "Rolle ändern", "user.changeRole": "Rolle ändern",
"user.changeRole.select": "Neue Rolle auswählen", "user.changeRole.select": "Neue Rolle auswählen",
"user.create": "Neuen Benutzer anlegen", "user.create": "Neuen Account anlegen",
"user.delete": "Benutzer löschen", "user.delete": "Account löschen",
"user.delete.confirm": "Willst du den Benutzer <br><strong>{email}</strong> wirklich löschen?", "user.delete.confirm": "Willst du den Account <br><strong>{email}</strong> wirklich löschen?",
"users": "Benutzer", "users": "Accounts",
"version": "Version", "version": "Version",
@@ -416,7 +416,7 @@
"view.installation": "Installation", "view.installation": "Installation",
"view.settings": "Einstellungen", "view.settings": "Einstellungen",
"view.site": "Seite", "view.site": "Seite",
"view.users": "Benutzer", "view.users": "Accounts",
"welcome": "Willkommen", "welcome": "Willkommen",
"year": "Jahr" "year": "Jahr"

View File

@@ -102,6 +102,7 @@
"error.page.notFound": "The page \"{slug}\" cannot be found", "error.page.notFound": "The page \"{slug}\" cannot be found",
"error.page.num.invalid": "Please enter a valid sorting number. Numbers must not be negative.", "error.page.num.invalid": "Please enter a valid sorting number. Numbers must not be negative.",
"error.page.slug.invalid": "Please enter a valid URL prefix", "error.page.slug.invalid": "Please enter a valid URL prefix",
"error.page.slug.maxlength": "Slug length must be less than \"{length}\" characters",
"error.page.sort.permission": "The page \"{slug}\" cannot be sorted", "error.page.sort.permission": "The page \"{slug}\" cannot be sorted",
"error.page.status.invalid": "Please set a valid page status", "error.page.status.invalid": "Please set a valid page status",
"error.page.undefined": "The page cannot be found", "error.page.undefined": "The page cannot be found",

View File

@@ -309,7 +309,7 @@
"page.duplicate.pages": "Salin halaman", "page.duplicate.pages": "Salin halaman",
"page.status": "Status", "page.status": "Status",
"page.status.draft": "Draf", "page.status.draft": "Draf",
"page.status.draft.description": "The page is in draft mode and only visible for logged in editors or via secret link", "page.status.draft.description": "Halaman ini ada pada mode draf dan hanya dapat dilihat oleh penyunting atau via tautan rahasia",
"page.status.listed": "Publik", "page.status.listed": "Publik",
"page.status.listed.description": "Halaman publik untuk siapapun", "page.status.listed.description": "Halaman publik untuk siapapun",
"page.status.unlisted": "Tidak tercantum", "page.status.unlisted": "Tidak tercantum",
@@ -331,7 +331,7 @@
"replace": "Ganti", "replace": "Ganti",
"retry": "Coba lagi", "retry": "Coba lagi",
"revert": "Kembalikan", "revert": "Kembalikan",
"revert.confirm": "Do you really want to <strong>delete all unsaved changes</strong>?", "revert.confirm": "Anda yakin <strong>menghapus semua perubahan yang belum tersimpan</strong>?",
"role": "Peran", "role": "Peran",
"role.admin.description": "Admin memiliki semua izin", "role.admin.description": "Admin memiliki semua izin",

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -32,7 +32,7 @@ class Api
/** /**
* Authentication callback * Authentication callback
* *
* @var Closure * @var \Closure
*/ */
protected $authentication; protected $authentication;
@@ -67,14 +67,14 @@ class Api
/** /**
* The current route * The current route
* *
* @var Route * @var \Kirby\Http\Route
*/ */
protected $route; protected $route;
/** /**
* The Router instance * The Router instance
* *
* @var Router * @var \Kirby\Http\Router
*/ */
protected $router; protected $router;
@@ -107,6 +107,7 @@ class Api
* @param string $method * @param string $method
* @param array $args * @param array $args
* @return mixed * @return mixed
* @throws \Kirby\Exception\NotFoundException
*/ */
public function __call(string $method, array $args = []) public function __call(string $method, array $args = [])
{ {
@@ -141,7 +142,7 @@ class Api
/** /**
* Returns the authentication callback * Returns the authentication callback
* *
* @return Closure|null * @return \Closure|null
*/ */
public function authentication() public function authentication()
{ {
@@ -152,10 +153,12 @@ class Api
* Execute an API call for the given path, * Execute an API call for the given path,
* request method and optional request data * request method and optional request data
* *
* @param string $path * @param string|null $path
* @param string $method * @param string $method
* @param array $requestData * @param array $requestData
* @return mixed * @return mixed
* @throws \Kirby\Exception\NotFoundException
* @throws \Exception
*/ */
public function call(string $path = null, string $method = 'GET', array $requestData = []) public function call(string $path = null, string $method = 'GET', array $requestData = [])
{ {
@@ -209,7 +212,10 @@ class Api
// restore old pagination validation mode // restore old pagination validation mode
Pagination::$validate = $validate; Pagination::$validate = $validate;
if (is_object($output) === true && is_a($output, 'Kirby\\Http\\Response') !== true) { if (
is_object($output) === true &&
is_a($output, 'Kirby\\Http\\Response') !== true
) {
return $this->resolve($output)->toResponse(); return $this->resolve($output)->toResponse();
} }
@@ -222,8 +228,8 @@ class Api
* @param string $name * @param string $name
* @param array|null $collection * @param array|null $collection
* @return \Kirby\Api\Collection * @return \Kirby\Api\Collection
*
* @throws \Kirby\Exception\NotFoundException If no collection for `$name` exists * @throws \Kirby\Exception\NotFoundException If no collection for `$name` exists
* @throws \Exception
*/ */
public function collection(string $name, $collection = null) public function collection(string $name, $collection = null)
{ {
@@ -314,7 +320,7 @@ class Api
/** /**
* Returns an API model instance by name * Returns an API model instance by name
* *
* @param string $name * @param string|null $name
* @param mixed $object * @param mixed $object
* @return \Kirby\Api\Model * @return \Kirby\Api\Model
* *
@@ -351,8 +357,8 @@ class Api
* Can either get all the data * Can either get all the data
* or certain parts of it. * or certain parts of it.
* *
* @param string $type * @param string|null $type
* @param string $key * @param string|null $key
* @param mixed $default * @param mixed $default
* @return mixed * @return mixed
*/ */
@@ -375,7 +381,7 @@ class Api
/** /**
* Returns the request body if available * Returns the request body if available
* *
* @param string $key * @param string|null $key
* @param mixed $default * @param mixed $default
* @return mixed * @return mixed
*/ */
@@ -387,7 +393,7 @@ class Api
/** /**
* Returns the files from the request if available * Returns the files from the request if available
* *
* @param string $key * @param string|null $key
* @param mixed $default * @param mixed $default
* @return mixed * @return mixed
*/ */
@@ -399,7 +405,7 @@ class Api
/** /**
* Returns all headers from the request if available * Returns all headers from the request if available
* *
* @param string $key * @param string|null $key
* @param mixed $default * @param mixed $default
* @return mixed * @return mixed
*/ */
@@ -421,7 +427,7 @@ class Api
/** /**
* Returns the request query if available * Returns the request query if available
* *
* @param string $key * @param string|null $key
* @param mixed $default * @param mixed $default
* @return mixed * @return mixed
*/ */
@@ -469,7 +475,7 @@ class Api
/** /**
* Setter for the authentication callback * Setter for the authentication callback
* *
* @param Closure $authentication * @param \Closure|null $authentication
* @return self * @return self
*/ */
protected function setAuthentication(Closure $authentication = null) protected function setAuthentication(Closure $authentication = null)
@@ -481,7 +487,7 @@ class Api
/** /**
* Setter for the collections definition * Setter for the collections definition
* *
* @param array $collections * @param array|null $collections
* @return self * @return self
*/ */
protected function setCollections(array $collections = null) protected function setCollections(array $collections = null)
@@ -495,7 +501,7 @@ class Api
/** /**
* Setter for the injected data * Setter for the injected data
* *
* @param array $data * @param array|null $data
* @return self * @return self
*/ */
protected function setData(array $data = null) protected function setData(array $data = null)
@@ -519,7 +525,7 @@ class Api
/** /**
* Setter for the model definitions * Setter for the model definitions
* *
* @param array $models * @param array|null $models
* @return self * @return self
*/ */
protected function setModels(array $models = null) protected function setModels(array $models = null)
@@ -534,7 +540,7 @@ class Api
/** /**
* Setter for the request data * Setter for the request data
* *
* @param array $requestData * @param array|null $requestData
* @return self * @return self
*/ */
protected function setRequestData(array $requestData = null) protected function setRequestData(array $requestData = null)
@@ -552,7 +558,7 @@ class Api
/** /**
* Setter for the request method * Setter for the request method
* *
* @param string $requestMethod * @param string|null $requestMethod
* @return self * @return self
*/ */
protected function setRequestMethod(string $requestMethod = null) protected function setRequestMethod(string $requestMethod = null)
@@ -564,7 +570,7 @@ class Api
/** /**
* Setter for the route definitions * Setter for the route definitions
* *
* @param array $routes * @param array|null $routes
* @return self * @return self
*/ */
protected function setRoutes(array $routes = null) protected function setRoutes(array $routes = null)
@@ -668,10 +674,10 @@ class Api
* an exception. Kirby exceptions will * an exception. Kirby exceptions will
* have more information * have more information
* *
* @param Exception $e * @param \Throwable $e
* @return array * @return array
*/ */
public function responseForException($e): array public function responseForException(Throwable $e): array
{ {
// prepare the result array for all exception types // prepare the result array for all exception types
$result = [ $result = [
@@ -710,14 +716,17 @@ class Api
/** /**
* Upload helper method * Upload helper method
* *
* @param Closure $callback * move_uploaded_file() not working with unit test
* Added debug parameter for testing purposes as we did in the Email class
*
* @param \Closure $callback
* @param bool $single * @param bool $single
* @param bool $debug
* @return array * @return array
* *
* @throws \Exception If request has no files * @throws \Exception If request has no files or there was an error with the upload
* @throws \Exception If there was an error with the upload
*/ */
public function upload(Closure $callback, $single = false): array public function upload(Closure $callback, $single = false, $debug = false): array
{ {
$trials = 0; $trials = 0;
$uploads = []; $uploads = [];
@@ -776,7 +785,7 @@ class Api
// move the file to a location including the extension, // move the file to a location including the extension,
// for better mime detection // for better mime detection
if (move_uploaded_file($upload['tmp_name'], $source) === false) { if ($debug === false && move_uploaded_file($upload['tmp_name'], $source) === false) {
throw new Exception(t('upload.error.cantMove')); throw new Exception(t('upload.error.cantMove'));
} }

View File

@@ -19,12 +19,39 @@ use Kirby\Toolkit\Str;
*/ */
class Collection class Collection
{ {
/**
* @var \Kirby\Api\Api
*/
protected $api; protected $api;
/**
* @var mixed|null
*/
protected $data; protected $data;
/**
* @var mixed|null
*/
protected $model; protected $model;
/**
* @var mixed|null
*/
protected $select; protected $select;
/**
* @var mixed|null
*/
protected $view; protected $view;
/**
* Collection constructor
*
* @param \Kirby\Api\Api $api
* @param mixed|null $data
* @param array $schema
* @throws \Exception
*/
public function __construct(Api $api, $data = null, array $schema) public function __construct(Api $api, $data = null, array $schema)
{ {
$this->api = $api; $this->api = $api;
@@ -48,6 +75,11 @@ class Collection
} }
} }
/**
* @param string|array|null $keys
* @return self
* @throws \Exception
*/
public function select($keys = null) public function select($keys = null)
{ {
if ($keys === false) { if ($keys === false) {
@@ -66,6 +98,11 @@ class Collection
return $this; return $this;
} }
/**
* @return array
* @throws \Kirby\Exception\NotFoundException
* @throws \Exception
*/
public function toArray(): array public function toArray(): array
{ {
$result = []; $result = [];
@@ -87,6 +124,11 @@ class Collection
return $result; return $result;
} }
/**
* @return array
* @throws \Kirby\Exception\NotFoundException
* @throws \Exception
*/
public function toResponse(): array public function toResponse(): array
{ {
if ($query = $this->api->requestQuery('query')) { if ($query = $this->api->requestQuery('query')) {
@@ -124,6 +166,10 @@ class Collection
]; ];
} }
/**
* @param string $view
* @return self
*/
public function view(string $view) public function view(string $view)
{ {
$this->view = $view; $this->view = $view;

View File

@@ -3,13 +3,12 @@
namespace Kirby\Api; namespace Kirby\Api;
use Exception; use Exception;
use Kirby\Toolkit\Str; use Kirby\Toolkit\Str;
/** /**
* The API Model class can be wrapped around any * The API Model class can be wrapped around any
* kind of object. Each model defines a set of properties that * kind of object. Each model defines a set of properties that
* are availabel in REST calls. Those properties are defined as * are available in REST calls. Those properties are defined as
* simple Closures which are resolved on demand. This is inspired * simple Closures which are resolved on demand. This is inspired
* by GraphQLs architecture and makes it possible to load * by GraphQLs architecture and makes it possible to load
* only the model data that is needed for the current API call. * only the model data that is needed for the current API call.
@@ -22,12 +21,39 @@ use Kirby\Toolkit\Str;
*/ */
class Model class Model
{ {
/**
* @var \Kirby\Api\Api
*/
protected $api; protected $api;
/**
* @var mixed|null
*/
protected $data; protected $data;
/**
* @var array|mixed
*/
protected $fields; protected $fields;
/**
* @var mixed|null
*/
protected $select; protected $select;
/**
* @var array|mixed
*/
protected $views; protected $views;
/**
* Model constructor
*
* @param \Kirby\Api\Api $api
* @param null $data
* @param array $schema
* @throws \Exception
*/
public function __construct(Api $api, $data = null, array $schema) public function __construct(Api $api, $data = null, array $schema)
{ {
$this->api = $api; $this->api = $api;
@@ -56,6 +82,11 @@ class Model
} }
} }
/**
* @param null $keys
* @return self
* @throws \Exception
*/
public function select($keys = null) public function select($keys = null)
{ {
if ($keys === false) { if ($keys === false) {
@@ -74,6 +105,10 @@ class Model
return $this; return $this;
} }
/**
* @return array
* @throws \Exception
*/
public function selection(): array public function selection(): array
{ {
$select = $this->select; $select = $this->select;
@@ -117,6 +152,11 @@ class Model
return $selection; return $selection;
} }
/**
* @return array
* @throws \Kirby\Exception\NotFoundException
* @throws \Exception
*/
public function toArray(): array public function toArray(): array
{ {
$select = $this->selection(); $select = $this->selection();
@@ -158,6 +198,11 @@ class Model
return $result; return $result;
} }
/**
* @return array
* @throws \Kirby\Exception\NotFoundException
* @throws \Exception
*/
public function toResponse(): array public function toResponse(): array
{ {
$model = $this; $model = $this;
@@ -178,6 +223,11 @@ class Model
]; ];
} }
/**
* @param string $name
* @return self
* @throws \Exception
*/
public function view(string $name) public function view(string $name)
{ {
if ($name === 'any') { if ($name === 'any') {

View File

@@ -27,7 +27,7 @@ class Api extends BaseApi
* Execute an API call for the given path, * Execute an API call for the given path,
* request method and optional request data * request method and optional request data
* *
* @param string $path * @param string|null $path
* @param string $method * @param string $method
* @param array $requestData * @param array $requestData
* @return mixed * @return mixed
@@ -50,8 +50,9 @@ class Api extends BaseApi
/** /**
* @param mixed $model * @param mixed $model
* @param string $name * @param string $name
* @param string $path * @param string|null $path
* @return mixed * @return mixed
* @throws \Kirby\Exception\NotFoundException if the field type cannot be found or the field cannot be loaded
*/ */
public function fieldApi($model, string $name, string $path = null) public function fieldApi($model, string $name, string $path = null)
{ {
@@ -73,8 +74,9 @@ class Api extends BaseApi
} }
} }
// it can get this error only if $name is an empty string as $name = ''
if ($field === null) { if ($field === null) {
throw new NotFoundException('The field "' . $fieldNames . '" could not be found'); throw new NotFoundException('No field could be loaded');
} }
$fieldApi = $this->clone([ $fieldApi = $this->clone([
@@ -89,9 +91,10 @@ class Api extends BaseApi
* Returns the file object for the given * Returns the file object for the given
* parent path and filename * parent path and filename
* *
* @param string $path Path to file's parent model * @param string|null $path Path to file's parent model
* @param string $filename Filename * @param string $filename Filename
* @return \Kirby\Cms\File|null * @return \Kirby\Cms\File|null
* @throws \Kirby\Exception\NotFoundException if the file cannot be found
*/ */
public function file(string $path = null, string $filename) public function file(string $path = null, string $filename)
{ {
@@ -115,6 +118,8 @@ class Api extends BaseApi
* *
* @param string $path Path to parent model * @param string $path Path to parent model
* @return \Kirby\Cms\Model|null * @return \Kirby\Cms\Model|null
* @throws \Kirby\Exception\InvalidArgumentException if the model type is invalid
* @throws \Kirby\Exception\NotFoundException if the model cannot be found
*/ */
public function parent(string $path) public function parent(string $path)
{ {
@@ -151,7 +156,7 @@ class Api extends BaseApi
$model = $kirby->user(basename($path)); $model = $kirby->user(basename($path));
break; break;
default: default:
throw new InvalidArgumentException('Invalid file model type: ' . $modelType); throw new InvalidArgumentException('Invalid model type: ' . $modelType);
} }
if ($model) { if ($model) {
@@ -188,6 +193,7 @@ class Api extends BaseApi
* *
* @param string $id Page's id * @param string $id Page's id
* @return \Kirby\Cms\Page|null * @return \Kirby\Cms\Page|null
* @throws \Kirby\Exception\NotFoundException if the page cannot be found
*/ */
public function page(string $id) public function page(string $id)
{ {
@@ -206,6 +212,12 @@ class Api extends BaseApi
]); ]);
} }
/**
* Returns the current Session instance
*
* @param array $options Additional options, see the session component
* @return \Kirby\Session\Session
*/
public function session(array $options = []) public function session(array $options = [])
{ {
return $this->kirby->session(array_merge([ return $this->kirby->session(array_merge([
@@ -214,7 +226,10 @@ class Api extends BaseApi
} }
/** /**
* Setter for the parent Kirby instance
*
* @param \Kirby\Cms\App $kirby * @param \Kirby\Cms\App $kirby
* @return self
*/ */
protected function setKirby(App $kirby) protected function setKirby(App $kirby)
{ {
@@ -237,8 +252,9 @@ class Api extends BaseApi
* returns the current authenticated user if no * returns the current authenticated user if no
* id is passed * id is passed
* *
* @param string $id User's id * @param string|null $id User's id
* @return \Kirby\Cms\User|null * @return \Kirby\Cms\User|null
* @throws \Kirby\Exception\NotFoundException if the user for the given id cannot be found
*/ */
public function user(string $id = null) public function user(string $id = null)
{ {

View File

@@ -256,7 +256,7 @@ class App
/** /**
* Sets the directory structure * Sets the directory structure
* *
* @param array $roots * @param array|null $roots
* @return self * @return self
*/ */
protected function bakeRoots(array $roots = null) protected function bakeRoots(array $roots = null)
@@ -269,7 +269,7 @@ class App
/** /**
* Sets the Url structure * Sets the Url structure
* *
* @param array $urls * @param array|null $urls
* @return self * @return self
*/ */
protected function bakeUrls(array $urls = null) protected function bakeUrls(array $urls = null)
@@ -314,8 +314,8 @@ class App
/** /**
* Calls any Kirby route * Calls any Kirby route
* *
* @param string $path * @param string|null $path
* @param string $method * @param string|null $method
* @return mixed * @return mixed
*/ */
public function call(string $path = null, string $method = null) public function call(string $path = null, string $method = null)
@@ -504,7 +504,7 @@ class App
} }
/** /**
* Detect the prefered language from the visitor object * Detect the preferred language from the visitor object
* *
* @return \Kirby\Cms\Language * @return \Kirby\Cms\Language
*/ */
@@ -586,7 +586,7 @@ class App
/** /**
* Returns the current App instance * Returns the current App instance
* *
* @param \Kirby\Cms\App $instance * @param \Kirby\Cms\App|null $instance
* @param bool $lazy If `true`, the instance is only returned if already existing * @param bool $lazy If `true`, the instance is only returned if already existing
* @return self|null * @return self|null
*/ */
@@ -699,7 +699,7 @@ class App
* *
* @internal * @internal
* @param string $type * @param string $type
* @param string $value * @param string|null $value
* @param array $attr * @param array $attr
* @param array $data * @param array $data
* @return string * @return string
@@ -717,7 +717,7 @@ class App
* KirbyTags Parser * KirbyTags Parser
* *
* @internal * @internal
* @param string $text * @param string|null $text
* @param array $data * @param array $data
* @return string * @return string
*/ */
@@ -734,7 +734,7 @@ class App
* Parses KirbyTags first and Markdown afterwards * Parses KirbyTags first and Markdown afterwards
* *
* @internal * @internal
* @param string $text * @param string|null $text
* @param array $data * @param array $data
* @param bool $inline * @param bool $inline
* @return string * @return string
@@ -825,7 +825,7 @@ class App
* Parses Markdown * Parses Markdown
* *
* @internal * @internal
* @param string $text * @param string|null $text
* @param bool $inline * @param bool $inline
* @return string * @return string
*/ */
@@ -945,8 +945,12 @@ class App
$this->site = null; $this->site = null;
} }
if (isset($options['slugs']) === true) { // checks custom language definition for slugs
$this->i18n(); if ($slugsOption = $this->option('slugs')) {
// slugs option must be set to string or "slugs" => ["language" => "de"] as array
if (is_string($slugsOption) === true || isset($slugsOption['language']) === true) {
$this->i18n();
}
} }
} }
@@ -956,7 +960,7 @@ class App
/** /**
* Returns any page from the content folder * Returns any page from the content folder
* *
* @param string $id|null * @param string|null $id
* @param \Kirby\Cms\Page|\Kirby\Cms\Site|null $parent * @param \Kirby\Cms\Page|\Kirby\Cms\Site|null $parent
* @param bool $drafts * @param bool $drafts
* @return \Kirby\Cms\Page|null * @return \Kirby\Cms\Page|null
@@ -1028,9 +1032,10 @@ class App
* Path resolver for the router * Path resolver for the router
* *
* @internal * @internal
* @param string $path * @param string|null $path
* @param string|null $language * @param string|null $language
* @return mixed * @return mixed
* @throws \Kirby\Exception\NotFoundException if the home page cannot be found
*/ */
public function resolve(string $path = null, string $language = null) public function resolve(string $path = null, string $language = null)
{ {
@@ -1211,7 +1216,7 @@ class App
/** /**
* Create your own set of languages * Create your own set of languages
* *
* @param array $languages * @param array|null $languages
* @return self * @return self
*/ */
protected function setLanguages(array $languages = null) protected function setLanguages(array $languages = null)
@@ -1233,7 +1238,7 @@ class App
* Sets the request path that is * Sets the request path that is
* used for the router * used for the router
* *
* @param string $path * @param string|null $path
* @return self * @return self
*/ */
protected function setPath(string $path = null) protected function setPath(string $path = null)
@@ -1245,7 +1250,7 @@ class App
/** /**
* Sets the request * Sets the request
* *
* @param array $request * @param array|null $request
* @return self * @return self
*/ */
protected function setRequest(array $request = null) protected function setRequest(array $request = null)
@@ -1260,7 +1265,7 @@ class App
/** /**
* Create your own set of roles * Create your own set of roles
* *
* @param array $roles * @param array|null $roles
* @return self * @return self
*/ */
protected function setRoles(array $roles = null) protected function setRoles(array $roles = null)
@@ -1277,7 +1282,7 @@ class App
/** /**
* Sets a custom Site object * Sets a custom Site object
* *
* @param \Kirby\Cms\Site|array $site * @param \Kirby\Cms\Site|array|null $site
* @return self * @return self
*/ */
protected function setSite($site = null) protected function setSite($site = null)
@@ -1321,7 +1326,7 @@ class App
* Applies the smartypants rule on the text * Applies the smartypants rule on the text
* *
* @internal * @internal
* @param string $text * @param string|null $text
* @return string * @return string
*/ */
public function smartypants(string $text = null): string public function smartypants(string $text = null): string
@@ -1469,6 +1474,7 @@ class App
* the composer.json (Keep that up to date! :)) * the composer.json (Keep that up to date! :))
* *
* @return string|null * @return string|null
* @throws \Kirby\Exception\LogicException if the Kirby version cannot be detected
*/ */
public static function version(): ?string public static function version(): ?string
{ {
@@ -1492,7 +1498,7 @@ class App
/** /**
* Returns the visitor object * Returns the visitor object
* *
* @return \Kirby\Cms\Visitor * @return \Kirby\Http\Visitor
*/ */
public function visitor() public function visitor()
{ {

View File

@@ -92,7 +92,7 @@ trait AppPlugins
* *
* @internal * @internal
* @param array $extensions * @param array $extensions
* @param \Kirby\Cms\Plugin $plugin The plugin which defined those extensions * @param \Kirby\Cms\Plugin $plugin|null The plugin which defined those extensions
* @return array * @return array
*/ */
public function extend(array $extensions, Plugin $plugin = null): array public function extend(array $extensions, Plugin $plugin = null): array
@@ -361,7 +361,7 @@ trait AppPlugins
/** /**
* Registers additional routes * Registers additional routes
* *
* @param array|Closure $routes * @param array|\Closure $routes
* @return array * @return array
*/ */
protected function extendRoutes($routes): array protected function extendRoutes($routes): array
@@ -398,8 +398,8 @@ trait AppPlugins
/** /**
* Registers SmartyPants component * Registers SmartyPants component
* *
* @param Closure $smartypants * @param \Closure $smartypants
* @return Closure * @return \Closure
*/ */
protected function extendSmartypants(Closure $smartypants) protected function extendSmartypants(Closure $smartypants)
{ {
@@ -455,7 +455,6 @@ trait AppPlugins
* so they can be used as plugins for plugins * so they can be used as plugins for plugins
* for example. * for example.
* *
* @param string $type
* @param array $extensions * @param array $extensions
* @return array * @return array
*/ */
@@ -567,7 +566,7 @@ trait AppPlugins
* the options array. I.e. hooks and routes can be * the options array. I.e. hooks and routes can be
* setup from the config. * setup from the config.
* *
* @return array * @return void
*/ */
protected function extensionsFromOptions() protected function extensionsFromOptions()
{ {
@@ -582,7 +581,6 @@ trait AppPlugins
/** /**
* Apply all plugin extensions * Apply all plugin extensions
* *
* @param array $plugins
* @return void * @return void
*/ */
protected function extensionsFromPlugins() protected function extensionsFromPlugins()
@@ -701,7 +699,7 @@ trait AppPlugins
* of a core component * of a core component
* *
* @param string $component * @param string $component
* @return \Closure | false * @return \Closure|false
*/ */
public function nativeComponent(string $component) public function nativeComponent(string $component)
{ {
@@ -714,6 +712,7 @@ trait AppPlugins
* @param string $name * @param string $name
* @param array|null $extends If null is passed it will be used as getter. Otherwise as factory. * @param array|null $extends If null is passed it will be used as getter. Otherwise as factory.
* @return \Kirby\Cms\Plugin|null * @return \Kirby\Cms\Plugin|null
* @throws \Kirby\Exception\DuplicateException
*/ */
public static function plugin(string $name, array $extends = null) public static function plugin(string $name, array $extends = null)
{ {
@@ -739,7 +738,7 @@ trait AppPlugins
* Loading only happens on the first call. * Loading only happens on the first call.
* *
* @internal * @internal
* @param array $plugins Can be used to overwrite the plugins registry * @param array|null $plugins Can be used to overwrite the plugins registry
* @return array * @return array
*/ */
public function plugins(array $plugins = null): array public function plugins(array $plugins = null): array

View File

@@ -2,6 +2,7 @@
namespace Kirby\Cms; namespace Kirby\Cms;
use Exception;
use Kirby\Data\Data; use Kirby\Data\Data;
use Kirby\Toolkit\F; use Kirby\Toolkit\F;
use Kirby\Toolkit\I18n; use Kirby\Toolkit\I18n;
@@ -64,17 +65,25 @@ trait AppTranslations
I18n::$translations = []; I18n::$translations = [];
if (isset($this->options['slugs']) === true) { // checks custom language definition for slugs
$file = $this->root('i18n:rules') . '/' . $this->options['slugs'] . '.json'; if ($slugsOption = $this->option('slugs')) {
// checks setting in two different ways
// "slugs" => "de" or "slugs" => ["language" => "de"]
$slugsLanguage = is_string($slugsOption) === true ? $slugsOption : ($slugsOption['language'] ?? null);
if (F::exists($file) === true) { // load custom slugs language if it's defined
try { if ($slugsLanguage !== null) {
$data = Data::read($file); $file = $this->root('i18n:rules') . '/' . $slugsLanguage . '.json';
} catch (\Exception $e) {
$data = []; if (F::exists($file) === true) {
try {
$data = Data::read($file);
} catch (Exception $e) {
$data = [];
}
Str::$language = $data;
} }
Str::$language = $data;
} }
} }
} }
@@ -84,7 +93,7 @@ trait AppTranslations
* Otherwise fall back to the default language * Otherwise fall back to the default language
* *
* @internal * @internal
* @param string $languageCode * @param string|null $languageCode
* @return \Kirby\Cms\Language|null * @return \Kirby\Cms\Language|null
*/ */
public function setCurrentLanguage(string $languageCode = null) public function setCurrentLanguage(string $languageCode = null)
@@ -111,7 +120,7 @@ trait AppTranslations
* Set the current translation * Set the current translation
* *
* @internal * @internal
* @param string $translationCode * @param string|null $translationCode
* @return void * @return void
*/ */
public function setCurrentTranslation(string $translationCode = null): void public function setCurrentTranslation(string $translationCode = null): void

View File

@@ -43,6 +43,7 @@ trait AppUsers
* impersonation will be reset afterwards * impersonation will be reset afterwards
* @return mixed If called without callback: User that was impersonated; * @return mixed If called without callback: User that was impersonated;
* if called with callback: Return value from the callback * if called with callback: Return value from the callback
* @throws \Throwable
*/ */
public function impersonate(?string $who = null, ?Closure $callback = null) public function impersonate(?string $who = null, ?Closure $callback = null)
{ {
@@ -82,7 +83,7 @@ trait AppUsers
/** /**
* Create your own set of app users * Create your own set of app users
* *
* @param array $users * @param array|null $users
* @return \Kirby\Cms\App * @return \Kirby\Cms\App
*/ */
protected function setUsers(array $users = null) protected function setUsers(array $users = null)

View File

@@ -64,6 +64,8 @@ class Auth
* *
* @param \Kirby\Http\Request\Auth\BasicAuth|null $auth * @param \Kirby\Http\Request\Auth\BasicAuth|null $auth
* @return \Kirby\Cms\User|null * @return \Kirby\Cms\User|null
* @throws \Kirby\Exception\InvalidArgumentException if the authorization header is invalid
* @throws \Kirby\Exception\PermissionException if basic authentication is not allowed
*/ */
public function currentUserFromBasicAuth(BasicAuth $auth = null) public function currentUserFromBasicAuth(BasicAuth $auth = null)
{ {
@@ -137,6 +139,7 @@ class Auth
* *
* @param string|null $who User ID or email address * @param string|null $who User ID or email address
* @return \Kirby\Cms\User|null * @return \Kirby\Cms\User|null
* @throws \Kirby\Exception\NotFoundException if the given user cannot be found
*/ */
public function impersonate(?string $who = null) public function impersonate(?string $who = null)
{ {

View File

@@ -38,7 +38,7 @@ class Blueprint
* Magic getter/caller for any blueprint prop * Magic getter/caller for any blueprint prop
* *
* @param string $key * @param string $key
* @param array $arguments * @param array|null $arguments
* @return mixed * @return mixed
*/ */
public function __call(string $key, array $arguments = null) public function __call(string $key, array $arguments = null)
@@ -50,6 +50,7 @@ class Blueprint
* Creates a new blueprint object with the given props * Creates a new blueprint object with the given props
* *
* @param array $props * @param array $props
* @throws \Kirby\Exception\InvalidArgumentException If the blueprint model is missing
*/ */
public function __construct(array $props) public function __construct(array $props)
{ {
@@ -215,7 +216,7 @@ class Blueprint
* Create a new blueprint for a model * Create a new blueprint for a model
* *
* @param string $name * @param string $name
* @param string $fallback * @param string|null $fallback
* @param \Kirby\Cms\Model $model * @param \Kirby\Cms\Model $model
* @return self * @return self
*/ */
@@ -263,6 +264,7 @@ class Blueprint
* *
* @param string $name * @param string $name
* @return array * @return array
* @throws \Kirby\Exception\NotFoundException If the blueprint cannot be found
*/ */
public static function find(string $name): array public static function find(string $name): array
{ {
@@ -398,6 +400,10 @@ class Blueprint
return $columns; return $columns;
} }
/**
* @param array $items
* @return string
*/
public static function helpList(array $items): string public static function helpList(array $items): string
{ {
$md = []; $md = [];
@@ -414,6 +420,7 @@ class Blueprint
* *
* @param array|string $props * @param array|string $props
* @return array * @return array
* @throws \Kirby\Exception\InvalidArgumentException If the filed name is missing or the field type is invalid
*/ */
public static function fieldProps($props): array public static function fieldProps($props): array
{ {
@@ -499,7 +506,7 @@ class Blueprint
$fieldProps = []; $fieldProps = [];
} }
// unset / remove field if its propperty is false // unset / remove field if its property is false
if ($fieldProps === false) { if ($fieldProps === false) {
unset($fields[$fieldName]); unset($fields[$fieldName]);
continue; continue;
@@ -582,7 +589,7 @@ class Blueprint
{ {
foreach ($sections as $sectionName => $sectionProps) { foreach ($sections as $sectionName => $sectionProps) {
// unset / remove section if its propperty is false // unset / remove section if its property is false
if ($sectionProps === false) { if ($sectionProps === false) {
unset($sections[$sectionName]); unset($sections[$sectionName]);
continue; continue;
@@ -668,7 +675,7 @@ class Blueprint
foreach ($tabs as $tabName => $tabProps) { foreach ($tabs as $tabName => $tabProps) {
// unset / remove tab if its propperty is false // unset / remove tab if its property is false
if ($tabProps === false) { if ($tabProps === false) {
unset($tabs[$tabName]); unset($tabs[$tabName]);
continue; continue;

View File

@@ -54,7 +54,7 @@ class Collection extends BaseCollection
* Creates a new Collection with the given objects * Creates a new Collection with the given objects
* *
* @param array $objects * @param array $objects
* @param object $parent * @param object|null $parent
*/ */
public function __construct($objects = [], $parent = null) public function __construct($objects = [], $parent = null)
{ {
@@ -101,6 +101,7 @@ class Collection extends BaseCollection
/** /**
* Appends an element to the data array * Appends an element to the data array
* *
* @param mixed ...$args
* @param mixed $key Optional collection key, will be determined from the item if not given * @param mixed $key Optional collection key, will be determined from the item if not given
* @param mixed $item * @param mixed $item
* @return \Kirby\Cms\Collection * @return \Kirby\Cms\Collection
@@ -126,6 +127,7 @@ class Collection extends BaseCollection
* @param string $field * @param string $field
* @param bool $i Ignore upper/lowercase for group names * @param bool $i Ignore upper/lowercase for group names
* @return \Kirby\Cms\Collection * @return \Kirby\Cms\Collection
* @throws \Kirby\Exception\Exception
*/ */
public function groupBy($field, bool $i = true) public function groupBy($field, bool $i = true)
{ {
@@ -203,7 +205,9 @@ class Collection extends BaseCollection
{ {
$collection = $this->clone(); $collection = $this->clone();
foreach ($keys as $key) { foreach ($keys as $key) {
if (is_a($key, 'Kirby\Toolkit\Collection') === true) { if (is_array($key) === true) {
return $this->not(...$key);
} elseif (is_a($key, 'Kirby\Toolkit\Collection') === true) {
$collection = $collection->not(...$key->keys()); $collection = $collection->not(...$key->keys());
} elseif (is_object($key) === true) { } elseif (is_object($key) === true) {
$key = $key->id(); $key = $key->id();
@@ -240,6 +244,7 @@ class Collection extends BaseCollection
/** /**
* Prepends an element to the data array * Prepends an element to the data array
* *
* @param mixed ...$args
* @param mixed $key Optional collection key, will be determined from the item if not given * @param mixed $key Optional collection key, will be determined from the item if not given
* @param mixed $item * @param mixed $item
* @return \Kirby\Cms\Collection * @return \Kirby\Cms\Collection
@@ -307,7 +312,7 @@ class Collection extends BaseCollection
/** /**
* Searches the collection * Searches the collection
* *
* @param string $query * @param string|null $query
* @param array $params * @param array $params
* @return self * @return self
*/ */
@@ -321,7 +326,7 @@ class Collection extends BaseCollection
* to an array. This can also take a callback * to an array. This can also take a callback
* function to further modify the array result. * function to further modify the array result.
* *
* @param Closure $map * @param \Closure|null $map
* @return array * @return array
*/ */
public function toArray(Closure $map = null): array public function toArray(Closure $map = null): array

View File

@@ -112,6 +112,7 @@ class Collections
* *
* @param string $name * @param string $name
* @return mixed * @return mixed
* @throws \Kirby\Exception\NotFoundException
*/ */
public function load(string $name) public function load(string $name)
{ {

View File

@@ -146,7 +146,7 @@ class Content
* Returns either a single field object * Returns either a single field object
* or all registered fields * or all registered fields
* *
* @param string $key * @param string|null $key
* @return \Kirby\Cms\Field|array * @return \Kirby\Cms\Field|array
*/ */
public function get(string $key = null) public function get(string $key = null)
@@ -250,7 +250,7 @@ class Content
* Updates the content and returns * Updates the content and returns
* a cloned object * a cloned object
* *
* @param array $content * @param array|null $content
* @param bool $overwrite * @param bool $overwrite
* @return self * @return self
*/ */

View File

@@ -62,6 +62,7 @@ class ContentLock
* Sets lock with the current user * Sets lock with the current user
* *
* @return bool * @return bool
* @throws \Kirby\Exception\DuplicateException
*/ */
public function create(): bool public function create(): bool
{ {
@@ -153,6 +154,7 @@ class ContentLock
* Removes lock of current user * Removes lock of current user
* *
* @return bool * @return bool
* @throws \Kirby\Exception\LogicException
*/ */
public function remove(): bool public function remove(): bool
{ {
@@ -217,6 +219,7 @@ class ContentLock
* throws exception if none is authenticated * throws exception if none is authenticated
* *
* @return \Kirby\Cms\User * @return \Kirby\Cms\User
* @throws \Kirby\Exception\PermissionException
*/ */
protected function user(): User protected function user(): User
{ {

View File

@@ -52,6 +52,7 @@ class ContentLocks
* *
* @param string $file * @param string $file
* @return void * @return void
* @throws \Kirby\Exception\Exception
*/ */
protected function closeHandle(string $file) protected function closeHandle(string $file)
{ {
@@ -123,6 +124,7 @@ class ContentLocks
* @param string $file * @param string $file
* @param bool $create Whether to create the file if it does not exist * @param bool $create Whether to create the file if it does not exist
* @return resource|null File handle * @return resource|null File handle
* @throws \Kirby\Exception\Exception
*/ */
protected function handle(string $file, bool $create = false) protected function handle(string $file, bool $create = false)
{ {
@@ -168,6 +170,7 @@ class ContentLocks
* @param \Kirby\Cms\ModelWithContent $model * @param \Kirby\Cms\ModelWithContent $model
* @param array $data * @param array $data
* @return bool * @return bool
* @throws \Kirby\Exception\Exception
*/ */
public function set(ModelWithContent $model, array $data): bool public function set(ModelWithContent $model, array $data): bool
{ {

View File

@@ -172,7 +172,7 @@ class ContentTranslation
} }
/** /**
* @param array $content * @param array|null $content
* @return self * @return self
*/ */
protected function setContent(array $content = null) protected function setContent(array $content = null)
@@ -192,7 +192,7 @@ class ContentTranslation
} }
/** /**
* @param string $slug * @param string|null $slug
* @return self * @return self
*/ */
protected function setSlug(string $slug = null) protected function setSlug(string $slug = null)
@@ -225,7 +225,7 @@ class ContentTranslation
} }
/** /**
* Converts the most imporant translation * Converts the most important translation
* props to an array * props to an array
* *
* @return array * @return array

View File

@@ -26,7 +26,7 @@ class Dir extends \Kirby\Toolkit\Dir
* *
* @param string $dir * @param string $dir
* @param string $contentExtension * @param string $contentExtension
* @param array $contentIgnore * @param array|null $contentIgnore
* @param bool $multilang * @param bool $multilang
* @return array * @return array
*/ */

View File

@@ -53,6 +53,11 @@ class Email
$this->props['transport'] = $this->options['transport'] ?? []; $this->props['transport'] = $this->options['transport'] ?? [];
} }
// add predefined beforeSend option
if (isset($this->props['beforeSend']) === false) {
$this->props['beforeSend'] = $this->options['beforeSend'] ?? null;
}
// transform model objects to values // transform model objects to values
$this->transformUserSingle('from', 'fromName'); $this->transformUserSingle('from', 'fromName');
$this->transformUserSingle('replyTo', 'replyToName'); $this->transformUserSingle('replyTo', 'replyToName');
@@ -71,6 +76,7 @@ class Email
* *
* @param string|array $preset Preset name or simple prop array * @param string|array $preset Preset name or simple prop array
* @return array * @return array
* @throws \Kirby\Exception\NotFoundException
*/ */
protected function preset($preset): array protected function preset($preset): array
{ {
@@ -95,6 +101,7 @@ class Email
* to the result * to the result
* *
* @return void * @return void
* @throws \Kirby\Exception\NotFoundException
*/ */
protected function template(): void protected function template(): void
{ {

View File

@@ -276,6 +276,7 @@ class Event
* @param string $name * @param string $name
* @param mixed $value * @param mixed $value
* @return void * @return void
* @throws \Kirby\Exception\InvalidArgumentException
*/ */
public function updateArgument(string $name, $value): void public function updateArgument(string $name, $value): void
{ {

View File

@@ -2,7 +2,6 @@
namespace Kirby\Cms; namespace Kirby\Cms;
use Closure;
use Kirby\Exception\InvalidArgumentException; use Kirby\Exception\InvalidArgumentException;
/** /**
@@ -93,7 +92,7 @@ class Field
/** /**
* Creates a new field object * Creates a new field object
* *
* @param object $parent * @param object|null $parent
* @param string $key * @param string $key
* @param mixed $value * @param mixed $value
*/ */
@@ -108,7 +107,7 @@ class Field
* Simplifies the var_dump result * Simplifies the var_dump result
* *
* @see Field::toArray * @see Field::toArray
* @return void * @return array
*/ */
public function __debugInfo() public function __debugInfo()
{ {
@@ -232,8 +231,9 @@ class Field
* the modified field will be returned. Otherwise it * the modified field will be returned. Otherwise it
* will return the field value. * will return the field value.
* *
* @param string|Closure $value * @param string|\Closure $value
* @return mixed * @return mixed
* @throws \Kirby\Exception\InvalidArgumentException
*/ */
public function value($value = null) public function value($value = null)
{ {

View File

@@ -231,34 +231,31 @@ class File extends ModelWithContent
* gets dragged onto a textarea * gets dragged onto a textarea
* *
* @internal * @internal
* @param string $type (null|auto|kirbytext|markdown) * @param string|null $type (null|auto|kirbytext|markdown)
* @param bool $absolute * @param bool $absolute
* @return string * @return string
*/ */
public function dragText(string $type = null, bool $absolute = false): string public function dragText(string $type = null, bool $absolute = false): string
{ {
$type = $type ?? 'auto'; $type = $this->dragTextType($type);
$url = $absolute ? $this->id() : $this->filename();
if ($type === 'auto') { if ($dragTextFromCallback = $this->dragTextFromCallback($type, $url)) {
$type = option('panel.kirbytext', true) ? 'kirbytext' : 'markdown'; return $dragTextFromCallback;
} }
$url = $absolute ? $this->id() : $this->filename(); if ($type === 'markdown') {
if ($this->type() === 'image') {
switch ($type) { return '![' . $this->alt() . '](' . $url . ')';
case 'markdown': } else {
if ($this->type() === 'image') { return '[' . $this->filename() . '](' . $url . ')';
return '![' . $this->alt() . '](' . $url . ')'; }
} else { } else {
return '[' . $this->filename() . '](' . $url . ')'; if ($this->type() === 'image') {
} return '(image: ' . $url . ')';
// no break } else {
default: return '(file: ' . $url . ')';
if ($this->type() === 'image') { }
return '(image: ' . $url . ')';
} else {
return '(file: ' . $url . ')';
}
} }
} }
@@ -392,6 +389,7 @@ class File extends ModelWithContent
* @deprecated 3.0.0 Use `File::content()` instead * @deprecated 3.0.0 Use `File::content()` instead
* *
* @return \Kirby\Cms\Content * @return \Kirby\Cms\Content
* @codeCoverageIgnore
*/ */
public function meta() public function meta()
{ {
@@ -403,7 +401,7 @@ class File extends ModelWithContent
/** /**
* Get the file's last modification time. * Get the file's last modification time.
* *
* @param string $format * @param string|null $format
* @param string|null $handler date or strftime * @param string|null $handler date or strftime
* @param string|null $languageCode * @param string|null $languageCode
* @return mixed * @return mixed
@@ -460,7 +458,7 @@ class File extends ModelWithContent
* Panel icon definition * Panel icon definition
* *
* @internal * @internal
* @param array $params * @param array|null $params
* @return array * @return array
*/ */
public function panelIcon(array $params = null): array public function panelIcon(array $params = null): array
@@ -677,7 +675,7 @@ class File extends ModelWithContent
/** /**
* Sets the parent model object * Sets the parent model object
* *
* @param \Kirby\Cms\Model $parent * @param \Kirby\Cms\Model|null $parent
* @return self * @return self
*/ */
protected function setParent(Model $parent = null) protected function setParent(Model $parent = null)
@@ -700,7 +698,7 @@ class File extends ModelWithContent
} }
/** /**
* @param string $template * @param string|null $template
* @return self * @return self
*/ */
protected function setTemplate(string $template = null) protected function setTemplate(string $template = null)
@@ -712,7 +710,7 @@ class File extends ModelWithContent
/** /**
* Sets the url * Sets the url
* *
* @param string $url * @param string|null $url
* @return self * @return self
*/ */
protected function setUrl(string $url = null) protected function setUrl(string $url = null)

View File

@@ -26,6 +26,7 @@ trait FileActions
* @param string $name * @param string $name
* @param bool $sanitize * @param bool $sanitize
* @return self * @return self
* @throws \Kirby\Exception\LogicException
*/ */
public function changeName(string $name, bool $sanitize = true) public function changeName(string $name, bool $sanitize = true)
{ {
@@ -161,6 +162,8 @@ trait FileActions
* *
* @param array $props * @param array $props
* @return self * @return self
* @throws \Kirby\Exception\InvalidArgumentException
* @throws \Kirby\Exception\LogicException
*/ */
public static function create(array $props) public static function create(array $props)
{ {
@@ -264,6 +267,7 @@ trait FileActions
* @param string $name * @param string $name
* @param bool $sanitize * @param bool $sanitize
* @return self * @return self
* @codeCoverageIgnore
*/ */
public function rename(string $name, bool $sanitize = true) public function rename(string $name, bool $sanitize = true)
{ {
@@ -281,6 +285,7 @@ trait FileActions
* *
* @param string $source * @param string $source
* @return self * @return self
* @throws \Kirby\Exception\LogicException
*/ */
public function replace(string $source) public function replace(string $source)
{ {

View File

@@ -27,6 +27,7 @@ trait FileFoundation
* @param string $method * @param string $method
* @param array $arguments * @param array $arguments
* @return mixed * @return mixed
* @throws \Kirby\Exception\BadMethodCallException
*/ */
public function __call(string $method, array $arguments = []) public function __call(string $method, array $arguments = [])
{ {
@@ -187,7 +188,7 @@ trait FileFoundation
/** /**
* Setter for the root * Setter for the root
* *
* @param string $root * @param string|null $root
* @return self * @return self
*/ */
protected function setRoot(string $root = null) protected function setRoot(string $root = null)

View File

@@ -40,7 +40,7 @@ trait FileModifications
* Crops the image by the given width and height * Crops the image by the given width and height
* *
* @param int $width * @param int $width
* @param int $height * @param int|null $height
* @param string|array $options * @param string|array $options
* @return \Kirby\Cms\FileVersion|\Kirby\Cms\File * @return \Kirby\Cms\FileVersion|\Kirby\Cms\File
*/ */
@@ -103,10 +103,11 @@ trait FileModifications
* Resizes the file with the given width and height * Resizes the file with the given width and height
* while keeping the aspect ratio. * while keeping the aspect ratio.
* *
* @param int $width * @param int|null $width
* @param int $height * @param int|null $height
* @param int $quality * @param int|null $quality
* @return \Kirby\Cms\FileVersion|\Kirby\Cms\File * @return \Kirby\Cms\FileVersion|\Kirby\Cms\File
* @throws \Kirby\Exception\InvalidArgumentException
*/ */
public function resize(int $width = null, int $height = null, int $quality = null) public function resize(int $width = null, int $height = null, int $quality = null)
{ {
@@ -123,7 +124,7 @@ trait FileModifications
* also be set up in the config with the thumbs.srcsets option. * also be set up in the config with the thumbs.srcsets option.
* @since 3.1.0 * @since 3.1.0
* *
* @param array|string $sizes * @param array|string|null $sizes
* @return string|null * @return string|null
*/ */
public function srcset($sizes = null): ?string public function srcset($sizes = null): ?string
@@ -175,6 +176,7 @@ trait FileModifications
* *
* @param array|null|string $options * @param array|null|string $options
* @return \Kirby\Cms\FileVersion|\Kirby\Cms\File * @return \Kirby\Cms\FileVersion|\Kirby\Cms\File
* @throws \Kirby\Exception\InvalidArgumentException
*/ */
public function thumb($options = null) public function thumb($options = null)
{ {

View File

@@ -34,6 +34,7 @@ class FilePicker extends Picker
* Search all files for the picker * Search all files for the picker
* *
* @return \Kirby\Cms\Files|null * @return \Kirby\Cms\Files|null
* @throws \Kirby\Exception\InvalidArgumentException
*/ */
public function items() public function items()
{ {

View File

@@ -4,7 +4,6 @@ namespace Kirby\Cms;
use Kirby\Exception\DuplicateException; use Kirby\Exception\DuplicateException;
use Kirby\Exception\InvalidArgumentException; use Kirby\Exception\InvalidArgumentException;
use Kirby\Exception\LogicException;
use Kirby\Exception\PermissionException; use Kirby\Exception\PermissionException;
use Kirby\Image\Image; use Kirby\Image\Image;
use Kirby\Toolkit\Str; use Kirby\Toolkit\Str;
@@ -21,6 +20,15 @@ use Kirby\Toolkit\V;
*/ */
class FileRules class FileRules
{ {
/**
* Validates if the filename can be changed
*
* @param \Kirby\Cms\File $file
* @param string $name
* @return bool
* @throws \Kirby\Exception\DuplicateException If a file with this name exists
* @throws \Kirby\Exception\PermissionException If the user is not allowed to rename the file
*/
public static function changeName(File $file, string $name): bool public static function changeName(File $file, string $name): bool
{ {
if ($file->permissions()->changeName() !== true) { if ($file->permissions()->changeName() !== true) {
@@ -43,15 +51,31 @@ class FileRules
return true; return true;
} }
/**
* Validates if the file can be sorted
*
* @param \Kirby\Cms\File $file
* @param int $sort
* @return bool
*/
public static function changeSort(File $file, int $sort): bool public static function changeSort(File $file, int $sort): bool
{ {
return true; return true;
} }
/**
* Validates if the file can be created
*
* @param \Kirby\Cms\File $file
* @param \Kirby\Image\Image $upload
* @return bool
* @throws \Kirby\Exception\DuplicateException If a file with the same name exists
* @throws \Kirby\Exception\PermissionException If the user is not allowed to create the file
*/
public static function create(File $file, Image $upload): bool public static function create(File $file, Image $upload): bool
{ {
if ($file->exists() === true) { if ($file->exists() === true) {
throw new LogicException('The file exists and cannot be overwritten'); throw new DuplicateException('The file exists and cannot be overwritten');
} }
if ($file->permissions()->create() !== true) { if ($file->permissions()->create() !== true) {
@@ -67,6 +91,13 @@ class FileRules
return true; return true;
} }
/**
* Validates if the file can be deleted
*
* @param \Kirby\Cms\File $file
* @return bool
* @throws \Kirby\Exception\PermissionException If the user is not allowed to delete the file
*/
public static function delete(File $file): bool public static function delete(File $file): bool
{ {
if ($file->permissions()->delete() !== true) { if ($file->permissions()->delete() !== true) {
@@ -76,6 +107,15 @@ class FileRules
return true; return true;
} }
/**
* Validates if the file can be replaced
*
* @param \Kirby\Cms\File $file
* @param \Kirby\Image\Image $upload
* @return bool
* @throws \Kirby\Exception\PermissionException If the user is not allowed to replace the file
* @throws \Kirby\Exception\InvalidArgumentException If the file type of the new file is different
*/
public static function replace(File $file, Image $upload): bool public static function replace(File $file, Image $upload): bool
{ {
if ($file->permissions()->replace() !== true) { if ($file->permissions()->replace() !== true) {
@@ -84,7 +124,6 @@ class FileRules
static::validMime($file, $upload->mime()); static::validMime($file, $upload->mime());
if ( if (
(string)$upload->mime() !== (string)$file->mime() && (string)$upload->mime() !== (string)$file->mime() &&
(string)$upload->extension() !== (string)$file->extension() (string)$upload->extension() !== (string)$file->extension()
@@ -100,6 +139,14 @@ class FileRules
return true; return true;
} }
/**
* Validates if the file can be updated
*
* @param \Kirby\Cms\File $file
* @param array $content
* @return bool
* @throws \Kirby\Exception\PermissionException If the user is not allowed to update the file
*/
public static function update(File $file, array $content = []): bool public static function update(File $file, array $content = []): bool
{ {
if ($file->permissions()->update() !== true) { if ($file->permissions()->update() !== true) {
@@ -109,6 +156,14 @@ class FileRules
return true; return true;
} }
/**
* Validates the file extension
*
* @param \Kirby\Cms\File $file
* @param string $extension
* @return bool
* @throws \Kirby\Exception\InvalidArgumentException If the extension is missing or forbidden
*/
public static function validExtension(File $file, string $extension): bool public static function validExtension(File $file, string $extension): bool
{ {
// make it easier to compare the extension // make it easier to compare the extension
@@ -145,9 +200,16 @@ class FileRules
return true; return true;
} }
/**
* Validates the filename
*
* @param \Kirby\Cms\File $file
* @param string $filename
* @return bool
* @throws \Kirby\Exception\InvalidArgumentException If the filename is missing or forbidden
*/
public static function validFilename(File $file, string $filename) public static function validFilename(File $file, string $filename)
{ {
// make it easier to compare the filename // make it easier to compare the filename
$filename = strtolower($filename); $filename = strtolower($filename);
@@ -177,6 +239,14 @@ class FileRules
return true; return true;
} }
/**
* Validates the MIME type
*
* @param \Kirby\Cms\File $file
* @param string|null $mime
* @return bool
* @throws \Kirby\Exception\InvalidArgumentException If the MIME type is missing or forbidden
*/
public static function validMime(File $file, string $mime = null) public static function validMime(File $file, string $mime = null)
{ {
// make it easier to compare the mime // make it easier to compare the mime

View File

@@ -23,6 +23,14 @@ class FileVersion
protected $modifications; protected $modifications;
protected $original; protected $original;
/**
* Proxy for public properties, asset methods
* and content field getters
*
* @param string $method
* @param array $arguments
* @return mixed
*/
public function __call(string $method, array $arguments = []) public function __call(string $method, array $arguments = [])
{ {
// public property access // public property access
@@ -45,12 +53,19 @@ class FileVersion
} }
} }
/**
* Returns the unique ID
*
* @return string
*/
public function id(): string public function id(): string
{ {
return dirname($this->original()->id()) . '/' . $this->filename(); return dirname($this->original()->id()) . '/' . $this->filename();
} }
/** /**
* Returns the parent Kirby App instance
*
* @return \Kirby\Cms\App * @return \Kirby\Cms\App
*/ */
public function kirby() public function kirby()
@@ -58,34 +73,60 @@ class FileVersion
return $this->original()->kirby(); return $this->original()->kirby();
} }
/**
* Returns an array with all applied modifications
*
* @return array
*/
public function modifications(): array public function modifications(): array
{ {
return $this->modifications ?? []; return $this->modifications ?? [];
} }
/**
* Returns the instance of the original File object
*
* @return mixed
*/
public function original() public function original()
{ {
return $this->original; return $this->original;
} }
/**
* Applies the stored modifications and
* saves the file on disk
*
* @return self
*/
public function save() public function save()
{ {
$this->kirby()->thumb($this->original()->root(), $this->root(), $this->modifications()); $this->kirby()->thumb($this->original()->root(), $this->root(), $this->modifications());
return $this; return $this;
} }
/**
* Setter for modifications
*
* @param array|null $modifications
*/
protected function setModifications(array $modifications = null) protected function setModifications(array $modifications = null)
{ {
$this->modifications = $modifications; $this->modifications = $modifications;
} }
/**
* Setter for the original File object
*
* @param $original
*/
protected function setOriginal($original) protected function setOriginal($original)
{ {
$this->original = $original; $this->original = $original;
} }
/** /**
* Convert the object to an array * Converts the object to an array
* *
* @return array * @return array
*/ */

View File

@@ -118,7 +118,7 @@ class Filename
* to a string, that can be used in the * to a string, that can be used in the
* new filename * new filename
* *
* @param string $prefix The prefix will be used in the filename creation * @param string|null $prefix The prefix will be used in the filename creation
* @return string * @return string
*/ */
public function attributesToString(string $prefix = null): string public function attributesToString(string $prefix = null): string

View File

@@ -76,7 +76,6 @@ class Files extends Collection
* *
* @param array $files * @param array $files
* @param \Kirby\Cms\Model $parent * @param \Kirby\Cms\Model $parent
* @param array $inject
* @return self * @return self
*/ */
public static function factory(array $files, Model $parent) public static function factory(array $files, Model $parent)

View File

@@ -21,6 +21,11 @@ class Form extends BaseForm
protected $fields; protected $fields;
protected $values = []; protected $values = [];
/**
* Form constructor.
*
* @param array $props
*/
public function __construct(array $props) public function __construct(array $props)
{ {
$kirby = App::instance(); $kirby = App::instance();

View File

@@ -177,6 +177,7 @@ trait HasChildren
/** /**
* @deprecated 3.0.0 Use `Page::hasUnlistedChildren()` instead * @deprecated 3.0.0 Use `Page::hasUnlistedChildren()` instead
* @return bool * @return bool
* @codeCoverageIgnore
*/ */
public function hasInvisibleChildren(): bool public function hasInvisibleChildren(): bool
{ {
@@ -208,6 +209,7 @@ trait HasChildren
/** /**
* @deprecated 3.0.0 Use `Page::hasListedChildren()` instead * @deprecated 3.0.0 Use `Page::hasListedChildren()` instead
* @return bool * @return bool
* @codeCoverageIgnore
*/ */
public function hasVisibleChildren(): bool public function hasVisibleChildren(): bool
{ {

View File

@@ -80,7 +80,7 @@ trait HasFiles
/** /**
* Returns a specific file by filename or the first one * Returns a specific file by filename or the first one
* *
* @param string $filename * @param string|null $filename
* @param string $in * @param string $in
* @return \Kirby\Cms\File|null * @return \Kirby\Cms\File|null
*/ */
@@ -181,7 +181,7 @@ trait HasFiles
/** /**
* Returns a specific image by filename or the first one * Returns a specific image by filename or the first one
* *
* @param string $filename * @param string|null $filename
* @return \Kirby\Cms\File|null * @return \Kirby\Cms\File|null
*/ */
public function image(string $filename = null) public function image(string $filename = null)

View File

@@ -30,6 +30,7 @@ trait HasMethods
* @param string $method * @param string $method
* @param array $args * @param array $args
* @return mixed * @return mixed
* @throws \Kirby\Exception\BadMethodCallException
*/ */
public function callMethod(string $method, array $args = []) public function callMethod(string $method, array $args = [])
{ {
@@ -60,7 +61,7 @@ trait HasMethods
* inheritance order (top to bottom) * inheritance order (top to bottom)
* *
* @param string $method * @param string $method
* @return Closure|null * @return \Closure|null
*/ */
protected function getMethod(string $method) protected function getMethod(string $method)
{ {
@@ -73,7 +74,7 @@ trait HasMethods
return $parent::$methods[$method]; return $parent::$methods[$method];
} }
} }
return null; return null;
} }
} }

View File

@@ -18,7 +18,7 @@ class Html extends \Kirby\Toolkit\Html
/** /**
* Generates an `a` tag with an absolute Url * Generates an `a` tag with an absolute Url
* *
* @param string $href Relative or absolute Url * @param string|null $href Relative or absolute Url
* @param string|array|null $text If `null`, the link will be used as link text. If an array is passed, each element will be added unencoded * @param string|array|null $text If `null`, the link will be used as link text. If an array is passed, each element will be added unencoded
* @param array $attr Additional attributes for the a tag. * @param array $attr Additional attributes for the a tag.
* @return string * @return string

View File

@@ -35,7 +35,7 @@ class Ingredients
* Magic getter for single ingredients * Magic getter for single ingredients
* *
* @param string $method * @param string $method
* @param array $args * @param array|null $args
* @return mixed * @return mixed
*/ */
public function __call(string $method, array $args = null) public function __call(string $method, array $args = null)

View File

@@ -22,10 +22,10 @@ class KirbyTags extends \Kirby\Text\KirbyTags
protected static $tagClass = 'Kirby\Cms\KirbyTag'; protected static $tagClass = 'Kirby\Cms\KirbyTag';
/** /**
* @param string $text * @param string|null $text
* @param array $data * @param array $data
* @param array $options * @param array $options
* @param \Kirby\Cms\App $app * @param \Kirby\Cms\App|null $app
* @return string * @return string
*/ */
public static function parse(string $text = null, array $data = [], array $options = [], ?App $app = null): string public static function parse(string $text = null, array $data = [], array $options = [], ?App $app = null): string

View File

@@ -230,6 +230,7 @@ class Language extends Model
* *
* @internal * @internal
* @return bool * @return bool
* @throws \Kirby\Exception\Exception
*/ */
public function delete(): bool public function delete(): bool
{ {

View File

@@ -50,6 +50,7 @@ class LanguageRouter
* current language from the Kirby instance * current language from the Kirby instance
* *
* @return array * @return array
* @throws \Kirby\Exception\NotFoundException
*/ */
public function routes(): array public function routes(): array
{ {

View File

@@ -17,6 +17,13 @@ use Kirby\Toolkit\Str;
*/ */
class LanguageRules class LanguageRules
{ {
/**
* Validates if the language can be created
*
* @param \Kirby\Cms\Language $language
* @return bool
* @throws \Kirby\Exception\DuplicateException If the language already exists
*/
public static function create(Language $language): bool public static function create(Language $language): bool
{ {
static::validLanguageCode($language); static::validLanguageCode($language);
@@ -34,12 +41,24 @@ class LanguageRules
return true; return true;
} }
/**
* Validates if the language can be updated
*
* @param \Kirby\Cms\Language $language
*/
public static function update(Language $language) public static function update(Language $language)
{ {
static::validLanguageCode($language); static::validLanguageCode($language);
static::validLanguageName($language); static::validLanguageName($language);
} }
/**
* Validates if the language code is formatted correctly
*
* @param \Kirby\Cms\Language $language
* @return bool
* @throws \Kirby\Exception\InvalidArgumentException If the language code is not valid
*/
public static function validLanguageCode(Language $language): bool public static function validLanguageCode(Language $language): bool
{ {
if (Str::length($language->code()) < 2) { if (Str::length($language->code()) < 2) {
@@ -55,6 +74,13 @@ class LanguageRules
return true; return true;
} }
/**
* Validates if the language name is formatted correctly
*
* @param \Kirby\Cms\Language $language
* @return bool
* @throws \Kirby\Exception\InvalidArgumentException If the language name is invalid
*/
public static function validLanguageName(Language $language): bool public static function validLanguageName(Language $language): bool
{ {
if (Str::length($language->name()) < 1) { if (Str::length($language->name()) < 1) {

View File

@@ -20,7 +20,8 @@ class Languages extends Collection
* Creates a new collection with the given language objects * Creates a new collection with the given language objects
* *
* @param array $objects * @param array $objects
* @param object $parent * @param null $parent
* @throws \Kirby\Exception\DuplicateException
*/ */
public function __construct($objects = [], $parent = null) public function __construct($objects = [], $parent = null)
{ {
@@ -74,6 +75,7 @@ class Languages extends Collection
/** /**
* @deprecated 3.0.0 Use `Languages::default()` instead * @deprecated 3.0.0 Use `Languages::default()` instead
* @return \Kirby\Cms\Language|null * @return \Kirby\Cms\Language|null
* @codeCoverageIgnore
*/ */
public function findDefault() public function findDefault()
{ {

View File

@@ -24,7 +24,7 @@ class Media
* Tries to find a file by model and filename * Tries to find a file by model and filename
* and to copy it to the media folder. * and to copy it to the media folder.
* *
* @param \Kirby\Cms\Model $model * @param \Kirby\Cms\Model|null $model
* @param string $hash * @param string $hash
* @param string $filename * @param string $filename
* @return \Kirby\Cms\Response|false * @return \Kirby\Cms\Response|false
@@ -137,7 +137,7 @@ class Media
* *
* @param string $directory * @param string $directory
* @param \Kirby\Cms\File $file * @param \Kirby\Cms\File $file
* @param string $ignore * @param string|null $ignore
* @return bool * @return bool
*/ */
public static function unpublish(string $directory, File $file, string $ignore = null): bool public static function unpublish(string $directory, File $file, string $ignore = null): bool

View File

@@ -21,11 +21,21 @@ abstract class ModelPermissions
protected $permissions; protected $permissions;
protected $user; protected $user;
/**
* @param string $method
* @param array $arguments
* @return bool
*/
public function __call(string $method, array $arguments = []): bool public function __call(string $method, array $arguments = []): bool
{ {
return $this->can($method); return $this->can($method);
} }
/**
* ModelPermissions constructor
*
* @param \Kirby\Cms\Model $model
*/
public function __construct(Model $model) public function __construct(Model $model)
{ {
$this->model = $model; $this->model = $model;
@@ -44,6 +54,10 @@ abstract class ModelPermissions
return $this->toArray(); return $this->toArray();
} }
/**
* @param string $action
* @return bool
*/
public function can(string $action): bool public function can(string $action): bool
{ {
$role = $this->user->role()->id(); $role = $this->user->role()->id();
@@ -77,11 +91,18 @@ abstract class ModelPermissions
return $this->permissions->for($this->category, $action); return $this->permissions->for($this->category, $action);
} }
/**
* @param string $action
* @return bool
*/
public function cannot(string $action): bool public function cannot(string $action): bool
{ {
return $this->can($action) === false; return $this->can($action) === false;
} }
/**
* @return array
*/
public function toArray(): array public function toArray(): array
{ {
$array = []; $array = [];

View File

@@ -46,12 +46,37 @@ abstract class ModelWithContent extends Model
*/ */
abstract public function blueprint(); abstract public function blueprint();
/**
* Returns an array with all blueprints that are available
*
* @param string|null $inSection
* @return array
*/
public function blueprints(string $inSection = null): array
{
$blueprints = [];
$blueprint = $this->blueprint();
$sections = $inSection !== null ? [$blueprint->section($inSection)] : $blueprint->sections();
foreach ($sections as $section) {
if ($section === null) {
continue;
}
foreach ((array)$section->blueprints() as $blueprint) {
$blueprints[$blueprint['name']] = $blueprint;
}
}
return array_values($blueprints);
}
/** /**
* Executes any given model action * Executes any given model action
* *
* @param string $action * @param string $action
* @param array $arguments * @param array $arguments
* @param Closure $callback * @param \Closure $callback
* @return mixed * @return mixed
*/ */
abstract protected function commit(string $action, array $arguments, Closure $callback); abstract protected function commit(string $action, array $arguments, Closure $callback);
@@ -59,8 +84,9 @@ abstract class ModelWithContent extends Model
/** /**
* Returns the content * Returns the content
* *
* @param string $languageCode * @param string|null $languageCode
* @return \Kirby\Cms\Content * @return \Kirby\Cms\Content
* @throws \Kirby\Exception\InvalidArgumentException If the language for the given code does not exist
*/ */
public function content(string $languageCode = null) public function content(string $languageCode = null)
{ {
@@ -104,6 +130,7 @@ abstract class ModelWithContent extends Model
* @param string|null $languageCode * @param string|null $languageCode
* @param bool $force * @param bool $force
* @return string * @return string
* @throws \Kirby\Exception\InvalidArgumentException If the language for the given code does not exist
*/ */
public function contentFile(string $languageCode = null, bool $force = false): string public function contentFile(string $languageCode = null, bool $force = false): string
{ {
@@ -158,7 +185,7 @@ abstract class ModelWithContent extends Model
* *
* @internal * @internal
* @param array $data * @param array $data
* @param string $languageCode * @param string|null $languageCode
* @return array * @return array
*/ */
public function contentFileData(array $data, string $languageCode = null): array public function contentFileData(array $data, string $languageCode = null): array
@@ -217,6 +244,46 @@ abstract class ModelWithContent extends Model
return $this->update([$field => $value]); return $this->update([$field => $value]);
} }
/**
* Returns the drag text from a custom callback
* if the callback is defined in the config
*
* @internal
* @param string $type markdown or kirbytext
* @param mixed ...$args
* @return string|null
*/
public function dragTextFromCallback(string $type, ...$args): ?string
{
$dragTextCallback = option('panel.' . $type . '.' . static::CLASS_ALIAS . 'DragText');
if (empty($dragTextCallback) === false && is_a($dragTextCallback, 'Closure') === true && ($dragText = $dragTextCallback($this, ...$args)) !== null) {
return $dragText;
}
return null;
}
/**
* Returns the correct drag text type
* depending on the given type or the
* configuration
*
* @internal
* @param string $type (null|auto|kirbytext|markdown)
* @return string
*/
public function dragTextType(string $type = null): string
{
$type = $type ?? 'auto';
if ($type === 'auto') {
$type = option('panel.kirbytext', true) ? 'kirbytext' : 'markdown';
}
return $type === 'markdown' ? 'markdown' : 'kirbytext';
}
/** /**
* Returns all content validation errors * Returns all content validation errors
* *
@@ -240,7 +307,7 @@ abstract class ModelWithContent extends Model
* *
* @param string $field * @param string $field
* @param int $by * @param int $by
* @param int $max * @param int|null $max
* @return self * @return self
*/ */
public function increment(string $field, int $by = 1, int $max = null) public function increment(string $field, int $by = 1, int $max = null)
@@ -300,7 +367,7 @@ abstract class ModelWithContent extends Model
* Returns the panel icon definition * Returns the panel icon definition
* *
* @internal * @internal
* @param array $params * @param array|null $params
* @return array * @return array
*/ */
public function panelIcon(array $params = null): array public function panelIcon(array $params = null): array
@@ -317,7 +384,7 @@ abstract class ModelWithContent extends Model
/** /**
* @internal * @internal
* @param string|array|false $settings * @param string|array|false|null $settings
* @return array|null * @return array|null
*/ */
public function panelImage($settings = null): ?array public function panelImage($settings = null): ?array
@@ -349,32 +416,36 @@ abstract class ModelWithContent extends Model
// main url // main url
$settings['url'] = $image->url(); $settings['url'] = $image->url();
// for cards // only create srcsets for actual File objects
$settings['cards'] = [ if (is_a($image, 'Kirby\Cms\File') === true) {
'url' => 'data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw',
'srcset' => $image->srcset([
352,
864,
1408,
])
];
// for lists // for cards
$settings['list'] = [ $settings['cards'] = [
'url' => 'data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw', 'url' => 'data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw',
'srcset' => $image->srcset([ 'srcset' => $image->srcset([
'1x' => [ 352,
'width' => 38, 864,
'height' => 38, 1408,
'crop' => 'center' ])
], ];
'2x' => [
'width' => 76, // for lists
'height' => 76, $settings['list'] = [
'crop' => 'center' 'url' => 'data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw',
], 'srcset' => $image->srcset([
]) '1x' => [
]; 'width' => 38,
'height' => 38,
'crop' => 'center'
],
'2x' => [
'width' => 76,
'height' => 76,
'crop' => 'center'
],
])
];
}
unset($settings['query']); unset($settings['query']);
} }
@@ -497,8 +568,8 @@ abstract class ModelWithContent extends Model
* Stores the content on disk * Stores the content on disk
* *
* @internal * @internal
* @param string $languageCode * @param array|null $data
* @param array $data * @param string|null $languageCode
* @param bool $overwrite * @param bool $overwrite
* @return self * @return self
*/ */
@@ -539,6 +610,7 @@ abstract class ModelWithContent extends Model
* @param string|null $languageCode * @param string|null $languageCode
* @param bool $overwrite * @param bool $overwrite
* @return self * @return self
* @throws \Kirby\Exception\InvalidArgumentException If the language for the given code does not exist
*/ */
protected function saveTranslation(array $data = null, string $languageCode = null, bool $overwrite = false) protected function saveTranslation(array $data = null, string $languageCode = null, bool $overwrite = false)
{ {
@@ -598,7 +670,7 @@ abstract class ModelWithContent extends Model
/** /**
* Create the translations collection from an array * Create the translations collection from an array
* *
* @param array $translations * @param array|null $translations
* @return self * @return self
*/ */
protected function setTranslations(array $translations = null) protected function setTranslations(array $translations = null)
@@ -679,10 +751,11 @@ abstract class ModelWithContent extends Model
/** /**
* Updates the model data * Updates the model data
* *
* @param array $input * @param array|null $input
* @param string $languageCode * @param string|null $languageCode
* @param bool $validate * @param bool $validate
* @return self * @return self
* @throws \Kirby\Exception\InvalidArgumentException If the input array contains invalid values
*/ */
public function update(array $input = null, string $languageCode = null, bool $validate = false) public function update(array $input = null, string $languageCode = null, bool $validate = false)
{ {
@@ -720,7 +793,7 @@ abstract class ModelWithContent extends Model
* *
* @internal * @internal
* @param array $data * @param array $data
* @param string $languageCode * @param string|null $languageCode
* @return bool * @return bool
*/ */
public function writeContent(array $data, string $languageCode = null): bool public function writeContent(array $data, string $languageCode = null): bool

View File

@@ -18,6 +18,11 @@ namespace Kirby\Cms;
*/ */
class Nest class Nest
{ {
/**
* @param $data
* @param null $parent
* @return mixed
*/
public static function create($data, $parent = null) public static function create($data, $parent = null)
{ {
if (is_scalar($data) === true) { if (is_scalar($data) === true) {

View File

@@ -21,7 +21,7 @@ class NestCollection extends BaseCollection
* to an array. This can also take a callback * to an array. This can also take a callback
* function to further modify the array result. * function to further modify the array result.
* *
* @param Closure $map * @param \Closure|null $map
* @return array * @return array
*/ */
public function toArray(Closure $map = null): array public function toArray(Closure $map = null): array

View File

@@ -237,7 +237,7 @@ class Page extends ModelWithContent
/** /**
* Returns an array with all blueprints that are available for the page * Returns an array with all blueprints that are available for the page
* *
* @param string $inSection * @param string|null $inSection
* @return array * @return array
*/ */
public function blueprints(string $inSection = null): array public function blueprints(string $inSection = null): array
@@ -302,7 +302,7 @@ class Page extends ModelWithContent
* *
* @internal * @internal
* @param array $data * @param array $data
* @param string $languageCode * @param string|null $languageCode
* @return array * @return array
*/ */
public function contentFileData(array $data, string $languageCode = null): array public function contentFileData(array $data, string $languageCode = null): array
@@ -318,7 +318,7 @@ class Page extends ModelWithContent
* which is found by the inventory method * which is found by the inventory method
* *
* @internal * @internal
* @param string $languageCode * @param string|null $languageCode
* @return string * @return string
*/ */
public function contentFileName(string $languageCode = null): string public function contentFileName(string $languageCode = null): string
@@ -333,6 +333,7 @@ class Page extends ModelWithContent
* @param array $data * @param array $data
* @param string $contentType * @param string $contentType
* @return array * @return array
* @throws \Kirby\Exception\InvalidArgumentException If the controller returns invalid objects for `kirby`, `site`, `pages` or `page`
*/ */
public function controller($data = [], $contentType = 'html'): array public function controller($data = [], $contentType = 'html'): array
{ {
@@ -432,22 +433,21 @@ class Page extends ModelWithContent
* gets dragged onto a textarea * gets dragged onto a textarea
* *
* @internal * @internal
* @param string $type (null|auto|kirbytext|markdown) * @param string|null $type (null|auto|kirbytext|markdown)
* @return string * @return string
*/ */
public function dragText(string $type = null): string public function dragText(string $type = null): string
{ {
$type = $type ?? 'auto'; $type = $this->dragTextType($type);
if ($type === 'auto') { if ($dragTextFromCallback = $this->dragTextFromCallback($type)) {
$type = option('panel.kirbytext', true) ? 'kirbytext' : 'markdown'; return $dragTextFromCallback;
} }
switch ($type) { if ($type === 'markdown') {
case 'markdown': return '[' . $this->title() . '](' . $this->url() . ')';
return '[' . $this->title() . '](' . $this->url() . ')'; } else {
default: return '(link: ' . $this->id() . ' text: ' . $this->title() . ')';
return '(link: ' . $this->id() . ' text: ' . $this->title() . ')';
} }
} }
@@ -757,6 +757,7 @@ class Page extends ModelWithContent
/** /**
* @deprecated 3.0.0 Use `Page::isUnlisted()` instead * @deprecated 3.0.0 Use `Page::isUnlisted()` instead
* @return bool * @return bool
* @codeCoverageIgnore
*/ */
public function isInvisible(): bool public function isInvisible(): bool
{ {
@@ -848,6 +849,7 @@ class Page extends ModelWithContent
/** /**
* @deprecated 3.0.0 Use `Page::isListed()` instead * @deprecated 3.0.0 Use `Page::isListed()` instead
* @return bool * @return bool
* @codeCoverageIgnore
*/ */
public function isVisible(): bool public function isVisible(): bool
{ {
@@ -861,7 +863,7 @@ class Page extends ModelWithContent
* This is only used for drafts so far. * This is only used for drafts so far.
* *
* @internal * @internal
* @param string $token * @param string|null $token
* @return bool * @return bool
*/ */
public function isVerified(string $token = null) public function isVerified(string $token = null)
@@ -926,7 +928,7 @@ class Page extends ModelWithContent
/** /**
* Returns the last modification date of the page * Returns the last modification date of the page
* *
* @param string $format * @param string|null $format
* @param string|null $handler * @param string|null $handler
* @param string|null $languageCode * @param string|null $languageCode
* @return int|string * @return int|string
@@ -955,7 +957,7 @@ class Page extends ModelWithContent
* according to the blueprint settings * according to the blueprint settings
* *
* @internal * @internal
* @param array $params * @param array|null $params
* @return array * @return array
*/ */
public function panelIcon(array $params = null): array public function panelIcon(array $params = null): array
@@ -1158,8 +1160,8 @@ class Page extends ModelWithContent
* *
* @param array $data * @param array $data
* @param string $contentType * @param string $contentType
* @param int $code
* @return string * @return string
* @throws \Kirby\Exception\NotFoundException If the default template cannot be found
*/ */
public function render(array $data = [], $contentType = 'html'): string public function render(array $data = [], $contentType = 'html'): string
{ {
@@ -1218,6 +1220,7 @@ class Page extends ModelWithContent
* @internal * @internal
* @param mixed $type * @param mixed $type
* @return \Kirby\Cms\Template * @return \Kirby\Cms\Template
* @throws \Kirby\Exception\NotFoundException If the content representation cannot be found
*/ */
public function representation($type) public function representation($type)
{ {
@@ -1258,7 +1261,7 @@ class Page extends ModelWithContent
/** /**
* Search all pages within the current page * Search all pages within the current page
* *
* @param string $query * @param string|null $query
* @param array $params * @param array $params
* @return \Kirby\Cms\Pages * @return \Kirby\Cms\Pages
*/ */
@@ -1288,7 +1291,7 @@ class Page extends ModelWithContent
* more reliable in connection with the inventory * more reliable in connection with the inventory
* than computing the dirname afterwards * than computing the dirname afterwards
* *
* @param string $dirname * @param string|null $dirname
* @return self * @return self
*/ */
protected function setDirname(string $dirname = null) protected function setDirname(string $dirname = null)
@@ -1312,7 +1315,7 @@ class Page extends ModelWithContent
/** /**
* Sets the sorting number * Sets the sorting number
* *
* @param int $num * @param int|null $num
* @return self * @return self
*/ */
protected function setNum(int $num = null) protected function setNum(int $num = null)
@@ -1360,7 +1363,7 @@ class Page extends ModelWithContent
/** /**
* Sets the intended template * Sets the intended template
* *
* @param string $template * @param string|null $template
* @return self * @return self
*/ */
protected function setTemplate(string $template = null) protected function setTemplate(string $template = null)
@@ -1375,7 +1378,7 @@ class Page extends ModelWithContent
/** /**
* Sets the Url * Sets the Url
* *
* @param string $url * @param string|null $url
* @return self * @return self
*/ */
protected function setUrl(string $url = null) protected function setUrl(string $url = null)
@@ -1570,8 +1573,8 @@ class Page extends ModelWithContent
* Builds the Url for a specific language * Builds the Url for a specific language
* *
* @internal * @internal
* @param string $language * @param string|null $language
* @param array $options * @param array|null $options
* @return string * @return string
*/ */
public function urlForLanguage($language = null, array $options = null): string public function urlForLanguage($language = null, array $options = null): string

View File

@@ -4,7 +4,6 @@ namespace Kirby\Cms;
use Closure; use Closure;
use Kirby\Exception\DuplicateException; use Kirby\Exception\DuplicateException;
use Kirby\Exception\Exception;
use Kirby\Exception\InvalidArgumentException; use Kirby\Exception\InvalidArgumentException;
use Kirby\Exception\LogicException; use Kirby\Exception\LogicException;
use Kirby\Exception\NotFoundException; use Kirby\Exception\NotFoundException;
@@ -28,8 +27,9 @@ trait PageActions
* The sorting number must already be correct * The sorting number must already be correct
* when the method is called * when the method is called
* *
* @param int $num * @param int|null $num
* @return self * @return self
* @throws \Kirby\Exception\LogicException If a draft is being sorted or the directory cannot be moved
*/ */
public function changeNum(int $num = null) public function changeNum(int $num = null)
{ {
@@ -74,8 +74,9 @@ trait PageActions
* Changes the slug/uid of the page * Changes the slug/uid of the page
* *
* @param string $slug * @param string $slug
* @param string $languageCode * @param string|null $languageCode
* @return self * @return self
* @throws \Kirby\Exception\LogicException If the directory cannot be moved
*/ */
public function changeSlug(string $slug, string $languageCode = null) public function changeSlug(string $slug, string $languageCode = null)
{ {
@@ -137,8 +138,10 @@ trait PageActions
* Change the slug for a specific language * Change the slug for a specific language
* *
* @param string $slug * @param string $slug
* @param string $languageCode * @param string|null $languageCode
* @return self * @return self
* @throws \Kirby\Exception\NotFoundException If the language for the given language code cannot be found
* @throws \Kirby\Exception\InvalidArgumentException If the slug for the default language is being changed
*/ */
protected function changeSlugForLanguage(string $slug, string $languageCode = null) protected function changeSlugForLanguage(string $slug, string $languageCode = null)
{ {
@@ -168,8 +171,9 @@ trait PageActions
* to either draft, listed or unlisted * to either draft, listed or unlisted
* *
* @param string $status "draft", "listed" or "unlisted" * @param string $status "draft", "listed" or "unlisted"
* @param int $position Optional sorting number * @param int|null $position Optional sorting number
* @return self * @return self
* @throws \Kirby\Exception\InvalidArgumentException If an invalid status is being passed
*/ */
public function changeStatus(string $status, int $position = null) public function changeStatus(string $status, int $position = null)
{ {
@@ -181,10 +185,13 @@ trait PageActions
case 'unlisted': case 'unlisted':
return $this->changeStatusToUnlisted(); return $this->changeStatusToUnlisted();
default: default:
throw new Exception('Invalid status: ' . $status); throw new InvalidArgumentException('Invalid status: ' . $status);
} }
} }
/**
* @return self
*/
protected function changeStatusToDraft() protected function changeStatusToDraft()
{ {
$arguments = ['page' => $this, 'status' => 'draft', 'position' => null]; $arguments = ['page' => $this, 'status' => 'draft', 'position' => null];
@@ -245,6 +252,7 @@ trait PageActions
* *
* @param string $template * @param string $template
* @return self * @return self
* @throws \Kirby\Exception\LogicException If the textfile cannot be renamed/moved
*/ */
public function changeTemplate(string $template) public function changeTemplate(string $template)
{ {
@@ -312,7 +320,7 @@ trait PageActions
* *
* @param string $action * @param string $action
* @param array $arguments * @param array $arguments
* @param Closure $callback * @param \Closure $callback
* @return mixed * @return mixed
*/ */
protected function commit(string $action, array $arguments, Closure $callback) protected function commit(string $action, array $arguments, Closure $callback)
@@ -346,6 +354,7 @@ trait PageActions
* *
* @param array $options * @param array $options
* @return \Kirby\Cms\Page * @return \Kirby\Cms\Page
* @throws \Kirby\Exception\DuplicateException If the page already exists
*/ */
public function copy(array $options = []) public function copy(array $options = [])
{ {
@@ -491,7 +500,7 @@ trait PageActions
* Create the sorting number for the page * Create the sorting number for the page
* depending on the blueprint settings * depending on the blueprint settings
* *
* @param int $num * @param int|null $num
* @return int * @return int
*/ */
public function createNum(int $num = null): int public function createNum(int $num = null): int
@@ -604,7 +613,7 @@ trait PageActions
* Duplicates the page with the given * Duplicates the page with the given
* slug and optionally copies all files * slug and optionally copies all files
* *
* @param string $slug * @param string|null $slug
* @param array $options * @param array $options
* @return \Kirby\Cms\Page * @return \Kirby\Cms\Page
*/ */
@@ -626,6 +635,10 @@ trait PageActions
}); });
} }
/**
* @return self
* @throws \Kirby\Exception\LogicException If the folder cannot be moved
*/
public function publish() public function publish()
{ {
if ($this->isDraft() === false) { if ($this->isDraft() === false) {
@@ -676,6 +689,11 @@ trait PageActions
return $this; return $this;
} }
/**
* @param int|null $position
* @return bool
* @throws \Kirby\Exception\LogicException If the page is not included in the siblings collection
*/
protected function resortSiblingsAfterListing(int $position = null): bool protected function resortSiblingsAfterListing(int $position = null): bool
{ {
// get all siblings including the current page // get all siblings including the current page
@@ -722,6 +740,9 @@ trait PageActions
return true; return true;
} }
/**
* @return bool
*/
public function resortSiblingsAfterUnlisting(): bool public function resortSiblingsAfterUnlisting(): bool
{ {
$index = 0; $index = 0;
@@ -746,6 +767,10 @@ trait PageActions
return true; return true;
} }
/**
* @param null $position
* @return self
*/
public function sort($position = null) public function sort($position = null)
{ {
return $this->changeStatus('listed', $position); return $this->changeStatus('listed', $position);
@@ -756,6 +781,7 @@ trait PageActions
* unlisted to draft. * unlisted to draft.
* *
* @return self * @return self
* @throws \Kirby\Exception\LogicException If the folder cannot be moved
*/ */
public function unpublish() public function unpublish()
{ {
@@ -789,8 +815,8 @@ trait PageActions
/** /**
* Updates the page data * Updates the page data
* *
* @param array $input * @param array|null $input
* @param string $language * @param string|null $language
* @param bool $validate * @param bool $validate
* @return self * @return self
*/ */

View File

@@ -180,7 +180,7 @@ class PageBlueprint extends Blueprint
/** /**
* Returns the preview settings * Returns the preview settings
* The preview setting controlls the "Open" * The preview setting controls the "Open"
* button in the panel and redirects it to a * button in the panel and redirects it to a
* different URL if necessary. * different URL if necessary.
* *

View File

@@ -13,18 +13,30 @@ namespace Kirby\Cms;
*/ */
class PagePermissions extends ModelPermissions class PagePermissions extends ModelPermissions
{ {
/**
* @var string
*/
protected $category = 'pages'; protected $category = 'pages';
/**
* @return bool
*/
protected function canChangeSlug(): bool protected function canChangeSlug(): bool
{ {
return $this->model->isHomeOrErrorPage() !== true; return $this->model->isHomeOrErrorPage() !== true;
} }
/**
* @return bool
*/
protected function canChangeStatus(): bool protected function canChangeStatus(): bool
{ {
return $this->model->isErrorPage() !== true; return $this->model->isErrorPage() !== true;
} }
/**
* @return bool
*/
protected function canChangeTemplate(): bool protected function canChangeTemplate(): bool
{ {
if ($this->model->isHomeOrErrorPage() === true) { if ($this->model->isHomeOrErrorPage() === true) {
@@ -38,11 +50,17 @@ class PagePermissions extends ModelPermissions
return true; return true;
} }
/**
* @return bool
*/
protected function canDelete(): bool protected function canDelete(): bool
{ {
return $this->model->isHomeOrErrorPage() !== true; return $this->model->isHomeOrErrorPage() !== true;
} }
/**
* @return bool
*/
protected function canSort(): bool protected function canSort(): bool
{ {
if ($this->model->isErrorPage() === true) { if ($this->model->isErrorPage() === true) {

View File

@@ -185,6 +185,7 @@ class PagePicker extends Picker
* Search for pages by query string * Search for pages by query string
* *
* @return \Kirby\Cms\Pages * @return \Kirby\Cms\Pages
* @throws \Kirby\Exception\InvalidArgumentException
*/ */
public function itemsForQuery() public function itemsForQuery()
{ {

View File

@@ -19,6 +19,14 @@ use Kirby\Toolkit\Str;
*/ */
class PageRules class PageRules
{ {
/**
* Validates if the sorting number of the page can be changed
*
* @param \Kirby\Cms\Page $page
* @param int|null $num
* @return bool
* @throws \Kirby\Exception\InvalidArgumentException If the given number is invalid
*/
public static function changeNum(Page $page, int $num = null): bool public static function changeNum(Page $page, int $num = null): bool
{ {
if ($num !== null && $num < 0) { if ($num !== null && $num < 0) {
@@ -28,6 +36,15 @@ class PageRules
return true; return true;
} }
/**
* Validates if the slug for the page can be changed
*
* @param \Kirby\Cms\Page $page
* @param string $slug
* @return bool
* @throws \Kirby\Exception\DuplicateException If a page with this slug already exists
* @throws \Kirby\Exception\PermissionException If the user is not allowed to change the slug
*/
public static function changeSlug(Page $page, string $slug): bool public static function changeSlug(Page $page, string $slug): bool
{ {
if ($page->permissions()->changeSlug() !== true) { if ($page->permissions()->changeSlug() !== true) {
@@ -39,6 +56,8 @@ class PageRules
]); ]);
} }
self::validateSlugLength($slug);
$siblings = $page->parentModel()->children(); $siblings = $page->parentModel()->children();
$drafts = $page->parentModel()->drafts(); $drafts = $page->parentModel()->drafts();
@@ -67,6 +86,15 @@ class PageRules
return true; return true;
} }
/**
* Validates if the status for the page can be changed
*
* @param \Kirby\Cms\Page $page
* @param string $status
* @param int|null $position
* @return bool
* @throws \Kirby\Exception\InvalidArgumentException If the given status is invalid
*/
public static function changeStatus(Page $page, string $status, int $position = null): bool public static function changeStatus(Page $page, string $status, int $position = null): bool
{ {
if (isset($page->blueprint()->status()[$status]) === false) { if (isset($page->blueprint()->status()[$status]) === false) {
@@ -85,6 +113,13 @@ class PageRules
} }
} }
/**
* Validates if a page can be converted to a draft
*
* @param \Kirby\Cms\Page $page
* @return bool
* @throws \Kirby\Exception\PermissionException If the user is not allowed to change the status or the page cannot be converted to a draft
*/
public static function changeStatusToDraft(Page $page) public static function changeStatusToDraft(Page $page)
{ {
if ($page->permissions()->changeStatus() !== true) { if ($page->permissions()->changeStatus() !== true) {
@@ -108,6 +143,15 @@ class PageRules
return true; return true;
} }
/**
* Validates if the status of a page can be changed to listed
*
* @param \Kirby\Cms\Page $page
* @param int $position
* @return bool
* @throws \Kirby\Exception\InvalidArgumentException If the given position is invalid
* @throws \Kirby\Exception\PermissionException If the user is not allowed to change the status or the status for the page cannot be changed by any user
*/
public static function changeStatusToListed(Page $page, int $position) public static function changeStatusToListed(Page $page, int $position)
{ {
// no need to check for status changing permissions, // no need to check for status changing permissions,
@@ -148,6 +192,13 @@ class PageRules
return true; return true;
} }
/**
* Validates if the status of a page can be changed to unlisted
*
* @param \Kirby\Cms\Page $page
* @return bool
* @throws \Kirby\Exception\PermissionException If the user is not allowed to change the status
*/
public static function changeStatusToUnlisted(Page $page) public static function changeStatusToUnlisted(Page $page)
{ {
if ($page->permissions()->changeStatus() !== true) { if ($page->permissions()->changeStatus() !== true) {
@@ -162,6 +213,15 @@ class PageRules
return true; return true;
} }
/**
* Validates if the template of the page can be changed
*
* @param \Kirby\Cms\Page $page
* @param string $template
* @return bool
* @throws \Kirby\Exception\LogicException If the template of the page cannot be changed at all
* @throws \Kirby\Exception\PermissionException If the user is not allowed to change the template
*/
public static function changeTemplate(Page $page, string $template): bool public static function changeTemplate(Page $page, string $template): bool
{ {
if ($page->permissions()->changeTemplate() !== true) { if ($page->permissions()->changeTemplate() !== true) {
@@ -183,6 +243,15 @@ class PageRules
return true; return true;
} }
/**
* Validates if the title of the page can be changed
*
* @param \Kirby\Cms\Page $page
* @param string $title
* @return bool
* @throws \Kirby\Exception\InvalidArgumentException If the new title is empty
* @throws \Kirby\Exception\PermissionException If the user is not allowed to change the title
*/
public static function changeTitle(Page $page, string $title): bool public static function changeTitle(Page $page, string $title): bool
{ {
if (Str::length($title) === 0) { if (Str::length($title) === 0) {
@@ -203,6 +272,15 @@ class PageRules
return true; return true;
} }
/**
* Validates if the page can be created
*
* @param \Kirby\Cms\Page $page
* @return bool
* @throws \Kirby\Exception\DuplicateException If the same page or a draft already exists
* @throws \Kirby\Exception\InvalidArgumentException If the slug is invalid
* @throws \Kirby\Exception\PermissionException If the user is not allowed to create this page
*/
public static function create(Page $page): bool public static function create(Page $page): bool
{ {
if (Str::length($page->slug()) < 1) { if (Str::length($page->slug()) < 1) {
@@ -211,6 +289,8 @@ class PageRules
]); ]);
} }
self::validateSlugLength($page->slug());
if ($page->exists() === true) { if ($page->exists() === true) {
throw new DuplicateException([ throw new DuplicateException([
'key' => 'page.draft.duplicate', 'key' => 'page.draft.duplicate',
@@ -250,6 +330,15 @@ class PageRules
return true; return true;
} }
/**
* Validates if the page can be deleted
*
* @param \Kirby\Cms\Page $page
* @param bool $force
* @return bool
* @throws \Kirby\Exception\LogicException If the page has children and should not be force-deleted
* @throws \Kirby\Exception\PermissionException If the user is not allowed to delete the page
*/
public static function delete(Page $page, bool $force = false): bool public static function delete(Page $page, bool $force = false): bool
{ {
if ($page->permissions()->delete() !== true) { if ($page->permissions()->delete() !== true) {
@@ -268,6 +357,15 @@ class PageRules
return true; return true;
} }
/**
* Validates if the page can be duplicated
*
* @param \Kirby\Cms\Page $page
* @param string $slug
* @param array $options
* @return bool
* @throws \Kirby\Exception\PermissionException If the user is not allowed to duplicate the page
*/
public static function duplicate(Page $page, string $slug, array $options = []): bool public static function duplicate(Page $page, string $slug, array $options = []): bool
{ {
if ($page->permissions()->duplicate() !== true) { if ($page->permissions()->duplicate() !== true) {
@@ -282,6 +380,14 @@ class PageRules
return true; return true;
} }
/**
* Validates if the page can be updated
*
* @param \Kirby\Cms\Page $page
* @param array $content
* @return bool
* @throws \Kirby\Exception\PermissionException If the user is not allowed to update the page
*/
public static function update(Page $page, array $content = []): bool public static function update(Page $page, array $content = []): bool
{ {
if ($page->permissions()->update() !== true) { if ($page->permissions()->update() !== true) {
@@ -295,4 +401,28 @@ class PageRules
return true; return true;
} }
/**
* Ensures that the slug doesn't exceed the maximum length to make
* sure that the directory name will be accepted by the filesystem
*
* @param string $slug New slug to check
* @return void
* @throws \Kirby\Exception\InvalidArgumentException If the slug is too long
*/
protected static function validateSlugLength(string $slug): void
{
if ($slugsMaxlength = App::instance()->option('slugs.maxlength', 255)) {
$maxlength = (int)$slugsMaxlength;
if (Str::length($slug) > $maxlength) {
throw new InvalidArgumentException([
'key' => 'page.slug.maxlength',
'data' => [
'length' => $maxlength
]
]);
}
}
}
} }

View File

@@ -141,6 +141,7 @@ trait PageSiblings
/** /**
* @deprecated 3.0.0 Use `Page::hasNextUnlisted()` instead * @deprecated 3.0.0 Use `Page::hasNextUnlisted()` instead
* @return bool * @return bool
* @codeCoverageIgnore
*/ */
public function hasNextInvisible(): bool public function hasNextInvisible(): bool
{ {
@@ -152,6 +153,7 @@ trait PageSiblings
/** /**
* @deprecated 3.0.0 Use `Page::hasNextListed()` instead * @deprecated 3.0.0 Use `Page::hasNextListed()` instead
* @return bool * @return bool
* @codeCoverageIgnore
*/ */
public function hasNextVisible(): bool public function hasNextVisible(): bool
{ {
@@ -163,6 +165,7 @@ trait PageSiblings
/** /**
* @deprecated 3.0.0 Use `Page::hasPrevUnlisted()` instead * @deprecated 3.0.0 Use `Page::hasPrevUnlisted()` instead
* @return bool * @return bool
* @codeCoverageIgnore
*/ */
public function hasPrevInvisible(): bool public function hasPrevInvisible(): bool
{ {
@@ -174,6 +177,7 @@ trait PageSiblings
/** /**
* @deprecated 3.0.0 Use `Page::hasPrevListed()` instead * @deprecated 3.0.0 Use `Page::hasPrevListed()` instead
* @return bool * @return bool
* @codeCoverageIgnore
*/ */
public function hasPrevVisible(): bool public function hasPrevVisible(): bool
{ {
@@ -185,6 +189,7 @@ trait PageSiblings
/** /**
* @deprecated 3.0.0 Use `Page::nextUnlisted()` instead * @deprecated 3.0.0 Use `Page::nextUnlisted()` instead
* @return self|null * @return self|null
* @codeCoverageIgnore
*/ */
public function nextInvisible() public function nextInvisible()
{ {
@@ -197,6 +202,7 @@ trait PageSiblings
/** /**
* @deprecated 3.0.0 Use `Page::nextListed()` instead * @deprecated 3.0.0 Use `Page::nextListed()` instead
* @return self|null * @return self|null
* @codeCoverageIgnore
*/ */
public function nextVisible() public function nextVisible()
{ {
@@ -208,6 +214,7 @@ trait PageSiblings
/** /**
* @deprecated 3.0.0 Use `Page::prevUnlisted()` instead * @deprecated 3.0.0 Use `Page::prevUnlisted()` instead
* @return self|null * @return self|null
* @codeCoverageIgnore
*/ */
public function prevInvisible() public function prevInvisible()
{ {
@@ -219,6 +226,7 @@ trait PageSiblings
/** /**
* @deprecated 3.0.0 Use `Page::prevListed()` instead * @deprecated 3.0.0 Use `Page::prevListed()` instead
* @return self|null * @return self|null
* @codeCoverageIgnore
*/ */
public function prevVisible() public function prevVisible()
{ {

View File

@@ -43,6 +43,7 @@ class Pages extends Collection
* *
* @param mixed $object * @param mixed $object
* @return self * @return self
* @throws \Kirby\Exception\InvalidArgumentException
*/ */
public function add($object) public function add($object)
{ {
@@ -136,7 +137,7 @@ class Pages extends Collection
* Creates a pages collection from an array of props * Creates a pages collection from an array of props
* *
* @param array $pages * @param array $pages
* @param \Kirby\Cms\Model $model * @param \Kirby\Cms\Model|null $model
* @param bool $draft * @param bool $draft
* @return self * @return self
*/ */
@@ -354,6 +355,7 @@ class Pages extends Collection
* @deprecated 3.0.0 Use `Pages::unlisted()` instead * @deprecated 3.0.0 Use `Pages::unlisted()` instead
* *
* @return self * @return self
* @codeCoverageIgnore
*/ */
public function invisible() public function invisible()
{ {
@@ -514,6 +516,7 @@ class Pages extends Collection
* @deprecated 3.0.0 Use `Pages::listed()` instead * @deprecated 3.0.0 Use `Pages::listed()` instead
* *
* @return \Kirby\Cms\Pages * @return \Kirby\Cms\Pages
* @codeCoverageIgnore
*/ */
public function visible() public function visible()
{ {

View File

@@ -24,6 +24,12 @@ use Throwable;
*/ */
class Panel class Panel
{ {
/**
* Returns custom css path for panel ui
*
* @param \Kirby\Cms\App $kirby
* @return bool|string
*/
public static function customCss(App $kirby) public static function customCss(App $kirby)
{ {
if ($css = $kirby->option('panel.css')) { if ($css = $kirby->option('panel.css')) {
@@ -37,6 +43,12 @@ class Panel
return false; return false;
} }
/**
* Returns predefined icons path as sprite svg file
*
* @param \Kirby\Cms\App $kirby
* @return string
*/
public static function icons(App $kirby): string public static function icons(App $kirby): string
{ {
return F::read($kirby->root('kirby') . '/panel/dist/img/icons.svg'); return F::read($kirby->root('kirby') . '/panel/dist/img/icons.svg');
@@ -48,6 +60,7 @@ class Panel
* *
* @param \Kirby\Cms\App $kirby * @param \Kirby\Cms\App $kirby
* @return bool * @return bool
* @throws \Exception If Panel assets could not be moved to the public directory
*/ */
public static function link(App $kirby): bool public static function link(App $kirby): bool
{ {
@@ -79,7 +92,7 @@ class Panel
* Renders the main panel view * Renders the main panel view
* *
* @param \Kirby\Cms\App $kirby * @param \Kirby\Cms\App $kirby
* @return \Kirby\Cms\Response * @return \Kirby\Http\Response
*/ */
public static function render(App $kirby) public static function render(App $kirby)
{ {

View File

@@ -17,8 +17,14 @@ use Kirby\Exception\InvalidArgumentException;
*/ */
class Permissions class Permissions
{ {
/**
* @var array
*/
public static $extendedActions = []; public static $extendedActions = [];
/**
* @var array
*/
protected $actions = [ protected $actions = [
'access' => [ 'access' => [
'panel' => true, 'panel' => true,
@@ -76,6 +82,12 @@ class Permissions
] ]
]; ];
/**
* Permissions constructor
*
* @param array $settings
* @throws \Kirby\Exception\InvalidArgumentException
*/
public function __construct($settings = []) public function __construct($settings = [])
{ {
// dynamically register the extended actions // dynamically register the extended actions
@@ -96,6 +108,11 @@ class Permissions
} }
} }
/**
* @param string|null $category
* @param string|null $action
* @return bool
*/
public function for(string $category = null, string $action = null): bool public function for(string $category = null, string $action = null): bool
{ {
if ($action === null) { if ($action === null) {
@@ -113,16 +130,31 @@ class Permissions
return $this->actions[$category][$action]; return $this->actions[$category][$action];
} }
/**
* @param string $category
* @param string $action
* @return bool
*/
protected function hasAction(string $category, string $action): bool protected function hasAction(string $category, string $action): bool
{ {
return $this->hasCategory($category) === true && array_key_exists($action, $this->actions[$category]) === true; return $this->hasCategory($category) === true && array_key_exists($action, $this->actions[$category]) === true;
} }
/**
* @param string $category
* @return bool
*/
protected function hasCategory(string $category): bool protected function hasCategory(string $category): bool
{ {
return array_key_exists($category, $this->actions) === true; return array_key_exists($category, $this->actions) === true;
} }
/**
* @param string $category
* @param string $action
* @param $setting
* @return self
*/
protected function setAction(string $category, string $action, $setting) protected function setAction(string $category, string $action, $setting)
{ {
// wildcard to overwrite the entire category // wildcard to overwrite the entire category
@@ -135,6 +167,10 @@ class Permissions
return $this; return $this;
} }
/**
* @param bool $setting
* @return self
*/
protected function setAll(bool $setting) protected function setAll(bool $setting)
{ {
foreach ($this->actions as $categoryName => $actions) { foreach ($this->actions as $categoryName => $actions) {
@@ -144,6 +180,10 @@ class Permissions
return $this; return $this;
} }
/**
* @param array $settings
* @return self
*/
protected function setCategories(array $settings) protected function setCategories(array $settings)
{ {
foreach ($settings as $categoryName => $categoryActions) { foreach ($settings as $categoryName => $categoryActions) {
@@ -161,6 +201,12 @@ class Permissions
return $this; return $this;
} }
/**
* @param string $category
* @param bool $setting
* @return self
* @throws \Kirby\Exception\InvalidArgumentException
*/
protected function setCategory(string $category, bool $setting) protected function setCategory(string $category, bool $setting)
{ {
if ($this->hasCategory($category) === false) { if ($this->hasCategory($category) === false) {
@@ -174,6 +220,9 @@ class Permissions
return $this; return $this;
} }
/**
* @return array
*/
public function toArray(): array public function toArray(): array
{ {
return $this->actions; return $this->actions;

View File

@@ -117,7 +117,7 @@ abstract class Picker
* @param \Kirby\Cms\Collection $items * @param \Kirby\Cms\Collection $items
* @return \Kirby\Cms\Collection * @return \Kirby\Cms\Collection
*/ */
public function paginate($items) public function paginate(Collection $items)
{ {
return $items->paginate([ return $items->paginate([
'limit' => $this->options['limit'], 'limit' => $this->options['limit'],
@@ -148,7 +148,7 @@ abstract class Picker
* @param \Kirby\Cms\Collection $items * @param \Kirby\Cms\Collection $items
* @return \Kirby\Cms\Collection * @return \Kirby\Cms\Collection
*/ */
public function search($items) public function search(Collection $items)
{ {
if (empty($this->options['search']) === false) { if (empty($this->options['search']) === false) {
return $items->search($this->options['search']); return $items->search($this->options['search']);

View File

@@ -24,11 +24,22 @@ class Plugin extends Model
protected $name; protected $name;
protected $root; protected $root;
/**
* @param string $key
* @param array|null $arguments
* @return mixed|null
*/
public function __call(string $key, array $arguments = null) public function __call(string $key, array $arguments = null)
{ {
return $this->info()[$key] ?? null; return $this->info()[$key] ?? null;
} }
/**
* Plugin constructor
*
* @param string $name
* @param array $extends
*/
public function __construct(string $name, array $extends = []) public function __construct(string $name, array $extends = [])
{ {
$this->setName($name); $this->setName($name);
@@ -38,11 +49,17 @@ class Plugin extends Model
unset($this->extends['root']); unset($this->extends['root']);
} }
/**
* @return array
*/
public function extends(): array public function extends(): array
{ {
return $this->extends; return $this->extends;
} }
/**
* @return array
*/
public function info(): array public function info(): array
{ {
if (is_array($this->info) === true) { if (is_array($this->info) === true) {
@@ -59,36 +76,58 @@ class Plugin extends Model
return $this->info = $info; return $this->info = $info;
} }
/**
* @return string
*/
public function manifest(): string public function manifest(): string
{ {
return $this->root() . '/composer.json'; return $this->root() . '/composer.json';
} }
/**
* @return string
*/
public function mediaRoot(): string public function mediaRoot(): string
{ {
return App::instance()->root('media') . '/plugins/' . $this->name(); return App::instance()->root('media') . '/plugins/' . $this->name();
} }
/**
* @return string
*/
public function mediaUrl(): string public function mediaUrl(): string
{ {
return App::instance()->url('media') . '/plugins/' . $this->name(); return App::instance()->url('media') . '/plugins/' . $this->name();
} }
/**
* @return string
*/
public function name(): string public function name(): string
{ {
return $this->name; return $this->name;
} }
/**
* @param string $key
* @return mixed
*/
public function option(string $key) public function option(string $key)
{ {
return $this->kirby()->option($this->prefix() . '.' . $key); return $this->kirby()->option($this->prefix() . '.' . $key);
} }
/**
* @return string
*/
public function prefix(): string public function prefix(): string
{ {
return str_replace('/', '.', $this->name()); return str_replace('/', '.', $this->name());
} }
/**
* @return string
*/
public function root(): string public function root(): string
{ {
return $this->root; return $this->root;
@@ -97,6 +136,7 @@ class Plugin extends Model
/** /**
* @param string $name * @param string $name
* @return self * @return self
* @throws \Kirby\Exception\InvalidArgumentException
*/ */
protected function setName(string $name) protected function setName(string $name)
{ {
@@ -108,6 +148,9 @@ class Plugin extends Model
return $this; return $this;
} }
/**
* @return array
*/
public function toArray(): array public function toArray(): array
{ {
return $this->propertiesToArray(); return $this->propertiesToArray();

View File

@@ -57,7 +57,7 @@ class Responder
/** /**
* Setter and getter for the response body * Setter and getter for the response body
* *
* @param string $body * @param string|null $body
* @return string|self * @return string|self
*/ */
public function body(string $body = null) public function body(string $body = null)
@@ -73,7 +73,7 @@ class Responder
/** /**
* Setter and getter for the status code * Setter and getter for the status code
* *
* @param int $code * @param int|null $code
* @return int|self * @return int|self
*/ */
public function code(int $code = null) public function code(int $code = null)
@@ -124,7 +124,7 @@ class Responder
/** /**
* Setter and getter for all headers * Setter and getter for all headers
* *
* @param array $headers * @param array|null $headers
* @return array|self * @return array|self
*/ */
public function headers(array $headers = null) public function headers(array $headers = null)
@@ -140,7 +140,7 @@ class Responder
/** /**
* Shortcut to configure a json response * Shortcut to configure a json response
* *
* @param array $json * @param array|null $json
* @return string|self * @return string|self
*/ */
public function json(array $json = null) public function json(array $json = null)
@@ -203,7 +203,7 @@ class Responder
/** /**
* Setter and getter for the content type * Setter and getter for the content type
* *
* @param string $type * @param string|null $type
* @return string|self * @return string|self
*/ */
public function type(string $type = null) public function type(string $type = null)

View File

@@ -19,8 +19,8 @@ class Response extends \Kirby\Http\Response
* parses locations with the Url::to method * parses locations with the Url::to method
* first. * first.
* *
* @param string $location * @param string|null $location
* @param int $code * @param int|null $code
* @return self * @return self
*/ */
public static function redirect(?string $location = null, ?int $code = null) public static function redirect(?string $location = null, ?int $code = null)

View File

@@ -39,11 +39,18 @@ class Role extends Model
return $this->toArray(); return $this->toArray();
} }
/**
* @return string
*/
public function __toString(): string public function __toString(): string
{ {
return $this->name(); return $this->name();
} }
/**
* @param array $inject
* @return self
*/
public static function admin(array $inject = []) public static function admin(array $inject = [])
{ {
try { try {
@@ -53,6 +60,9 @@ class Role extends Model
} }
} }
/**
* @return array
*/
protected static function defaults(): array protected static function defaults(): array
{ {
return [ return [
@@ -71,6 +81,9 @@ class Role extends Model
]; ];
} }
/**
* @return mixed
*/
public function description() public function description()
{ {
return $this->description; return $this->description;
@@ -86,16 +99,25 @@ class Role extends Model
return new static($props + $inject); return new static($props + $inject);
} }
/**
* @return string
*/
public function id(): string public function id(): string
{ {
return $this->name(); return $this->name();
} }
/**
* @return bool
*/
public function isAdmin(): bool public function isAdmin(): bool
{ {
return $this->name() === 'admin'; return $this->name() === 'admin';
} }
/**
* @return bool
*/
public function isNobody(): bool public function isNobody(): bool
{ {
return $this->name() === 'nobody'; return $this->name() === 'nobody';
@@ -114,6 +136,9 @@ class Role extends Model
return static::factory($data, $inject); return static::factory($data, $inject);
} }
/**
* @return string
*/
public function name(): string public function name(): string
{ {
return $this->name; return $this->name;
@@ -180,6 +205,9 @@ class Role extends Model
return $this; return $this;
} }
/**
* @return string
*/
public function title(): string public function title(): string
{ {
return $this->title = $this->title ?? ucfirst($this->name()); return $this->title = $this->title ?? ucfirst($this->name());

View File

@@ -24,6 +24,7 @@ class Roles extends Collection
* current user * current user
* *
* @return self * @return self
* @throws \Exception
*/ */
public function canBeChanged() public function canBeChanged()
{ {
@@ -47,6 +48,7 @@ class Roles extends Collection
* current user * current user
* *
* @return self * @return self
* @throws \Exception
*/ */
public function canBeCreated() public function canBeCreated()
{ {
@@ -89,7 +91,7 @@ class Roles extends Collection
} }
/** /**
* @param string $root * @param string|null $root
* @param array $inject * @param array $inject
* @return self * @return self
*/ */

View File

@@ -17,7 +17,7 @@ namespace Kirby\Cms;
class Search class Search
{ {
/** /**
* @param string $query * @param string|null $query
* @param array $params * @param array $params
* @return \Kirby\Cms\Files * @return \Kirby\Cms\Files
*/ */
@@ -30,7 +30,7 @@ class Search
* Native search method to search for anything within the collection * Native search method to search for anything within the collection
* *
* @param \Kirby\Cms\Collection $collection * @param \Kirby\Cms\Collection $collection
* @param string $query * @param string|null $query
* @param mixed $params * @param mixed $params
* @return \Kirby\Cms\Collection|bool * @return \Kirby\Cms\Collection|bool
*/ */
@@ -41,7 +41,7 @@ class Search
} }
/** /**
* @param string $query * @param string|null $query
* @param array $params * @param array $params
* @return \Kirby\Cms\Pages * @return \Kirby\Cms\Pages
*/ */
@@ -51,7 +51,7 @@ class Search
} }
/** /**
* @param string $query * @param string|null $query
* @param array $params * @param array $params
* @return \Kirby\Cms\Users * @return \Kirby\Cms\Users
*/ */

View File

@@ -31,6 +31,13 @@ class Section extends Component
public static $types = []; public static $types = [];
/**
* Section constructor.
*
* @param string $type
* @param array $attrs
* @throws \Kirby\Exception\InvalidArgumentException
*/
public function __construct(string $type, array $attrs = []) public function __construct(string $type, array $attrs = [])
{ {
if (isset($attrs['model']) === false) { if (isset($attrs['model']) === false) {
@@ -60,6 +67,9 @@ class Section extends Component
return $this->model; return $this->model;
} }
/**
* @return array
*/
public function toArray(): array public function toArray(): array
{ {
$array = parent::toArray(); $array = parent::toArray();
@@ -69,6 +79,9 @@ class Section extends Component
return $array; return $array;
} }
/**
* @return array
*/
public function toResponse(): array public function toResponse(): array
{ {
return array_merge([ return array_merge([

View File

@@ -140,6 +140,17 @@ class Site extends ModelWithContent
]); ]);
} }
/**
* Makes it possible to convert the site model
* to a string. Mostly useful for debugging
*
* @return string
*/
public function __toString(): string
{
return $this->url();
}
/** /**
* Returns the url to the api endpoint * Returns the url to the api endpoint
* *
@@ -170,32 +181,6 @@ class Site extends ModelWithContent
return $this->blueprint = SiteBlueprint::factory('site', null, $this); return $this->blueprint = SiteBlueprint::factory('site', null, $this);
} }
/**
* Returns an array with all blueprints that are available
* as subpages of the site
*
* @param string $inSection
* @return array
*/
public function blueprints(string $inSection = null): array
{
$blueprints = [];
$blueprint = $this->blueprint();
$sections = $inSection !== null ? [$blueprint->section($inSection)] : $blueprint->sections();
foreach ($sections as $section) {
if ($section === null) {
continue;
}
foreach ((array)$section->blueprints() as $blueprint) {
$blueprints[$blueprint['name']] = $blueprint;
}
}
return array_values($blueprints);
}
/** /**
* Builds a breadcrumb collection * Builds a breadcrumb collection
* *
@@ -220,7 +205,7 @@ class Site extends ModelWithContent
* *
* @internal * @internal
* @param array $data * @param array $data
* @param string $languageCode * @param string|null $languageCode
* @return array * @return array
*/ */
public function contentFileData(array $data, string $languageCode = null): array public function contentFileData(array $data, string $languageCode = null): array
@@ -391,7 +376,7 @@ class Site extends ModelWithContent
* prop, the home page will be returned if * prop, the home page will be returned if
* it can be found. (see `Site::homePage()`) * it can be found. (see `Site::homePage()`)
* *
* @param string $path * @param string|null $path
* @return \Kirby\Cms\Page|null * @return \Kirby\Cms\Page|null
*/ */
public function page(string $path = null) public function page(string $path = null)
@@ -507,7 +492,7 @@ class Site extends ModelWithContent
/** /**
* Search all pages in the site * Search all pages in the site
* *
* @param string $query * @param string|null $query
* @param array $params * @param array $params
* @return \Kirby\Cms\Pages * @return \Kirby\Cms\Pages
*/ */
@@ -578,7 +563,7 @@ class Site extends ModelWithContent
/** /**
* Sets the Url * Sets the Url
* *
* @param string $url * @param string|null $url
* @return self * @return self
*/ */
protected function setUrl($url = null) protected function setUrl($url = null)
@@ -626,8 +611,8 @@ class Site extends ModelWithContent
* Returns the translated url * Returns the translated url
* *
* @internal * @internal
* @param string $languageCode * @param string|null $languageCode
* @param array $options * @param array|null $options
* @return string * @return string
*/ */
public function urlForLanguage(string $languageCode = null, array $options = null): string public function urlForLanguage(string $languageCode = null, array $options = null): string

View File

@@ -41,7 +41,7 @@ class SiteBlueprint extends Blueprint
/** /**
* Returns the preview settings * Returns the preview settings
* The preview setting controlls the "Open" * The preview setting controls the "Open"
* button in the panel and redirects it to a * button in the panel and redirects it to a
* different URL if necessary. * different URL if necessary.
* *

View File

@@ -17,6 +17,15 @@ use Kirby\Toolkit\Str;
*/ */
class SiteRules class SiteRules
{ {
/**
* Validates if the site title can be changed
*
* @param \Kirby\Cms\Site $site
* @param string $title
* @return bool
* @throws \Kirby\Exception\InvalidArgumentException If the title is empty
* @throws \Kirby\Exception\PermissionException If the user is not allowed to change the title
*/
public static function changeTitle(Site $site, string $title): bool public static function changeTitle(Site $site, string $title): bool
{ {
if ($site->permissions()->changeTitle() !== true) { if ($site->permissions()->changeTitle() !== true) {
@@ -30,6 +39,14 @@ class SiteRules
return true; return true;
} }
/**
* Validates if the site can be updated
*
* @param \Kirby\Cms\Site $site
* @param array $content
* @return bool
* @throws \Kirby\Exception\PermissionException If the user is not allowed to update the site
*/
public static function update(Site $site, array $content = []): bool public static function update(Site $site, array $content = []): bool
{ {
if ($site->permissions()->update() !== true) { if ($site->permissions()->update() !== true) {

View File

@@ -24,7 +24,7 @@ class Structure extends Collection
* Creates a new Collection with the given objects * Creates a new Collection with the given objects
* *
* @param array $objects * @param array $objects
* @param object $parent * @param object|null $parent
*/ */
public function __construct($objects = [], $parent = null) public function __construct($objects = [], $parent = null)
{ {
@@ -40,6 +40,7 @@ class Structure extends Collection
* *
* @param string $id * @param string $id
* @param array|StructureObject $props * @param array|StructureObject $props
* @throws \Kirby\Exception\InvalidArgumentException
*/ */
public function __set(string $id, $props) public function __set(string $id, $props)
{ {

View File

@@ -170,7 +170,7 @@ class StructureObject extends Model
/** /**
* Sets the parent Structure collection * Sets the parent Structure collection
* *
* @param \Kirby\Cms\Structure $structure * @param \Kirby\Cms\Structure|null $structure
* @return self * @return self
*/ */
protected function setStructure(Structure $structure = null) protected function setStructure(Structure $structure = null)

View File

@@ -33,7 +33,7 @@ use Throwable;
class System class System
{ {
/** /**
* @var App * @var \Kirby\Cms\App
*/ */
protected $app; protected $app;
@@ -135,6 +135,7 @@ class System
* if they don't exist yet * if they don't exist yet
* *
* @return void * @return void
* @throws \Kirby\Exception\PermissionException
*/ */
public function init() public function init()
{ {
@@ -374,9 +375,11 @@ class System
* and adds it to the .license file in the config * and adds it to the .license file in the config
* folder if possible. * folder if possible.
* *
* @param string $license * @param string|null $license
* @param string $email * @param string|null $email
* @return bool * @return bool
* @throws \Kirby\Exception\Exception
* @throws \Kirby\Exception\InvalidArgumentException
*/ */
public function register(string $license = null, string $email = null): bool public function register(string $license = null, string $email = null): bool
{ {

View File

@@ -113,8 +113,8 @@ class Translation
* string by key * string by key
* *
* @param string $key * @param string $key
* @param string $default * @param string|null $default
* @return void * @return string|null
*/ */
public function get(string $key, string $default = null): ?string public function get(string $key, string $default = null): ?string
{ {

View File

@@ -19,11 +19,19 @@ use Kirby\Toolkit\F;
*/ */
class Translations extends Collection class Translations extends Collection
{ {
/**
* @param string $code
* @return void
*/
public function start(string $code): void public function start(string $code): void
{ {
F::move($this->parent->contentFile('', true), $this->parent->contentFile($code, true)); F::move($this->parent->contentFile('', true), $this->parent->contentFile($code, true));
} }
/**
* @param string $code
* @return void
*/
public function stop(string $code): void public function stop(string $code): void
{ {
F::move($this->parent->contentFile($code, true), $this->parent->contentFile('', true)); F::move($this->parent->contentFile($code, true), $this->parent->contentFile('', true));

View File

@@ -54,7 +54,7 @@ class Url extends BaseUrl
/** /**
* Smart resolver for internal and external urls * Smart resolver for internal and external urls
* *
* @param string $path * @param string|null $path
* @param array|string|null $options Either an array of options for the Uri class or a language string * @param array|string|null $options Either an array of options for the Uri class or a language string
* @return string * @return string
*/ */

View File

@@ -82,7 +82,7 @@ class User extends ModelWithContent
public static $models = []; public static $models = [];
/** /**
* @var string * @var \Kirby\Cms\Field
*/ */
protected $name; protected $name;
@@ -176,7 +176,7 @@ class User extends ModelWithContent
/** /**
* Returns the UserBlueprint object * Returns the UserBlueprint object
* *
* @return \Kirby\Cms\UserBlueprint * @return \Kirby\Cms\Blueprint
*/ */
public function blueprint() public function blueprint()
{ {
@@ -200,7 +200,7 @@ class User extends ModelWithContent
* *
* @internal * @internal
* @param array $data * @param array $data
* @param string $languageCode Not used so far * @param string $languageCode|null Not used so far
* @return array * @return array
*/ */
public function contentFileData(array $data, string $languageCode = null): array public function contentFileData(array $data, string $languageCode = null): array
@@ -400,10 +400,8 @@ class User extends ModelWithContent
* Logs the user in * Logs the user in
* *
* @param string $password * @param string $password
* @param \Kirby\Session\Session|array $session Session options or session object to set the user in * @param \Kirby\Session\Session|array|null $session Session options or session object to set the user in
* @return bool * @return bool
*
* @throws \Kirby\Exception\PermissionException If the password is not valid
*/ */
public function login(string $password, $session = null): bool public function login(string $password, $session = null): bool
{ {
@@ -416,7 +414,7 @@ class User extends ModelWithContent
/** /**
* Logs the user in without checking the password * Logs the user in without checking the password
* *
* @param \Kirby\Session\Session|array $session Session options or session object to set the user in * @param \Kirby\Session\Session|array|null $session Session options or session object to set the user in
* @return void * @return void
*/ */
public function loginPasswordless($session = null): void public function loginPasswordless($session = null): void
@@ -437,7 +435,7 @@ class User extends ModelWithContent
/** /**
* Logs the user out * Logs the user out
* *
* @param \Kirby\Session\Session|array $session Session options or session object to unset the user in * @param \Kirby\Session\Session|array|null $session Session options or session object to unset the user in
* @return void * @return void
*/ */
public function logout($session = null): void public function logout($session = null): void
@@ -757,7 +755,7 @@ class User extends ModelWithContent
/** /**
* Sets the user email * Sets the user email
* *
* @param string $email * @param string $email|null
* @return self * @return self
*/ */
protected function setEmail(string $email = null) protected function setEmail(string $email = null)
@@ -771,7 +769,7 @@ class User extends ModelWithContent
/** /**
* Sets the user id * Sets the user id
* *
* @param string $id * @param string $id|null
* @return self * @return self
*/ */
protected function setId(string $id = null) protected function setId(string $id = null)
@@ -783,7 +781,7 @@ class User extends ModelWithContent
/** /**
* Sets the user language * Sets the user language
* *
* @param string $language * @param string $language|null
* @return self * @return self
*/ */
protected function setLanguage(string $language = null) protected function setLanguage(string $language = null)
@@ -795,7 +793,7 @@ class User extends ModelWithContent
/** /**
* Sets the user name * Sets the user name
* *
* @param string $name * @param string $name|null
* @return self * @return self
*/ */
protected function setName(string $name = null) protected function setName(string $name = null)
@@ -807,7 +805,7 @@ class User extends ModelWithContent
/** /**
* Sets the user's password hash * Sets the user's password hash
* *
* @param string $password * @param string $password|null
* @return self * @return self
*/ */
protected function setPassword(string $password = null) protected function setPassword(string $password = null)
@@ -819,7 +817,7 @@ class User extends ModelWithContent
/** /**
* Sets the user role * Sets the user role
* *
* @param string $role * @param string $role|null
* @return self * @return self
*/ */
protected function setRole(string $role = null) protected function setRole(string $role = null)
@@ -907,12 +905,12 @@ class User extends ModelWithContent
/** /**
* Compares the given password with the stored one * Compares the given password with the stored one
* *
* @param string $password * @param string $password|null
* @return bool * @return bool
* *
* @throws \Kirby\Exception\NotFoundException If the user has no password * @throws \Kirby\Exception\NotFoundException If the user has no password
* @throws \Kirby\Exception\InvalidArgumentException If the entered password is not valid * @throws \Kirby\Exception\InvalidArgumentException If the entered password is not valid
* @throws \Kirby\Exception\InvalidArgumentException If the entered password does not match the user password * or does not match the user password
*/ */
public function validatePassword(string $password = null): bool public function validatePassword(string $password = null): bool
{ {

View File

@@ -136,8 +136,9 @@ trait UserActions
* *
* @param string $action * @param string $action
* @param array $arguments * @param array $arguments
* @param Closure $callback * @param \Closure $callback
* @return mixed * @return mixed
* @throws \Kirby\Exception\PermissionException
*/ */
protected function commit(string $action, array $arguments = [], Closure $callback) protected function commit(string $action, array $arguments = [], Closure $callback)
{ {
@@ -170,7 +171,7 @@ trait UserActions
/** /**
* Creates a new User from the given props and returns a new User object * Creates a new User from the given props and returns a new User object
* *
* @param array $props * @param array|null $props
* @return self * @return self
*/ */
public static function create(array $props = null) public static function create(array $props = null)
@@ -245,6 +246,7 @@ trait UserActions
* Deletes the user * Deletes the user
* *
* @return bool * @return bool
* @throws \Kirby\Exception\LogicException
*/ */
public function delete(): bool public function delete(): bool
{ {
@@ -299,8 +301,8 @@ trait UserActions
/** /**
* Updates the user data * Updates the user data
* *
* @param array $input * @param array|null $input
* @param string $language * @param string|null $language
* @param bool $validate * @param bool $validate
* @return self * @return self
*/ */
@@ -342,7 +344,7 @@ trait UserActions
/** /**
* Writes the password to disk * Writes the password to disk
* *
* @param string $password * @param string|null $password
* @return bool * @return bool
*/ */
protected function writePassword(string $password = null): bool protected function writePassword(string $password = null): bool

View File

@@ -14,6 +14,12 @@ namespace Kirby\Cms;
*/ */
class UserBlueprint extends Blueprint class UserBlueprint extends Blueprint
{ {
/**
* UserBlueprint constructor.
*
* @param array $props
* @throws \Kirby\Exception\InvalidArgumentException
*/
public function __construct(array $props) public function __construct(array $props)
{ {
// normalize and translate the description // normalize and translate the description

View File

@@ -13,8 +13,16 @@ namespace Kirby\Cms;
*/ */
class UserPermissions extends ModelPermissions class UserPermissions extends ModelPermissions
{ {
/**
* @var string
*/
protected $category = 'users'; protected $category = 'users';
/**
* UserPermissions constructor
*
* @param \Kirby\Cms\Model $model
*/
public function __construct(Model $model) public function __construct(Model $model)
{ {
parent::__construct($model); parent::__construct($model);
@@ -23,11 +31,17 @@ class UserPermissions extends ModelPermissions
$this->category = $this->user && $this->user->is($model) ? 'user' : 'users'; $this->category = $this->user && $this->user->is($model) ? 'user' : 'users';
} }
/**
* @return bool
*/
protected function canChangeRole(): bool protected function canChangeRole(): bool
{ {
return $this->model->roles()->count() > 1; return $this->model->roles()->count() > 1;
} }
/**
* @return bool
*/
protected function canCreate(): bool protected function canCreate(): bool
{ {
// the admin can always create new users // the admin can always create new users
@@ -43,6 +57,9 @@ class UserPermissions extends ModelPermissions
return true; return true;
} }
/**
* @return bool
*/
protected function canDelete(): bool protected function canDelete(): bool
{ {
return $this->model->isLastAdmin() !== true; return $this->model->isLastAdmin() !== true;

View File

@@ -34,6 +34,7 @@ class UserPicker extends Picker
* Search all users for the picker * Search all users for the picker
* *
* @return \Kirby\Cms\Users|null * @return \Kirby\Cms\Users|null
* @throws \Kirby\Exception\InvalidArgumentException
*/ */
public function items() public function items()
{ {

View File

@@ -20,6 +20,14 @@ use Kirby\Toolkit\V;
*/ */
class UserRules class UserRules
{ {
/**
* Validates if the email address can be changed
*
* @param \Kirby\Cms\User $user
* @param string $email
* @return bool
* @throws \Kirby\Exception\PermissionException If the user is not allowed to change the address
*/
public static function changeEmail(User $user, string $email): bool public static function changeEmail(User $user, string $email): bool
{ {
if ($user->permissions()->changeEmail() !== true) { if ($user->permissions()->changeEmail() !== true) {
@@ -32,6 +40,14 @@ class UserRules
return static::validEmail($user, $email); return static::validEmail($user, $email);
} }
/**
* Validates if the language can be changed
*
* @param \Kirby\Cms\User $user
* @param string $language
* @return bool
* @throws \Kirby\Exception\PermissionException If the user is not allowed to change the language
*/
public static function changeLanguage(User $user, string $language): bool public static function changeLanguage(User $user, string $language): bool
{ {
if ($user->permissions()->changeLanguage() !== true) { if ($user->permissions()->changeLanguage() !== true) {
@@ -44,6 +60,14 @@ class UserRules
return static::validLanguage($user, $language); return static::validLanguage($user, $language);
} }
/**
* Validates if the name can be changed
*
* @param \Kirby\Cms\User $user
* @param string $name
* @return bool
* @throws \Kirby\Exception\PermissionException If the user is not allowed to change the name
*/
public static function changeName(User $user, string $name): bool public static function changeName(User $user, string $name): bool
{ {
if ($user->permissions()->changeName() !== true) { if ($user->permissions()->changeName() !== true) {
@@ -56,6 +80,14 @@ class UserRules
return true; return true;
} }
/**
* Validates if the password can be changed
*
* @param \Kirby\Cms\User $user
* @param string $password
* @return bool
* @throws \Kirby\Exception\PermissionException If the user is not allowed to change the password
*/
public static function changePassword(User $user, string $password): bool public static function changePassword(User $user, string $password): bool
{ {
if ($user->permissions()->changePassword() !== true) { if ($user->permissions()->changePassword() !== true) {
@@ -68,6 +100,15 @@ class UserRules
return static::validPassword($user, $password); return static::validPassword($user, $password);
} }
/**
* Validates if the role can be changed
*
* @param \Kirby\Cms\User $user
* @param string $role
* @return bool
* @throws \Kirby\Exception\LogicException If the user is the last admin
* @throws \Kirby\Exception\PermissionException If the user is not allowed to change the role
*/
public static function changeRole(User $user, string $role): bool public static function changeRole(User $user, string $role): bool
{ {
// protect admin from role changes by non-admin // protect admin from role changes by non-admin
@@ -110,19 +151,27 @@ class UserRules
return true; return true;
} }
/**
* Validates if the user can be created
*
* @param \Kirby\Cms\User $user
* @param array $props
* @return bool
* @throws \Kirby\Exception\PermissionException If the user is not allowed to create a new user
*/
public static function create(User $user, array $props = []): bool public static function create(User $user, array $props = []): bool
{ {
static::validId($user, $user->id()); static::validId($user, $user->id());
static::validEmail($user, $user->email(), true); static::validEmail($user, $user->email(), true);
static::validLanguage($user, $user->language()); static::validLanguage($user, $user->language());
if (empty($props['password']) === false) { if (empty($props['password']) === false) {
static::validPassword($user, $props['password']); static::validPassword($user, $props['password']);
} }
// get the current user if it exists // get the current user if it exists
$currentUser = $user->kirby()->user(); $currentUser = $user->kirby()->user();
// admins are allowed everything // admins are allowed everything
if ($currentUser && $currentUser->isAdmin() === true) { if ($currentUser && $currentUser->isAdmin() === true) {
return true; return true;
@@ -136,7 +185,7 @@ class UserRules
'key' => 'user.create.permission' 'key' => 'user.create.permission'
]); ]);
} }
// check user permissions (if not on install) // check user permissions (if not on install)
if ($user->kirby()->users()->count() > 0) { if ($user->kirby()->users()->count() > 0) {
if ($user->permissions()->create() !== true) { if ($user->permissions()->create() !== true) {
@@ -149,6 +198,14 @@ class UserRules
return true; return true;
} }
/**
* Validates if the user can be deleted
*
* @param \Kirby\Cms\User $user
* @return bool
* @throws \Kirby\Exception\LogicException If this is the last user or last admin, which cannot be deleted
* @throws \Kirby\Exception\PermissionException If the user is not allowed to delete this user
*/
public static function delete(User $user): bool public static function delete(User $user): bool
{ {
if ($user->isLastAdmin() === true) { if ($user->isLastAdmin() === true) {
@@ -171,6 +228,15 @@ class UserRules
return true; return true;
} }
/**
* Validates if the user can be updated
*
* @param \Kirby\Cms\User $user
* @param array $values
* @param array $strings
* @return bool
* @throws \Kirby\Exception\PermissionException If the user it not allowed to update this user
*/
public static function update(User $user, array $values = [], array $strings = []): bool public static function update(User $user, array $values = [], array $strings = []): bool
{ {
if ($user->permissions()->update() !== true) { if ($user->permissions()->update() !== true) {
@@ -183,6 +249,16 @@ class UserRules
return true; return true;
} }
/**
* Validates an email address
*
* @param \Kirby\Cms\User $user
* @param string $email
* @param bool $strict
* @return bool
* @throws \Kirby\Exception\DuplicateException If the email address already exists
* @throws \Kirby\Exception\InvalidArgumentException If the email address is invalid
*/
public static function validEmail(User $user, string $email, bool $strict = false): bool public static function validEmail(User $user, string $email, bool $strict = false): bool
{ {
if (V::email($email ?? null) === false) { if (V::email($email ?? null) === false) {
@@ -207,6 +283,14 @@ class UserRules
return true; return true;
} }
/**
* Validates a user id
*
* @param \Kirby\Cms\User $user
* @param string $id
* @return bool
* @throws \Kirby\Exception\DuplicateException If the user already exists
*/
public static function validId(User $user, string $id): bool public static function validId(User $user, string $id): bool
{ {
if ($user->kirby()->users()->find($id)) { if ($user->kirby()->users()->find($id)) {
@@ -216,6 +300,14 @@ class UserRules
return true; return true;
} }
/**
* Validates a user language code
*
* @param \Kirby\Cms\User $user
* @param string $language
* @return bool
* @throws \Kirby\Exception\InvalidArgumentException If the language does not exist
*/
public static function validLanguage(User $user, string $language): bool public static function validLanguage(User $user, string $language): bool
{ {
if (in_array($language, $user->kirby()->translations()->keys(), true) === false) { if (in_array($language, $user->kirby()->translations()->keys(), true) === false) {
@@ -227,6 +319,14 @@ class UserRules
return true; return true;
} }
/**
* Validates a password
*
* @param \Kirby\Cms\User $user
* @param string $password
* @return bool
* @throws \Kirby\Exception\InvalidArgumentException If the password is too short
*/
public static function validPassword(User $user, string $password): bool public static function validPassword(User $user, string $password): bool
{ {
if (Str::length($password ?? null) < 8) { if (Str::length($password ?? null) < 8) {
@@ -238,6 +338,14 @@ class UserRules
return true; return true;
} }
/**
* Validates a user role
*
* @param \Kirby\Cms\User $user
* @param string $role
* @return bool
* @throws \Kirby\Exception\InvalidArgumentException If the user role does not exist
*/
public static function validRole(User $user, string $role): bool public static function validRole(User $user, string $role): bool
{ {
if (is_a($user->kirby()->roles()->find($role), 'Kirby\Cms\Role') === true) { if (is_a($user->kirby()->roles()->find($role), 'Kirby\Cms\Role') === true) {

View File

@@ -8,7 +8,6 @@ use Kirby\Exception\InvalidArgumentException;
use Kirby\Toolkit\A; use Kirby\Toolkit\A;
use Kirby\Toolkit\Str; use Kirby\Toolkit\Str;
use PDO; use PDO;
use PDOStatement;
use Throwable; use Throwable;
/** /**
@@ -39,7 +38,7 @@ class Database
/** /**
* The established connection * The established connection
* *
* @var PDO|null * @var \PDO|null
*/ */
protected $connection; protected $connection;
@@ -79,7 +78,7 @@ class Database
/** /**
* The last error * The last error
* *
* @var Exception|null * @var \Exception|null
*/ */
protected $lastError; protected $lastError;
@@ -114,16 +113,16 @@ class Database
/** /**
* The PDO query statement * The PDO query statement
* *
* @var PDOStatement|null * @var \PDOStatement|null
*/ */
protected $statement; protected $statement;
/** /**
* Whitelists for table names * List of existing tables in the database
* *
* @var array|null * @var array|null
*/ */
protected $tableWhitelist; protected $tables;
/** /**
* An array with all queries which are being made * An array with all queries which are being made
@@ -156,10 +155,10 @@ class Database
} }
/** /**
* Returns one of the started instance * Returns one of the started instances
* *
* @param string $id * @param string|null $id
* @return self * @return self|null
*/ */
public static function instance(string $id = null) public static function instance(string $id = null)
{ {
@@ -180,7 +179,8 @@ class Database
* Connects to a database * Connects to a database
* *
* @param array|null $params This can either be a config key or an array of parameters for the connection * @param array|null $params This can either be a config key or an array of parameters for the connection
* @return \Kirby\Database\Database * @return \PDO|null
* @throws \Kirby\Exception\InvalidArgumentException
*/ */
public function connect(array $params = null) public function connect(array $params = null)
{ {
@@ -223,9 +223,9 @@ class Database
/** /**
* Returns the currently active connection * Returns the currently active connection
* *
* @return \Kirby\Database\Database|null * @return \PDO|null
*/ */
public function connection() public function connection(): ?PDO
{ {
return $this->connection; return $this->connection;
} }
@@ -277,10 +277,10 @@ class Database
/** /**
* Adds a value to the db trace and also returns the entire trace if nothing is specified * Adds a value to the db trace and also returns the entire trace if nothing is specified
* *
* @param array $data * @param array|null $data
* @return array * @return array
*/ */
public function trace($data = null): array public function trace(array $data = null): array
{ {
// return the full trace // return the full trace
if ($data === null) { if ($data === null) {
@@ -336,7 +336,7 @@ class Database
/** /**
* Returns the last db error * Returns the last db error
* *
* @return Throwable * @return \Throwable
*/ */
public function lastError() public function lastError()
{ {
@@ -363,7 +363,6 @@ class Database
*/ */
protected function hit(string $query, array $bindings = []): bool protected function hit(string $query, array $bindings = []): bool
{ {
// try to prepare and execute the sql // try to prepare and execute the sql
try { try {
$this->statement = $this->connection->prepare($query); $this->statement = $this->connection->prepare($query);
@@ -401,7 +400,7 @@ class Database
} }
/** /**
* Exectues a sql query, which is expected to return a set of results * Executes a sql query, which is expected to return a set of results
* *
* @param string $query * @param string $query
* @param array $bindings * @param array $bindings
@@ -504,19 +503,19 @@ class Database
*/ */
public function validateTable(string $table): bool public function validateTable(string $table): bool
{ {
if ($this->tableWhitelist === null) { if ($this->tables === null) {
// Get the table whitelist from the database // Get the list of tables from the database
$sql = $this->sql()->tables($this->database); $sql = $this->sql()->tables($this->database);
$results = $this->query($sql['query'], $sql['bindings']); $results = $this->query($sql['query'], $sql['bindings']);
if ($results) { if ($results) {
$this->tableWhitelist = $results->pluck('name'); $this->tables = $results->pluck('name');
} else { } else {
return false; return false;
} }
} }
return in_array($table, $this->tableWhitelist) === true; return in_array($table, $this->tables) === true;
} }
/** /**
@@ -569,8 +568,8 @@ class Database
} }
// update cache // update cache
if (in_array($table, $this->tableWhitelist) !== true) { if (in_array($table, $this->tables ?? []) !== true) {
$this->tableWhitelist[] = $table; $this->tables[] = $table;
} }
return true; return true;
@@ -582,7 +581,7 @@ class Database
* @param string $table * @param string $table
* @return bool * @return bool
*/ */
public function dropTable($table): bool public function dropTable(string $table): bool
{ {
$sql = $this->sql()->dropTable($table); $sql = $this->sql()->dropTable($table);
if ($this->execute($sql['query'], $sql['bindings']) !== true) { if ($this->execute($sql['query'], $sql['bindings']) !== true) {
@@ -590,9 +589,9 @@ class Database
} }
// update cache // update cache
$key = array_search($this->tableWhitelist, $table); $key = array_search($table, $this->tables ?? []);
if ($key !== false) { if ($key !== false) {
unset($this->tableWhitelist[$key]); unset($this->tables[$key]);
} }
return true; return true;
@@ -605,6 +604,7 @@ class Database
* *
* @param mixed $method * @param mixed $method
* @param mixed $arguments * @param mixed $arguments
* @return \Kirby\Database\Query
*/ */
public function __call($method, $arguments = null) public function __call($method, $arguments = null)
{ {

View File

@@ -26,7 +26,7 @@ class Db
/** /**
* The singleton Database object * The singleton Database object
* *
* @var Database * @var \Kirby\Database\Database
*/ */
public static $connection = null; public static $connection = null;
@@ -76,7 +76,7 @@ class Db
* @param string $table * @param string $table
* @return \Kirby\Database\Query * @return \Kirby\Database\Query
*/ */
public static function table($table) public static function table(string $table)
{ {
$db = static::connect(); $db = static::connect();
return $db->table($table); return $db->table($table);
@@ -117,8 +117,9 @@ class Db
* @param string $method * @param string $method
* @param mixed $arguments * @param mixed $arguments
* @return mixed * @return mixed
* @throws \Kirby\Exception\InvalidArgumentException
*/ */
public static function __callStatic($method, $arguments) public static function __callStatic(string $method, $arguments)
{ {
if (isset(static::$queries[$method])) { if (isset(static::$queries[$method])) {
return static::$queries[$method](...$arguments); return static::$queries[$method](...$arguments);

View File

@@ -24,7 +24,7 @@ class Query
/** /**
* Parent Database object * Parent Database object
* *
* @var Database * @var \Kirby\Database\Database
*/ */
protected $database = null; protected $database = null;
@@ -251,6 +251,7 @@ class Query
* *
* @param string $table * @param string $table
* @return \Kirby\Database\Query * @return \Kirby\Database\Query
* @throws \Kirby\Exception\InvalidArgumentException if the table does not exist
*/ */
public function table(string $table) public function table(string $table)
{ {
@@ -293,7 +294,7 @@ class Query
* @param string $table Name of the table, which should be joined * @param string $table Name of the table, which should be joined
* @param string $on The on clause for this join * @param string $on The on clause for this join
* @param string $type The join type. Uses an inner join by default * @param string $type The join type. Uses an inner join by default
* @return object * @return self
*/ */
public function join(string $table, string $on, string $type = 'JOIN') public function join(string $table, string $on, string $type = 'JOIN')
{ {
@@ -362,7 +363,7 @@ class Query
* Also can be used as getter for all attached bindings by not passing an argument. * Also can be used as getter for all attached bindings by not passing an argument.
* *
* @param mixed $bindings Array of bindings or null to use this method as getter * @param mixed $bindings Array of bindings or null to use this method as getter
* @return array|Query * @return array|\Kirby\Database\Query
*/ */
public function bindings(array $bindings = null) public function bindings(array $bindings = null)
{ {
@@ -445,7 +446,7 @@ class Query
/** /**
* Attaches a group by clause * Attaches a group by clause
* *
* @param string $group * @param string|null $group
* @return \Kirby\Database\Query * @return \Kirby\Database\Query
*/ */
public function group(string $group = null) public function group(string $group = null)
@@ -477,7 +478,7 @@ class Query
/** /**
* Attaches an order clause * Attaches an order clause
* *
* @param string $order * @param string|null $order
* @return \Kirby\Database\Query * @return \Kirby\Database\Query
*/ */
public function order(string $order = null) public function order(string $order = null)
@@ -489,7 +490,7 @@ class Query
/** /**
* Sets the offset for select clauses * Sets the offset for select clauses
* *
* @param int $offset * @param int|null $offset
* @return \Kirby\Database\Query * @return \Kirby\Database\Query
*/ */
public function offset(int $offset = null) public function offset(int $offset = null)
@@ -501,7 +502,7 @@ class Query
/** /**
* Sets the limit for select clauses * Sets the limit for select clauses
* *
* @param int $limit * @param int|null $limit
* @return \Kirby\Database\Query * @return \Kirby\Database\Query
*/ */
public function limit(int $limit = null) public function limit(int $limit = null)
@@ -515,9 +516,9 @@ class Query
* This uses the SQL class to build stuff. * This uses the SQL class to build stuff.
* *
* @param string $type (select, update, insert) * @param string $type (select, update, insert)
* @return string The final query * @return array The final query
*/ */
public function build($type) public function build(string $type)
{ {
$sql = $this->database->sql(); $sql = $this->database->sql();
@@ -618,7 +619,7 @@ class Query
* *
* @param string $method * @param string $method
* @param string $column * @param string $column
* @param string $default An optional default value, which should be returned if the query fails * @param int $default An optional default value, which should be returned if the query fails
* @return mixed * @return mixed
*/ */
public function aggregate(string $method, string $column = '*', $default = 0) public function aggregate(string $method, string $column = '*', $default = 0)
@@ -812,7 +813,7 @@ class Query
* @param string $column * @param string $column
* @return mixed * @return mixed
*/ */
public function column($column) public function column(string $column)
{ {
// if there isn't already an explicit order, order by the primary key // if there isn't already an explicit order, order by the primary key
// instead of the column that was requested (which would be implied otherwise) // instead of the column that was requested (which would be implied otherwise)
@@ -850,7 +851,7 @@ class Query
* @param mixed $value * @param mixed $value
* @return mixed * @return mixed
*/ */
public function findBy($column, $value) public function findBy(string $column, $value)
{ {
return $this->where([$column => $value])->first(); return $this->where([$column => $value])->first();
} }
@@ -869,7 +870,7 @@ class Query
/** /**
* Fires an insert query * Fires an insert query
* *
* @param array $values You can pass values here or set them with ->values() before * @param mixed $values You can pass values here or set them with ->values() before
* @return mixed Returns the last inserted id on success or false. * @return mixed Returns the last inserted id on success or false.
*/ */
public function insert($values = null) public function insert($values = null)
@@ -886,7 +887,7 @@ class Query
/** /**
* Fires an update query * Fires an update query
* *
* @param array $values You can pass values here or set them with ->values() before * @param mixed $values You can pass values here or set them with ->values() before
* @param mixed $where You can pass a where clause here or set it with ->where() before * @param mixed $where You can pass a where clause here or set it with ->where() before
* @return bool * @return bool
*/ */
@@ -927,10 +928,10 @@ class Query
* Builder for where and having clauses * Builder for where and having clauses
* *
* @param array $args Arguments, see where() description * @param array $args Arguments, see where() description
* @param string $current Current value (like $this->where) * @param mixed $current Current value (like $this->where)
* @return string * @return string
*/ */
protected function filterQuery($args, $current) protected function filterQuery(array $args, $current)
{ {
$mode = A::last($args); $mode = A::last($args);
$result = ''; $result = '';

View File

@@ -175,6 +175,7 @@ abstract class Sql
* - `unique`: Whether the index (or if not set the column itself) has a UNIQUE constraint * - `unique`: Whether the index (or if not set the column itself) has a UNIQUE constraint
* - `default`: Default value of this column * - `default`: Default value of this column
* @return array Array with `query` and `key` strings, a `unique` boolean and a `bindings` array * @return array Array with `query` and `key` strings, a `unique` boolean and a `bindings` array
* @throws \Kirby\Exception\InvalidArgumentException if no column type is given or the column type is not supported.
*/ */
public function createColumn(string $name, array $column): array public function createColumn(string $name, array $column): array
{ {
@@ -408,7 +409,7 @@ abstract class Sql
/** /**
* Creates the having syntax * Creates the having syntax
* *
* @param string $having * @param string|null $having
* @return array * @return array
*/ */
public function having(string $having = null): array public function having(string $having = null): array
@@ -455,6 +456,7 @@ abstract class Sql
* @param string $type * @param string $type
* @param string $on * @param string $on
* @return array * @return array
* @throws \Kirby\Exception\InvalidArgumentException if an invalid join type is given
*/ */
public function join(string $type, string $table, string $on): array public function join(string $type, string $table, string $on): array
{ {
@@ -489,7 +491,7 @@ abstract class Sql
/** /**
* Create the syntax for multiple joins * Create the syntax for multiple joins
* *
* @param array $joins * @param array|null $joins
* @return array * @return array
*/ */
public function joins(array $joins = null): array public function joins(array $joins = null): array
@@ -692,6 +694,7 @@ abstract class Sql
* @param $table string Default table if the identifier is not qualified * @param $table string Default table if the identifier is not qualified
* @param $identifier string * @param $identifier string
* @return array * @return array
* @throws \Kirby\Exception\InvalidArgumentException if an invalid identifier is given
*/ */
public function splitIdentifier($table, $identifier): array public function splitIdentifier($table, $identifier): array
{ {
@@ -726,6 +729,7 @@ abstract class Sql
* *
* @param string $table * @param string $table
* @return string * @return string
* @throws \Kirby\Exception\InvalidArgumentException if an invalid table name is given
*/ */
public function tableName(string $table): string public function tableName(string $table): string
{ {
@@ -797,7 +801,6 @@ abstract class Sql
* @param string $table * @param string $table
* @param string $column * @param string $column
* @return bool * @return bool
*
* @throws \Kirby\Exception\InvalidArgumentException If the column is invalid * @throws \Kirby\Exception\InvalidArgumentException If the column is invalid
*/ */
public function validateColumn(string $table, string $column): bool public function validateColumn(string $table, string $column): bool
@@ -882,6 +885,7 @@ abstract class Sql
* @param string $separator * @param string $separator
* @param bool $enforceQualified * @param bool $enforceQualified
* @param array * @param array
* @return array
*/ */
public function valueSet(string $table, $values, string $separator = ',', bool $enforceQualified = false): array public function valueSet(string $table, $values, string $separator = ',', bool $enforceQualified = false): array
{ {

View File

@@ -23,6 +23,20 @@ use Kirby\Toolkit\V;
*/ */
class Field extends Component class Field extends Component
{ {
/**
* An array of all found errors
*
* @var array|null
*/
protected $errors;
/**
* Parent collection with all fields of the current form
*
* @var \Kirby\Form\Fields|null
*/
protected $formFields;
/** /**
* Registry for all component mixins * Registry for all component mixins
* *
@@ -37,14 +51,7 @@ class Field extends Component
*/ */
public static $types = []; public static $types = [];
/** public function __construct(string $type, array $attrs = [], ?Fields $formFields = null)
* An array of all found errors
*
* @var array
*/
protected $errors = [];
public function __construct(string $type, array $attrs = [])
{ {
if (isset(static::$types[$type]) === false) { if (isset(static::$types[$type]) === false) {
throw new InvalidArgumentException('The field type "' . $type . '" does not exist'); throw new InvalidArgumentException('The field type "' . $type . '" does not exist');
@@ -54,13 +61,13 @@ class Field extends Component
throw new InvalidArgumentException('Field requires a model'); throw new InvalidArgumentException('Field requires a model');
} }
$this->formFields = $formFields;
// use the type as fallback for the name // use the type as fallback for the name
$attrs['name'] = $attrs['name'] ?? $type; $attrs['name'] = $attrs['name'] ?? $type;
$attrs['type'] = $type; $attrs['type'] = $type;
parent::__construct($type, $attrs); parent::__construct($type, $attrs);
$this->validate();
} }
/** /**
@@ -225,8 +232,17 @@ class Field extends Component
]; ];
} }
public function formFields(): ?Fields
{
return $this->formFields;
}
public function errors(): array public function errors(): array
{ {
if ($this->errors === null) {
$this->validate();
}
return $this->errors; return $this->errors;
} }
@@ -247,7 +263,7 @@ class Field extends Component
public function isInvalid(): bool public function isInvalid(): bool
{ {
return empty($this->errors) === false; return empty($this->errors()) === false;
} }
public function isRequired(): bool public function isRequired(): bool
@@ -257,7 +273,7 @@ class Field extends Component
public function isValid(): bool public function isValid(): bool
{ {
return empty($this->errors) === true; return empty($this->errors()) === true;
} }
/** /**
@@ -273,6 +289,46 @@ class Field extends Component
return $this->model; return $this->model;
} }
/**
* Checks if the field needs a value before being saved;
* this is the case if all of the following requirements are met:
* - The field is saveable
* - The field is required
* - The field is currently empty
* - The field is not currently inactive because of a `when` rule
*
* @return bool
*/
protected function needsValue(): bool
{
// check simple conditions first
if ($this->save() === false || $this->isRequired() === false || $this->isEmpty() === false) {
return false;
}
// check the data of the relevant fields if there is a `when` option
if (empty($this->when) === false && is_array($this->when) === true) {
$formFields = $this->formFields();
if ($formFields !== null) {
foreach ($this->when as $field => $value) {
$field = $formFields->get($field);
$inputValue = $field !== null ? $field->value() : '';
// if the input data doesn't match the requested `when` value,
// that means that this field is not required and can be saved
// (*all* `when` conditions must be met for this field to be required)
if ($inputValue !== $value) {
return false;
}
}
}
}
// either there was no `when` condition or all conditions matched
return true;
}
public function save(): bool public function save(): bool
{ {
return ($this->options['save'] ?? true) !== false; return ($this->options['save'] ?? true) !== false;
@@ -302,7 +358,7 @@ class Field extends Component
$this->errors = []; $this->errors = [];
// validate required values // validate required values
if ($this->isRequired() === true && $this->save() === true && $this->isEmpty() === true) { if ($this->needsValue() === true) {
$this->errors['required'] = I18n::translate('error.validation.required'); $this->errors['required'] = I18n::translate('error.validation.required');
} }

View File

@@ -59,7 +59,7 @@ class Form
} }
try { try {
$field = new Field($props['type'], $props); $field = new Field($props['type'], $props, $this->fields);
} catch (Throwable $e) { } catch (Throwable $e) {
$field = static::exceptionField($e, $props); $field = static::exceptionField($e, $props);
} }

View File

@@ -23,11 +23,25 @@ class Darkroom
protected $settings = []; protected $settings = [];
/**
* Darkroom constructor
*
* @param array $settings
*/
public function __construct(array $settings = []) public function __construct(array $settings = [])
{ {
$this->settings = array_merge($this->defaults(), $settings); $this->settings = array_merge($this->defaults(), $settings);
} }
/**
* Creates a new Darkroom instance for the given
* type/driver
*
* @param string $type
* @param array $settings
* @return mixed
* @throws \Exception
*/
public static function factory(string $type, array $settings = []) public static function factory(string $type, array $settings = [])
{ {
if (isset(static::$types[$type]) === false) { if (isset(static::$types[$type]) === false) {
@@ -38,6 +52,11 @@ class Darkroom
return new $class($settings); return new $class($settings);
} }
/**
* Returns the default thumb settings
*
* @return array
*/
protected function defaults(): array protected function defaults(): array
{ {
return [ return [
@@ -51,6 +70,12 @@ class Darkroom
]; ];
} }
/**
* Normalizes all thumb options
*
* @param array $options
* @return array
*/
protected function options(array $options = []): array protected function options(array $options = []): array
{ {
$options = array_merge($this->settings, $options); $options = array_merge($this->settings, $options);
@@ -84,6 +109,15 @@ class Darkroom
return $options; return $options;
} }
/**
* Calculates the dimensions of the final thumb based
* on the given options and returns a full array with
* all the final options to be used for the image generator
*
* @param string $file
* @param array $options
* @return array
*/
public function preprocess(string $file, array $options = []) public function preprocess(string $file, array $options = [])
{ {
$options = $this->options($options); $options = $this->options($options);
@@ -96,6 +130,14 @@ class Darkroom
return $options; return $options;
} }
/**
* This method must be replaced by the driver to run the
* actual image processing job.
*
* @param string $file
* @param array $options
* @return array
*/
public function process(string $file, array $options = []): array public function process(string $file, array $options = []): array
{ {
return $this->preprocess($file, $options); return $this->preprocess($file, $options);

View File

@@ -18,6 +18,13 @@ use Kirby\Image\Darkroom;
*/ */
class GdLib extends Darkroom class GdLib extends Darkroom
{ {
/**
* Processes the image with the SimpleImage library
*
* @param string $file
* @param array $options
* @return array
*/
public function process(string $file, array $options = []): array public function process(string $file, array $options = []): array
{ {
$options = $this->preprocess($file, $options); $options = $this->preprocess($file, $options);
@@ -35,6 +42,14 @@ class GdLib extends Darkroom
return $options; return $options;
} }
/**
* Activates the autoOrient option in SimpleImage
* unless this is deactivated
*
* @param \claviska\SimpleImage $image
* @param $options
* @return \claviska\SimpleImage
*/
protected function autoOrient(SimpleImage $image, $options) protected function autoOrient(SimpleImage $image, $options)
{ {
if ($options['autoOrient'] === false) { if ($options['autoOrient'] === false) {
@@ -44,6 +59,13 @@ class GdLib extends Darkroom
return $image->autoOrient(); return $image->autoOrient();
} }
/**
* Wrapper around SimpleImage's resize and crop methods
*
* @param \claviska\SimpleImage $image
* @param array $options
* @return \claviska\SimpleImage
*/
protected function resize(SimpleImage $image, array $options) protected function resize(SimpleImage $image, array $options)
{ {
if ($options['crop'] === false) { if ($options['crop'] === false) {
@@ -53,6 +75,13 @@ class GdLib extends Darkroom
return $image->thumbnail($options['width'], $options['height'] ?? $options['width'], $options['crop']); return $image->thumbnail($options['width'], $options['height'] ?? $options['width'], $options['crop']);
} }
/**
* Applies the correct blur settings for SimpleImage
*
* @param \claviska\SimpleImage $image
* @param array $options
* @return \claviska\SimpleImage
*/
protected function blur(SimpleImage $image, array $options) protected function blur(SimpleImage $image, array $options)
{ {
if ($options['blur'] === false) { if ($options['blur'] === false) {
@@ -62,6 +91,13 @@ class GdLib extends Darkroom
return $image->blur('gaussian', (int)$options['blur']); return $image->blur('gaussian', (int)$options['blur']);
} }
/**
* Applies grayscale conversion if activated in the options.
*
* @param \claviska\SimpleImage $image
* @param array $options
* @return \claviska\SimpleImage
*/
protected function grayscale(SimpleImage $image, array $options) protected function grayscale(SimpleImage $image, array $options)
{ {
if ($options['grayscale'] === false) { if ($options['grayscale'] === false) {

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