Add blueprints and fake content
This commit is contained in:
parent
1ff19bf38f
commit
8235816462
592 changed files with 22385 additions and 31535 deletions
|
@ -1,14 +1,12 @@
|
|||
<?php
|
||||
|
||||
// @codeCoverageIgnoreStart
|
||||
return [
|
||||
// cms classes
|
||||
'asset' => 'Kirby\Cms\Asset',
|
||||
'collection' => 'Kirby\Cms\Collection',
|
||||
'dir' => 'Kirby\Cms\Dir',
|
||||
'field' => 'Kirby\Cms\Field',
|
||||
'file' => 'Kirby\Cms\File',
|
||||
'files' => 'Kirby\Cms\Files',
|
||||
'find' => 'Kirby\Cms\Find',
|
||||
'html' => 'Kirby\Cms\Html',
|
||||
'kirby' => 'Kirby\Cms\App',
|
||||
'page' => 'Kirby\Cms\Page',
|
||||
|
@ -17,6 +15,7 @@ return [
|
|||
'r' => 'Kirby\Cms\R',
|
||||
'response' => 'Kirby\Cms\Response',
|
||||
's' => 'Kirby\Cms\S',
|
||||
'sane' => 'Kirby\Sane\Sane',
|
||||
'site' => 'Kirby\Cms\Site',
|
||||
'structure' => 'Kirby\Cms\Structure',
|
||||
'url' => 'Kirby\Cms\Url',
|
||||
|
@ -29,6 +28,12 @@ return [
|
|||
'json' => 'Kirby\Data\Json',
|
||||
'yaml' => 'Kirby\Data\Yaml',
|
||||
|
||||
// file classes
|
||||
'asset' => 'Kirby\Filesystem\Asset',
|
||||
'dir' => 'Kirby\Filesystem\Dir',
|
||||
'f' => 'Kirby\Filesystem\F',
|
||||
'mime' => 'Kirby\Filesystem\Mime',
|
||||
|
||||
// data classes
|
||||
'database' => 'Kirby\Database\Database',
|
||||
'db' => 'Kirby\Database\Db',
|
||||
|
@ -45,18 +50,31 @@ return [
|
|||
// image classes
|
||||
'dimensions' => 'Kirby\Image\Dimensions',
|
||||
|
||||
// panel classes
|
||||
'panel' => 'Kirby\Panel\Panel',
|
||||
|
||||
// toolkit classes
|
||||
'a' => 'Kirby\Toolkit\A',
|
||||
'c' => 'Kirby\Toolkit\Config',
|
||||
'config' => 'Kirby\Toolkit\Config',
|
||||
'escape' => 'Kirby\Toolkit\Escape',
|
||||
'f' => 'Kirby\Toolkit\F',
|
||||
'i18n' => 'Kirby\Toolkit\I18n',
|
||||
'mime' => 'Kirby\Toolkit\Mime',
|
||||
'obj' => 'Kirby\Toolkit\Obj',
|
||||
'str' => 'Kirby\Toolkit\Str',
|
||||
'tpl' => 'Kirby\Toolkit\Tpl',
|
||||
'v' => 'Kirby\Toolkit\V',
|
||||
'xml' => 'Kirby\Toolkit\Xml'
|
||||
'xml' => 'Kirby\Toolkit\Xml',
|
||||
|
||||
// TODO: remove in 4.0.0
|
||||
'kirby\cms\asset' => 'Kirby\Filesystem\Asset',
|
||||
'kirby\cms\dir' => 'Kirby\Filesystem\Dir',
|
||||
'kirby\cms\filename' => 'Kirby\Filesystem\Filename',
|
||||
'kirby\cms\filefoundation' => 'Kirby\Filesystem\IsFile',
|
||||
'kirby\cms\form' => 'Kirby\Form\Form',
|
||||
'kirby\cms\kirbytag' => 'Kirby\Text\KirbyTag',
|
||||
'kirby\cms\kirbytags' => 'Kirby\Text\KirbyTags',
|
||||
'kirby\toolkit\dir' => 'Kirby\Filesystem\Dir',
|
||||
'kirby\toolkit\f' => 'Kirby\Filesystem\F',
|
||||
'kirby\toolkit\file' => 'Kirby\Filesystem\File',
|
||||
'kirby\toolkit\mime' => 'Kirby\Filesystem\Mime',
|
||||
];
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
|
|
@ -7,7 +7,10 @@ return function () {
|
|||
$allowImpersonation = $this->kirby()->option('api.allowImpersonation') ?? false;
|
||||
|
||||
// csrf token check
|
||||
if ($auth->type($allowImpersonation) === 'session' && $auth->csrf() === false) {
|
||||
if (
|
||||
$auth->type($allowImpersonation) === 'session' &&
|
||||
$auth->csrf() === false
|
||||
) {
|
||||
throw new PermissionException('Unauthenticated');
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
|
||||
use Kirby\Cms\File;
|
||||
use Kirby\Cms\Form;
|
||||
use Kirby\Form\Form;
|
||||
|
||||
/**
|
||||
* File
|
||||
|
@ -18,7 +18,7 @@ return [
|
|||
return $file->dimensions()->toArray();
|
||||
},
|
||||
'dragText' => function (File $file) {
|
||||
return $file->dragText();
|
||||
return $file->panel()->dragText();
|
||||
},
|
||||
'exists' => function (File $file) {
|
||||
return $file->exists();
|
||||
|
@ -33,7 +33,7 @@ return [
|
|||
return $file->id();
|
||||
},
|
||||
'link' => function (File $file) {
|
||||
return $file->panelUrl(true);
|
||||
return $file->panel()->url(true);
|
||||
},
|
||||
'mime' => function (File $file) {
|
||||
return $file->mime();
|
||||
|
@ -48,7 +48,7 @@ return [
|
|||
return $file->next();
|
||||
},
|
||||
'nextWithTemplate' => function (File $file) {
|
||||
$files = $file->templateSiblings()->sort('sort', 'asc', 'filename', 'asc');
|
||||
$files = $file->templateSiblings()->sorted();
|
||||
$index = $files->indexOf($file);
|
||||
|
||||
return $files->nth($index + 1);
|
||||
|
@ -57,22 +57,26 @@ return [
|
|||
return $file->niceSize();
|
||||
},
|
||||
'options' => function (File $file) {
|
||||
return $file->panelOptions();
|
||||
return $file->panel()->options();
|
||||
},
|
||||
'panelIcon' => function (File $file) {
|
||||
return $file->panelIcon();
|
||||
// TODO: remove in 3.7.0
|
||||
// @codeCoverageIgnoreStart
|
||||
deprecated('The API field file.panelIcon has been deprecated and will be removed in 3.7.0. Use file.panelImage instead');
|
||||
return $file->panel()->image();
|
||||
// @codeCoverageIgnoreEnd
|
||||
},
|
||||
'panelImage' => function (File $file) {
|
||||
return $file->panelImage();
|
||||
return $file->panel()->image();
|
||||
},
|
||||
'panelUrl' => function (File $file) {
|
||||
return $file->panelUrl(true);
|
||||
return $file->panel()->url(true);
|
||||
},
|
||||
'prev' => function (File $file) {
|
||||
return $file->prev();
|
||||
},
|
||||
'prevWithTemplate' => function (File $file) {
|
||||
$files = $file->templateSiblings()->sort('sort', 'asc', 'filename', 'asc');
|
||||
$files = $file->templateSiblings()->sorted();
|
||||
$index = $files->indexOf($file);
|
||||
|
||||
return $files->nth($index - 1);
|
||||
|
@ -106,7 +110,7 @@ return [
|
|||
return $file->type();
|
||||
},
|
||||
'url' => function (File $file) {
|
||||
return $file->url(true);
|
||||
return $file->url();
|
||||
},
|
||||
],
|
||||
'type' => 'Kirby\Cms\File',
|
||||
|
|
|
@ -41,7 +41,7 @@ return [
|
|||
return $file->type();
|
||||
},
|
||||
'url' => function (FileVersion $file) {
|
||||
return $file->url(true);
|
||||
return $file->url();
|
||||
},
|
||||
],
|
||||
'type' => 'Kirby\Cms\FileVersion',
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
|
||||
use Kirby\Cms\Form;
|
||||
use Kirby\Cms\Page;
|
||||
use Kirby\Form\Form;
|
||||
|
||||
/**
|
||||
* Page
|
||||
|
@ -27,7 +27,7 @@ return [
|
|||
return $page->errors();
|
||||
},
|
||||
'files' => function (Page $page) {
|
||||
return $page->files()->sort('sort', 'asc', 'filename', 'asc');
|
||||
return $page->files()->sorted();
|
||||
},
|
||||
'hasChildren' => function (Page $page) {
|
||||
return $page->hasChildren();
|
||||
|
@ -44,6 +44,12 @@ return [
|
|||
'isSortable' => function (Page $page) {
|
||||
return $page->isSortable();
|
||||
},
|
||||
/**
|
||||
* @deprecated 3.6.0
|
||||
* @todo Throw deprecated warning in 3.7.0
|
||||
* @todo Remove in 3.8.0
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
'next' => function (Page $page) {
|
||||
return $page
|
||||
->nextAll()
|
||||
|
@ -56,13 +62,18 @@ return [
|
|||
return $page->num();
|
||||
},
|
||||
'options' => function (Page $page) {
|
||||
return $page->panelOptions(['preview']);
|
||||
return $page->panel()->options(['preview']);
|
||||
},
|
||||
/**
|
||||
* @todo Remove in 3.7.0
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
'panelIcon' => function (Page $page) {
|
||||
return $page->panelIcon();
|
||||
deprecated('The API field page.panelIcon has been deprecated and will be removed in 3.7.0. Use page.panelImage instead');
|
||||
return $page->panel()->image();
|
||||
},
|
||||
'panelImage' => function (Page $page) {
|
||||
return $page->panelImage();
|
||||
return $page->panel()->image();
|
||||
},
|
||||
'parent' => function (Page $page) {
|
||||
return $page->parent();
|
||||
|
@ -70,6 +81,12 @@ return [
|
|||
'parents' => function (Page $page) {
|
||||
return $page->parents()->flip();
|
||||
},
|
||||
/**
|
||||
* @deprecated 3.6.0
|
||||
* @todo Throw deprecated warning in 3.7.0
|
||||
* @todo Remove in 3.8.0
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
'prev' => function (Page $page) {
|
||||
return $page
|
||||
->prevAll()
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
|
||||
use Kirby\Cms\Form;
|
||||
use Kirby\Cms\Site;
|
||||
use Kirby\Form\Form;
|
||||
|
||||
/**
|
||||
* Site
|
||||
|
@ -24,7 +24,7 @@ return [
|
|||
return $site->drafts();
|
||||
},
|
||||
'files' => function (Site $site) {
|
||||
return $site->files()->sort('sort', 'asc', 'filename', 'asc');
|
||||
return $site->files()->sorted();
|
||||
},
|
||||
'options' => function (Site $site) {
|
||||
return $site->permissions()->toArray();
|
||||
|
|
|
@ -52,12 +52,8 @@ return [
|
|||
'requirements' => function (System $system) {
|
||||
return $system->toArray();
|
||||
},
|
||||
'site' => function () {
|
||||
try {
|
||||
return $this->site()->blueprint()->title();
|
||||
} catch (Throwable $e) {
|
||||
return $this->site()->title()->value();
|
||||
}
|
||||
'site' => function (System $system) {
|
||||
return $system->title();
|
||||
},
|
||||
'slugs' => function () {
|
||||
return Str::$language;
|
||||
|
@ -87,7 +83,7 @@ return [
|
|||
'version' => function () {
|
||||
$user = $this->user();
|
||||
|
||||
if ($user && $user->role()->permissions()->for('access', 'settings') === true) {
|
||||
if ($user && $user->role()->permissions()->for('access', 'system') === true) {
|
||||
return $this->kirby()->version();
|
||||
} else {
|
||||
return null;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
|
||||
use Kirby\Cms\Form;
|
||||
use Kirby\Cms\User;
|
||||
use Kirby\Form\Form;
|
||||
|
||||
/**
|
||||
* User
|
||||
|
@ -24,7 +24,7 @@ return [
|
|||
return $user->email();
|
||||
},
|
||||
'files' => function (User $user) {
|
||||
return $user->files()->sort('sort', 'asc', 'filename', 'asc');
|
||||
return $user->files()->sorted();
|
||||
},
|
||||
'id' => function (User $user) {
|
||||
return $user->id();
|
||||
|
@ -39,7 +39,10 @@ return [
|
|||
return $user->next();
|
||||
},
|
||||
'options' => function (User $user) {
|
||||
return $user->panelOptions();
|
||||
return $user->panel()->options();
|
||||
},
|
||||
'panelImage' => function (User $user) {
|
||||
return $user->panel()->image();
|
||||
},
|
||||
'permissions' => function (User $user) {
|
||||
return $user->role()->permissions()->toArray();
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
<?php
|
||||
|
||||
// routing pattern to match all models with files
|
||||
$pattern = '(account|pages/[^/]+|site|users/[^/]+)';
|
||||
|
||||
/**
|
||||
* Files Routes
|
||||
*/
|
||||
return [
|
||||
|
||||
[
|
||||
'pattern' => '(:all)/files/(:any)/sections/(:any)',
|
||||
'pattern' => $pattern . '/files/(:any)/sections/(:any)',
|
||||
'method' => 'GET',
|
||||
'action' => function (string $path, string $filename, string $sectionName) {
|
||||
if ($section = $this->file($path, $filename)->blueprint()->section($sectionName)) {
|
||||
|
@ -15,7 +18,7 @@ return [
|
|||
}
|
||||
],
|
||||
[
|
||||
'pattern' => '(:all)/files/(:any)/fields/(:any)/(:all?)',
|
||||
'pattern' => $pattern . '/files/(:any)/fields/(:any)/(:all?)',
|
||||
'method' => 'ALL',
|
||||
'action' => function (string $parent, string $filename, string $fieldName, string $path = null) {
|
||||
if ($file = $this->file($parent, $filename)) {
|
||||
|
@ -24,27 +27,33 @@ return [
|
|||
}
|
||||
],
|
||||
[
|
||||
'pattern' => '(:all)/files',
|
||||
'pattern' => $pattern . '/files',
|
||||
'method' => 'GET',
|
||||
'action' => function (string $path) {
|
||||
return $this->parent($path)->files()->sort('sort', 'asc', 'filename', 'asc');
|
||||
return $this->parent($path)->files()->sorted();
|
||||
}
|
||||
],
|
||||
[
|
||||
'pattern' => '(:all)/files',
|
||||
'pattern' => $pattern . '/files',
|
||||
'method' => 'POST',
|
||||
'action' => function (string $path) {
|
||||
// move_uploaded_file() not working with unit test
|
||||
// @codeCoverageIgnoreStart
|
||||
return $this->upload(function ($source, $filename) use ($path) {
|
||||
return $this->parent($path)->createFile([
|
||||
'content' => [
|
||||
'sort' => $this->requestBody('sort')
|
||||
],
|
||||
'source' => $source,
|
||||
'template' => $this->requestBody('template'),
|
||||
'filename' => $filename
|
||||
]);
|
||||
});
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
],
|
||||
[
|
||||
'pattern' => '(:all)/files/search',
|
||||
'pattern' => $pattern . '/files/search',
|
||||
'method' => 'GET|POST',
|
||||
'action' => function (string $path) {
|
||||
$files = $this->parent($path)->files();
|
||||
|
@ -57,7 +66,7 @@ return [
|
|||
}
|
||||
],
|
||||
[
|
||||
'pattern' => '(:all)/files/sort',
|
||||
'pattern' => $pattern . '/files/sort',
|
||||
'method' => 'PATCH',
|
||||
'action' => function (string $path) {
|
||||
return $this->parent($path)->files()->changeSort(
|
||||
|
@ -67,21 +76,21 @@ return [
|
|||
}
|
||||
],
|
||||
[
|
||||
'pattern' => '(:all)/files/(:any)',
|
||||
'pattern' => $pattern . '/files/(:any)',
|
||||
'method' => 'GET',
|
||||
'action' => function (string $path, string $filename) {
|
||||
return $this->file($path, $filename);
|
||||
}
|
||||
],
|
||||
[
|
||||
'pattern' => '(:all)/files/(:any)',
|
||||
'pattern' => $pattern . '/files/(:any)',
|
||||
'method' => 'PATCH',
|
||||
'action' => function (string $path, string $filename) {
|
||||
return $this->file($path, $filename)->update($this->requestBody(), $this->language(), true);
|
||||
}
|
||||
],
|
||||
[
|
||||
'pattern' => '(:all)/files/(:any)',
|
||||
'pattern' => $pattern . '/files/(:any)',
|
||||
'method' => 'POST',
|
||||
'action' => function (string $path, string $filename) {
|
||||
return $this->upload(function ($source) use ($path, $filename) {
|
||||
|
@ -90,14 +99,14 @@ return [
|
|||
}
|
||||
],
|
||||
[
|
||||
'pattern' => '(:all)/files/(:any)',
|
||||
'pattern' => $pattern . '/files/(:any)',
|
||||
'method' => 'DELETE',
|
||||
'action' => function (string $path, string $filename) {
|
||||
return $this->file($path, $filename)->delete();
|
||||
}
|
||||
],
|
||||
[
|
||||
'pattern' => '(:all)/files/(:any)/name',
|
||||
'pattern' => $pattern . '/files/(:any)/name',
|
||||
'method' => 'PATCH',
|
||||
'action' => function (string $path, string $filename) {
|
||||
return $this->file($path, $filename)->changeName($this->requestBody('name'));
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
<?php
|
||||
|
||||
use Kirby\Exception\Exception;
|
||||
|
||||
/**
|
||||
* Content Lock Routes
|
||||
|
@ -9,7 +8,13 @@ return [
|
|||
[
|
||||
'pattern' => '(:all)/lock',
|
||||
'method' => 'GET',
|
||||
/**
|
||||
* @deprecated 3.6.0
|
||||
* @todo Remove in 3.7.0
|
||||
*/
|
||||
'action' => function (string $path) {
|
||||
deprecated('The `GET (:all)/lock` API endpoint has been deprecated and will be removed in 3.7.0');
|
||||
|
||||
if ($lock = $this->parent($path)->lock()) {
|
||||
return [
|
||||
'supported' => true,
|
||||
|
@ -30,11 +35,6 @@ return [
|
|||
if ($lock = $this->parent($path)->lock()) {
|
||||
return $lock->create();
|
||||
}
|
||||
|
||||
throw new Exception([
|
||||
'key' => 'lock.notImplemented',
|
||||
'httpCode' => 501
|
||||
]);
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -44,17 +44,19 @@ return [
|
|||
if ($lock = $this->parent($path)->lock()) {
|
||||
return $lock->remove();
|
||||
}
|
||||
|
||||
throw new Exception([
|
||||
'key' => 'lock.notImplemented',
|
||||
'httpCode' => 501
|
||||
]);
|
||||
}
|
||||
],
|
||||
[
|
||||
'pattern' => '(:all)/unlock',
|
||||
'method' => 'GET',
|
||||
/**
|
||||
* @deprecated 3.6.0
|
||||
* @todo Remove in 3.7.0
|
||||
*/
|
||||
'action' => function (string $path) {
|
||||
deprecated('The `GET (:all)/unlock` API endpoint has been deprecated and will be removed in 3.7.0');
|
||||
|
||||
|
||||
if ($lock = $this->parent($path)->lock()) {
|
||||
return [
|
||||
'supported' => true,
|
||||
|
@ -75,11 +77,6 @@ return [
|
|||
if ($lock = $this->parent($path)->lock()) {
|
||||
return $lock->unlock();
|
||||
}
|
||||
|
||||
throw new Exception([
|
||||
'key' => 'lock.notImplemented',
|
||||
'httpCode' => 501
|
||||
]);
|
||||
}
|
||||
],
|
||||
[
|
||||
|
@ -89,11 +86,6 @@ return [
|
|||
if ($lock = $this->parent($path)->lock()) {
|
||||
return $lock->resolve();
|
||||
}
|
||||
|
||||
throw new Exception([
|
||||
'key' => 'lock.notImplemented',
|
||||
'httpCode' => 501
|
||||
]);
|
||||
}
|
||||
],
|
||||
];
|
||||
|
|
|
@ -38,12 +38,17 @@ return [
|
|||
'pages/(:any)/blueprints',
|
||||
/**
|
||||
* @deprecated
|
||||
* @todo remove in 3.6.0
|
||||
* @todo remove in 3.7.0
|
||||
*/
|
||||
'pages/(:any)/children/blueprints',
|
||||
],
|
||||
'method' => 'GET',
|
||||
'action' => function (string $id) {
|
||||
// @codeCoverageIgnoreStart
|
||||
if ($this->route->pattern() === 'pages/([a-zA-Z0-9\.\-_%= \+\@\(\)]+)/children/blueprints') {
|
||||
deprecated('`GET pages/(:any)/children/blueprints` API endpoint has been deprecated and will be removed in 3.7.0. Use `GET pages/(:any)/blueprints` instead');
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
return $this->page($id)->blueprints($this->requestQuery('section'));
|
||||
}
|
||||
],
|
||||
|
|
|
@ -51,12 +51,17 @@ return [
|
|||
'site/blueprints',
|
||||
/**
|
||||
* @deprecated
|
||||
* @todo remove in 3.6.0
|
||||
* @todo remove in 3.7.0
|
||||
*/
|
||||
'site/children/blueprints',
|
||||
],
|
||||
'method' => 'GET',
|
||||
'action' => function () {
|
||||
// @codeCoverageIgnoreStart
|
||||
if ($this->route->pattern() === 'site/children/blueprints') {
|
||||
deprecated('`GET site/children/blueprints` API endpoint has been deprecated and will be removed in 3.7.0. Use `GET site/blueprints` instead.');
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
return $this->site()->blueprints($this->requestQuery('section'));
|
||||
}
|
||||
],
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
<?php
|
||||
|
||||
use Kirby\Toolkit\F;
|
||||
use Kirby\Filesystem\F;
|
||||
|
||||
/**
|
||||
* User Routes
|
||||
*/
|
||||
return [
|
||||
|
||||
[
|
||||
'pattern' => 'users',
|
||||
'method' => 'GET',
|
||||
|
@ -33,35 +32,51 @@ return [
|
|||
}
|
||||
],
|
||||
[
|
||||
'pattern' => 'users/(:any)',
|
||||
'pattern' => [
|
||||
'(account)',
|
||||
'users/(:any)',
|
||||
],
|
||||
'method' => 'GET',
|
||||
'action' => function (string $id) {
|
||||
return $this->user($id);
|
||||
}
|
||||
],
|
||||
[
|
||||
'pattern' => 'users/(:any)',
|
||||
'pattern' => [
|
||||
'(account)',
|
||||
'users/(:any)',
|
||||
],
|
||||
'method' => 'PATCH',
|
||||
'action' => function (string $id) {
|
||||
return $this->user($id)->update($this->requestBody(), $this->language(), true);
|
||||
}
|
||||
],
|
||||
[
|
||||
'pattern' => 'users/(:any)',
|
||||
'pattern' => [
|
||||
'(account)',
|
||||
'users/(:any)',
|
||||
],
|
||||
'method' => 'DELETE',
|
||||
'action' => function (string $id) {
|
||||
return $this->user($id)->delete();
|
||||
}
|
||||
],
|
||||
[
|
||||
'pattern' => 'users/(:any)/avatar',
|
||||
'pattern' => [
|
||||
'(account)/avatar',
|
||||
'users/(:any)/avatar',
|
||||
],
|
||||
'method' => 'GET',
|
||||
'action' => function (string $id) {
|
||||
return $this->user($id)->avatar();
|
||||
}
|
||||
],
|
||||
// @codeCoverageIgnoreStart
|
||||
[
|
||||
'pattern' => 'users/(:any)/avatar',
|
||||
'pattern' => [
|
||||
'(account)/avatar',
|
||||
'users/(:any)/avatar',
|
||||
],
|
||||
'method' => 'POST',
|
||||
'action' => function (string $id) {
|
||||
if ($avatar = $this->user($id)->avatar()) {
|
||||
|
@ -77,79 +92,101 @@ return [
|
|||
}, $single = true);
|
||||
}
|
||||
],
|
||||
// @codeCoverageIgnoreEnd
|
||||
[
|
||||
'pattern' => 'users/(:any)/avatar',
|
||||
'pattern' => [
|
||||
'(account)/avatar',
|
||||
'users/(:any)/avatar',
|
||||
],
|
||||
'method' => 'DELETE',
|
||||
'action' => function (string $id) {
|
||||
return $this->user($id)->avatar()->delete();
|
||||
}
|
||||
],
|
||||
[
|
||||
'pattern' => 'users/(:any)/blueprint',
|
||||
'pattern' => [
|
||||
'(account)/blueprint',
|
||||
'users/(:any)/blueprint',
|
||||
],
|
||||
'method' => 'GET',
|
||||
'action' => function (string $id) {
|
||||
return $this->user($id)->blueprint();
|
||||
}
|
||||
],
|
||||
[
|
||||
'pattern' => 'users/(:any)/blueprints',
|
||||
'pattern' => [
|
||||
'(account)/blueprints',
|
||||
'users/(:any)/blueprints',
|
||||
],
|
||||
'method' => 'GET',
|
||||
'action' => function (string $id) {
|
||||
return $this->user($id)->blueprints($this->requestQuery('section'));
|
||||
}
|
||||
],
|
||||
[
|
||||
'pattern' => 'users/(:any)/email',
|
||||
'pattern' => [
|
||||
'(account)/email',
|
||||
'users/(:any)/email',
|
||||
],
|
||||
'method' => 'PATCH',
|
||||
'action' => function (string $id) {
|
||||
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' => [
|
||||
'(account)/language',
|
||||
'users/(:any)/language',
|
||||
],
|
||||
'method' => 'PATCH',
|
||||
'action' => function (string $id) {
|
||||
return $this->user($id)->changeLanguage($this->requestBody('language'));
|
||||
}
|
||||
],
|
||||
[
|
||||
'pattern' => 'users/(:any)/name',
|
||||
'pattern' => [
|
||||
'(account)/name',
|
||||
'users/(:any)/name',
|
||||
],
|
||||
'method' => 'PATCH',
|
||||
'action' => function (string $id) {
|
||||
return $this->user($id)->changeName($this->requestBody('name'));
|
||||
}
|
||||
],
|
||||
[
|
||||
'pattern' => 'users/(:any)/password',
|
||||
'pattern' => [
|
||||
'(account)/password',
|
||||
'users/(:any)/password',
|
||||
],
|
||||
'method' => 'PATCH',
|
||||
'action' => function (string $id) {
|
||||
return $this->user($id)->changePassword($this->requestBody('password'));
|
||||
}
|
||||
],
|
||||
[
|
||||
'pattern' => 'users/(:any)/role',
|
||||
'pattern' => [
|
||||
'(account)/role',
|
||||
'users/(:any)/role',
|
||||
],
|
||||
'method' => 'PATCH',
|
||||
'action' => function (string $id) {
|
||||
return $this->user($id)->changeRole($this->requestBody('role'));
|
||||
}
|
||||
],
|
||||
[
|
||||
'pattern' => 'users/(:any)/roles',
|
||||
'pattern' => [
|
||||
'(account)/roles',
|
||||
'users/(:any)/roles',
|
||||
],
|
||||
'action' => function (string $id) {
|
||||
return $this->user($id)->roles();
|
||||
}
|
||||
],
|
||||
[
|
||||
'pattern' => 'users/(:any)/sections/(:any)',
|
||||
'pattern' => [
|
||||
'(account)/sections/(:any)',
|
||||
'users/(:any)/sections/(:any)',
|
||||
],
|
||||
'method' => 'GET',
|
||||
'action' => function (string $id, string $sectionName) {
|
||||
if ($section = $this->user($id)->blueprint()->section($sectionName)) {
|
||||
|
@ -157,4 +194,14 @@ return [
|
|||
}
|
||||
}
|
||||
],
|
||||
[
|
||||
'pattern' => [
|
||||
'(account)/fields/(:any)/(:all?)',
|
||||
'users/(:any)/fields/(:any)/(:all?)',
|
||||
],
|
||||
'method' => 'ALL',
|
||||
'action' => function (string $id, string $fieldName, string $path = null) {
|
||||
return $this->fieldApi($this->user($id), $fieldName, $path);
|
||||
}
|
||||
],
|
||||
];
|
||||
|
|
12
kirby/config/areas/account.php
Normal file
12
kirby/config/areas/account.php
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
return function () {
|
||||
return [
|
||||
'icon' => 'account',
|
||||
'label' => t('view.account'),
|
||||
'search' => 'users',
|
||||
'dialogs' => require __DIR__ . '/account/dialogs.php',
|
||||
'dropdowns' => require __DIR__ . '/account/dropdowns.php',
|
||||
'views' => require __DIR__ . '/account/views.php'
|
||||
];
|
||||
};
|
70
kirby/config/areas/account/dialogs.php
Normal file
70
kirby/config/areas/account/dialogs.php
Normal file
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
|
||||
$dialogs = require __DIR__ . '/../users/dialogs.php';
|
||||
|
||||
return [
|
||||
|
||||
// change email
|
||||
'account.changeEmail' => [
|
||||
'pattern' => '(account)/changeEmail',
|
||||
'load' => $dialogs['user.changeEmail']['load'],
|
||||
'submit' => $dialogs['user.changeEmail']['submit'],
|
||||
],
|
||||
|
||||
// change language
|
||||
'account.changeLanguage' => [
|
||||
'pattern' => '(account)/changeLanguage',
|
||||
'load' => $dialogs['user.changeLanguage']['load'],
|
||||
'submit' => $dialogs['user.changeLanguage']['submit'],
|
||||
],
|
||||
|
||||
// change name
|
||||
'account.changeName' => [
|
||||
'pattern' => '(account)/changeName',
|
||||
'load' => $dialogs['user.changeName']['load'],
|
||||
'submit' => $dialogs['user.changeName']['submit'],
|
||||
],
|
||||
|
||||
// change password
|
||||
'account.changePassword' => [
|
||||
'pattern' => '(account)/changePassword',
|
||||
'load' => $dialogs['user.changePassword']['load'],
|
||||
'submit' => $dialogs['user.changePassword']['submit'],
|
||||
],
|
||||
|
||||
// change role
|
||||
'account.changeRole' => [
|
||||
'pattern' => '(account)/changeRole',
|
||||
'load' => $dialogs['user.changeRole']['load'],
|
||||
'submit' => $dialogs['user.changeRole']['submit'],
|
||||
],
|
||||
|
||||
// delete
|
||||
'account.delete' => [
|
||||
'pattern' => '(account)/delete',
|
||||
'load' => $dialogs['user.delete']['load'],
|
||||
'submit' => $dialogs['user.delete']['submit'],
|
||||
],
|
||||
|
||||
// change file name
|
||||
'account.file.changeName' => [
|
||||
'pattern' => '(account)/files/(:any)/changeName',
|
||||
'load' => $dialogs['user.file.changeName']['load'],
|
||||
'submit' => $dialogs['user.file.changeName']['submit'],
|
||||
],
|
||||
|
||||
// change file sort
|
||||
'account.file.changeSort' => [
|
||||
'pattern' => '(account)/files/(:any)/changeSort',
|
||||
'load' => $dialogs['user.file.changeSort']['load'],
|
||||
'submit' => $dialogs['user.file.changeSort']['submit'],
|
||||
],
|
||||
|
||||
// delete
|
||||
'account.file.delete' => [
|
||||
'pattern' => '(account)/files/(:any)/delete',
|
||||
'load' => $dialogs['user.file.delete']['load'],
|
||||
'submit' => $dialogs['user.file.delete']['submit'],
|
||||
],
|
||||
|
||||
];
|
14
kirby/config/areas/account/dropdowns.php
Normal file
14
kirby/config/areas/account/dropdowns.php
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
$dropdowns = require __DIR__ . '/../users/dropdowns.php';
|
||||
|
||||
return [
|
||||
'account' => [
|
||||
'pattern' => '(account)',
|
||||
'options' => $dropdowns['user']['options']
|
||||
],
|
||||
'account.file' => [
|
||||
'pattern' => '(account)/files/(:any)',
|
||||
'options' => $dropdowns['user.file']['options']
|
||||
],
|
||||
];
|
40
kirby/config/areas/account/views.php
Normal file
40
kirby/config/areas/account/views.php
Normal file
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
use Kirby\Cms\Find;
|
||||
use Kirby\Panel\Panel;
|
||||
|
||||
return [
|
||||
'account' => [
|
||||
'pattern' => 'account',
|
||||
'action' => function () {
|
||||
return [
|
||||
'component' => 'k-account-view',
|
||||
'props' => kirby()->user()->panel()->props(),
|
||||
];
|
||||
},
|
||||
],
|
||||
'account.file' => [
|
||||
'pattern' => 'account/files/(:any)',
|
||||
'action' => function (string $filename) {
|
||||
return Find::file('account', $filename)->panel()->view();
|
||||
}
|
||||
],
|
||||
'account.logout' => [
|
||||
'pattern' => 'logout',
|
||||
'auth' => false,
|
||||
'action' => function () {
|
||||
if ($user = kirby()->user()) {
|
||||
$user->logout();
|
||||
}
|
||||
Panel::go('login');
|
||||
},
|
||||
],
|
||||
'account.password' => [
|
||||
'pattern' => 'reset-password',
|
||||
'action' => function () {
|
||||
return [
|
||||
'component' => 'k-reset-password-view',
|
||||
];
|
||||
}
|
||||
]
|
||||
];
|
131
kirby/config/areas/files/dialogs.php
Normal file
131
kirby/config/areas/files/dialogs.php
Normal file
|
@ -0,0 +1,131 @@
|
|||
<?php
|
||||
|
||||
use Kirby\Cms\Find;
|
||||
use Kirby\Panel\Field;
|
||||
use Kirby\Panel\Panel;
|
||||
use Kirby\Toolkit\Escape;
|
||||
|
||||
/**
|
||||
* Shared file dialogs
|
||||
* They are included in the site and
|
||||
* users area to create dialogs there.
|
||||
* The array keys are replaced by
|
||||
* the appropriate routes in the areas.
|
||||
*/
|
||||
return [
|
||||
'changeName' => [
|
||||
'load' => function (string $path, string $filename) {
|
||||
$file = Find::file($path, $filename);
|
||||
return [
|
||||
'component' => 'k-form-dialog',
|
||||
'props' => [
|
||||
'fields' => [
|
||||
'name' => [
|
||||
'label' => t('name'),
|
||||
'type' => 'slug',
|
||||
'required' => true,
|
||||
'icon' => 'title',
|
||||
'allow' => '@._-',
|
||||
'after' => '.' . $file->extension(),
|
||||
'preselect' => true
|
||||
]
|
||||
],
|
||||
'submitButton' => t('rename'),
|
||||
'value' => [
|
||||
'name' => $file->name(),
|
||||
]
|
||||
]
|
||||
];
|
||||
},
|
||||
'submit' => function (string $path, string $filename) {
|
||||
$file = Find::file($path, $filename);
|
||||
$renamed = $file->changeName(get('name'));
|
||||
$oldUrl = $file->panel()->url(true);
|
||||
$newUrl = $renamed->panel()->url(true);
|
||||
$response = [
|
||||
'event' => 'file.changeName',
|
||||
'dispatch' => [
|
||||
'content/move' => [
|
||||
$oldUrl,
|
||||
$newUrl
|
||||
]
|
||||
],
|
||||
];
|
||||
|
||||
// check for a necessary redirect after the filename has changed
|
||||
if (Panel::referrer() === $oldUrl && $oldUrl !== $newUrl) {
|
||||
$response['redirect'] = $newUrl;
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
],
|
||||
|
||||
'changeSort' => [
|
||||
'load' => function (string $path, string $filename) {
|
||||
$file = Find::file($path, $filename);
|
||||
return [
|
||||
'component' => 'k-form-dialog',
|
||||
'props' => [
|
||||
'fields' => [
|
||||
'position' => Field::filePosition($file)
|
||||
],
|
||||
'submitButton' => t('change'),
|
||||
'value' => [
|
||||
'position' => $file->sort()->isEmpty() ? $file->siblings(false)->count() + 1 : $file->sort()->toInt(),
|
||||
]
|
||||
]
|
||||
];
|
||||
},
|
||||
'submit' => function (string $path, string $filename) {
|
||||
$file = Find::file($path, $filename);
|
||||
$files = $file->siblings()->sorted();
|
||||
$ids = $files->keys();
|
||||
$newIndex = (int)(get('position')) - 1;
|
||||
$oldIndex = $files->indexOf($file);
|
||||
|
||||
array_splice($ids, $oldIndex, 1);
|
||||
array_splice($ids, $newIndex, 0, $file->id());
|
||||
|
||||
$files->changeSort($ids);
|
||||
|
||||
return [
|
||||
'event' => 'file.sort',
|
||||
];
|
||||
}
|
||||
],
|
||||
|
||||
'delete' => [
|
||||
'load' => function (string $path, string $filename) {
|
||||
$file = Find::file($path, $filename);
|
||||
return [
|
||||
'component' => 'k-remove-dialog',
|
||||
'props' => [
|
||||
'text' => tt('file.delete.confirm', [
|
||||
'filename' => Escape::html($file->filename())
|
||||
]),
|
||||
]
|
||||
];
|
||||
},
|
||||
'submit' => function (string $path, string $filename) {
|
||||
$file = Find::file($path, $filename);
|
||||
$redirect = false;
|
||||
$referrer = Panel::referrer();
|
||||
$url = $file->panel()->url(true);
|
||||
|
||||
$file->delete();
|
||||
|
||||
// redirect to the parent model URL
|
||||
// if the dialog has been opened in the file view
|
||||
if ($referrer === $url) {
|
||||
$redirect = $file->parent()->panel()->url(true);
|
||||
}
|
||||
|
||||
return [
|
||||
'event' => 'file.delete',
|
||||
'dispatch' => ['content/remove' => [$url]],
|
||||
'redirect' => $redirect
|
||||
];
|
||||
}
|
||||
],
|
||||
];
|
9
kirby/config/areas/files/dropdowns.php
Normal file
9
kirby/config/areas/files/dropdowns.php
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
|
||||
use Kirby\Cms\Find;
|
||||
|
||||
return [
|
||||
'file' => function (string $parent, string $filename) {
|
||||
return Find::file($parent, $filename)->panel()->dropdown();
|
||||
}
|
||||
];
|
41
kirby/config/areas/installation.php
Normal file
41
kirby/config/areas/installation.php
Normal file
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
use Kirby\Panel\Panel;
|
||||
|
||||
return function ($kirby) {
|
||||
return [
|
||||
'icon' => 'settings',
|
||||
'label' => t('view.installation'),
|
||||
'views' => [
|
||||
'installation' => [
|
||||
'pattern' => 'installation',
|
||||
'auth' => false,
|
||||
'action' => function () use ($kirby) {
|
||||
$system = $kirby->system();
|
||||
return [
|
||||
'component' => 'k-installation-view',
|
||||
'props' => [
|
||||
'isInstallable' => $system->isInstallable(),
|
||||
'isInstalled' => $system->isInstalled(),
|
||||
'isOk' => $system->isOk(),
|
||||
'requirements' => $system->status(),
|
||||
'translations' => $kirby->translations()->values(function ($translation) {
|
||||
return [
|
||||
'text' => $translation->name(),
|
||||
'value' => $translation->code(),
|
||||
];
|
||||
}),
|
||||
]
|
||||
];
|
||||
}
|
||||
],
|
||||
'installation.fallback' => [
|
||||
'pattern' => '(:all)',
|
||||
'auth' => false,
|
||||
'action' => function () {
|
||||
Panel::go('installation');
|
||||
}
|
||||
]
|
||||
]
|
||||
];
|
||||
};
|
11
kirby/config/areas/languages.php
Normal file
11
kirby/config/areas/languages.php
Normal file
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
|
||||
return function ($kirby) {
|
||||
return [
|
||||
'icon' => 'globe',
|
||||
'label' => t('view.languages'),
|
||||
'menu' => true,
|
||||
'dialogs' => require __DIR__ . '/languages/dialogs.php',
|
||||
'views' => require __DIR__ . '/languages/views.php'
|
||||
];
|
||||
};
|
149
kirby/config/areas/languages/dialogs.php
Normal file
149
kirby/config/areas/languages/dialogs.php
Normal file
|
@ -0,0 +1,149 @@
|
|||
<?php
|
||||
|
||||
use Kirby\Cms\Find;
|
||||
use Kirby\Panel\Field;
|
||||
use Kirby\Toolkit\A;
|
||||
use Kirby\Toolkit\Escape;
|
||||
|
||||
$languageDialogFields = [
|
||||
'name' => [
|
||||
'label' => t('language.name'),
|
||||
'type' => 'text',
|
||||
'required' => true,
|
||||
'icon' => 'title'
|
||||
],
|
||||
'code' => [
|
||||
'label' => t('language.code'),
|
||||
'type' => 'text',
|
||||
'required' => true,
|
||||
'counter' => false,
|
||||
'icon' => 'globe',
|
||||
'width' => '1/2'
|
||||
],
|
||||
'direction' => [
|
||||
'label' => t('language.direction'),
|
||||
'type' => 'select',
|
||||
'required' => true,
|
||||
'empty' => false,
|
||||
'options' => [
|
||||
['value' => 'ltr', 'text' => t('language.direction.ltr')],
|
||||
['value' => 'rtl', 'text' => t('language.direction.rtl')]
|
||||
],
|
||||
'width' => '1/2'
|
||||
],
|
||||
'locale' => [
|
||||
'label' => t('language.locale'),
|
||||
'type' => 'text',
|
||||
],
|
||||
];
|
||||
|
||||
return [
|
||||
|
||||
// create language
|
||||
'language.create' => [
|
||||
'pattern' => 'languages/create',
|
||||
'load' => function () use ($languageDialogFields) {
|
||||
return [
|
||||
'component' => 'k-language-dialog',
|
||||
'props' => [
|
||||
'fields' => $languageDialogFields,
|
||||
'submitButton' => t('language.create'),
|
||||
'value' => [
|
||||
'code' => '',
|
||||
'direction' => 'ltr',
|
||||
'locale' => '',
|
||||
'name' => '',
|
||||
]
|
||||
]
|
||||
];
|
||||
},
|
||||
'submit' => function () {
|
||||
kirby()->languages()->create([
|
||||
'code' => get('code'),
|
||||
'direction' => get('direction'),
|
||||
'locale' => get('locale'),
|
||||
'name' => get('name'),
|
||||
]);
|
||||
return [
|
||||
'event' => 'language.create'
|
||||
];
|
||||
}
|
||||
],
|
||||
|
||||
// delete language
|
||||
'language.delete' => [
|
||||
'pattern' => 'languages/(:any)/delete',
|
||||
'load' => function (string $id) {
|
||||
$language = Find::language($id);
|
||||
return [
|
||||
'component' => 'k-remove-dialog',
|
||||
'props' => [
|
||||
'text' => tt('language.delete.confirm', [
|
||||
'name' => Escape::html($language->name())
|
||||
])
|
||||
]
|
||||
];
|
||||
},
|
||||
'submit' => function (string $id) {
|
||||
Find::language($id)->delete();
|
||||
return [
|
||||
'event' => 'language.delete',
|
||||
];
|
||||
}
|
||||
],
|
||||
|
||||
// update language
|
||||
'language.update' => [
|
||||
'pattern' => 'languages/(:any)/update',
|
||||
'load' => function (string $id) use ($languageDialogFields) {
|
||||
$language = Find::language($id);
|
||||
$fields = $languageDialogFields;
|
||||
$locale = $language->locale();
|
||||
|
||||
// use the first locale key if there's only one
|
||||
if (count($locale) === 1) {
|
||||
$locale = A::first($locale);
|
||||
}
|
||||
|
||||
// the code of an existing language cannot be changed
|
||||
$fields['code']['disabled'] = true;
|
||||
|
||||
// if the locale settings is more complex than just a
|
||||
// single string, the text field won't do it anymore.
|
||||
// Changes can only be made in the language file and
|
||||
// we display a warning box instead.
|
||||
if (is_array($locale) === true) {
|
||||
$fields['locale'] = [
|
||||
'label' => $fields['locale']['label'],
|
||||
'type' => 'info',
|
||||
'text' => t('language.locale.warning')
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'component' => 'k-language-dialog',
|
||||
'props' => [
|
||||
'fields' => $fields,
|
||||
'submitButton' => t('save'),
|
||||
'value' => [
|
||||
'code' => $language->code(),
|
||||
'direction' => $language->direction(),
|
||||
'locale' => $locale,
|
||||
'name' => $language->name(),
|
||||
'rules' => $language->rules(),
|
||||
]
|
||||
]
|
||||
];
|
||||
},
|
||||
'submit' => function (string $id) {
|
||||
$language = Find::language($id)->update([
|
||||
'direction' => get('direction'),
|
||||
'locale' => get('locale'),
|
||||
'name' => get('name'),
|
||||
]);
|
||||
return [
|
||||
'event' => 'language.update'
|
||||
];
|
||||
}
|
||||
],
|
||||
];
|
26
kirby/config/areas/languages/views.php
Normal file
26
kirby/config/areas/languages/views.php
Normal file
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
use Kirby\Toolkit\Escape;
|
||||
|
||||
return [
|
||||
'languages' => [
|
||||
'pattern' => 'languages',
|
||||
'action' => function () {
|
||||
$kirby = kirby();
|
||||
|
||||
return [
|
||||
'component' => 'k-languages-view',
|
||||
'props' => [
|
||||
'languages' => $kirby->languages()->values(function ($language) {
|
||||
return [
|
||||
'default' => $language->isDefault(),
|
||||
'id' => $language->code(),
|
||||
'info' => Escape::html($language->code()),
|
||||
'text' => Escape::html($language->name()),
|
||||
];
|
||||
})
|
||||
]
|
||||
];
|
||||
}
|
||||
],
|
||||
];
|
43
kirby/config/areas/login.php
Normal file
43
kirby/config/areas/login.php
Normal file
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
use Kirby\Panel\Panel;
|
||||
|
||||
return function ($kirby) {
|
||||
return [
|
||||
'icon' => 'user',
|
||||
'label' => t('login'),
|
||||
'views' => [
|
||||
'login' => [
|
||||
'pattern' => 'login',
|
||||
'auth' => false,
|
||||
'action' => function () use ($kirby) {
|
||||
$system = $kirby->system();
|
||||
$status = $kirby->auth()->status();
|
||||
return [
|
||||
'component' => 'k-login-view',
|
||||
'props' => [
|
||||
'methods' => array_keys($system->loginMethods()),
|
||||
'pending' => [
|
||||
'email' => $status->email(),
|
||||
'challenge' => $status->challenge()
|
||||
]
|
||||
],
|
||||
];
|
||||
}
|
||||
],
|
||||
'login.fallback' => [
|
||||
'pattern' => '(:all)',
|
||||
'auth' => false,
|
||||
'action' => function ($path) use ($kirby) {
|
||||
/**
|
||||
* Store the current path in the session
|
||||
* Once the user is logged in, the path will
|
||||
* be used to redirect to that view again
|
||||
*/
|
||||
$kirby->session()->set('panel.path', $path);
|
||||
Panel::go('login');
|
||||
}
|
||||
]
|
||||
]
|
||||
];
|
||||
};
|
17
kirby/config/areas/site.php
Normal file
17
kirby/config/areas/site.php
Normal file
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
|
||||
return function ($kirby) {
|
||||
return [
|
||||
'breadcrumbLabel' => function () use ($kirby) {
|
||||
return $kirby->site()->title()->or(t('view.site'))->toString();
|
||||
},
|
||||
'icon' => 'home',
|
||||
'label' => $kirby->site()->blueprint()->title() ?? t('view.site'),
|
||||
'menu' => true,
|
||||
'dialogs' => require __DIR__ . '/site/dialogs.php',
|
||||
'dropdowns' => require __DIR__ . '/site/dropdowns.php',
|
||||
'searches' => require __DIR__ . '/site/searches.php',
|
||||
'views' => require __DIR__ . '/site/views.php',
|
||||
];
|
||||
};
|
547
kirby/config/areas/site/dialogs.php
Normal file
547
kirby/config/areas/site/dialogs.php
Normal file
|
@ -0,0 +1,547 @@
|
|||
<?php
|
||||
|
||||
use Kirby\Cms\Find;
|
||||
use Kirby\Exception\Exception;
|
||||
use Kirby\Exception\InvalidArgumentException;
|
||||
use Kirby\Exception\PermissionException;
|
||||
use Kirby\Panel\Field;
|
||||
use Kirby\Panel\Panel;
|
||||
use Kirby\Toolkit\Str;
|
||||
|
||||
$files = require __DIR__ . '/../files/dialogs.php';
|
||||
|
||||
return [
|
||||
|
||||
// change page position
|
||||
'page.changeSort' => [
|
||||
'pattern' => 'pages/(:any)/changeSort',
|
||||
'load' => function (string $id) {
|
||||
$page = Find::page($id);
|
||||
$position = null;
|
||||
|
||||
if ($page->blueprint()->num() !== 'default') {
|
||||
throw new PermissionException([
|
||||
'key' => 'page.sort.permission',
|
||||
'data' => [
|
||||
'slug' => $page->slug()
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
return [
|
||||
'component' => 'k-form-dialog',
|
||||
'props' => [
|
||||
'fields' => [
|
||||
'position' => Field::pagePosition($page),
|
||||
],
|
||||
'submitButton' => t('change'),
|
||||
'value' => [
|
||||
'position' => $page->panel()->position()
|
||||
]
|
||||
]
|
||||
];
|
||||
},
|
||||
'submit' => function (string $id) {
|
||||
Find::page($id)->changeStatus('listed', get('position'));
|
||||
return [
|
||||
'event' => 'page.sort',
|
||||
];
|
||||
}
|
||||
],
|
||||
|
||||
// change page status
|
||||
'page.changeStatus' => [
|
||||
'pattern' => 'pages/(:any)/changeStatus',
|
||||
'load' => function (string $id) {
|
||||
$page = Find::page($id);
|
||||
$blueprint = $page->blueprint();
|
||||
$status = $page->status();
|
||||
$states = [];
|
||||
$position = null;
|
||||
|
||||
foreach ($blueprint->status() as $key => $state) {
|
||||
$states[] = [
|
||||
'value' => $key,
|
||||
'text' => $state['label'],
|
||||
'info' => $state['text'],
|
||||
];
|
||||
}
|
||||
|
||||
if ($status === 'draft') {
|
||||
$errors = $page->errors();
|
||||
|
||||
// switch to the error dialog if there are
|
||||
// errors and the draft cannot be published
|
||||
if (count($errors) > 0) {
|
||||
return [
|
||||
'component' => 'k-error-dialog',
|
||||
'props' => [
|
||||
'message' => t('error.page.changeStatus.incomplete'),
|
||||
'details' => $errors,
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$fields = [
|
||||
'status' => [
|
||||
'label' => t('page.changeStatus.select'),
|
||||
'type' => 'radio',
|
||||
'required' => true,
|
||||
'options' => $states
|
||||
]
|
||||
];
|
||||
|
||||
if ($blueprint->num() === 'default') {
|
||||
$fields['position'] = Field::pagePosition($page, [
|
||||
'when' => [
|
||||
'status' => 'listed'
|
||||
]
|
||||
]);
|
||||
|
||||
$position = $page->panel()->position();
|
||||
}
|
||||
|
||||
return [
|
||||
'component' => 'k-form-dialog',
|
||||
'props' => [
|
||||
'fields' => $fields,
|
||||
'submitButton' => t('change'),
|
||||
'value' => [
|
||||
'status' => $status,
|
||||
'position' => $position
|
||||
]
|
||||
]
|
||||
];
|
||||
},
|
||||
'submit' => function (string $id) {
|
||||
Find::page($id)->changeStatus(get('status'), get('position'));
|
||||
return [
|
||||
'event' => 'page.changeStatus',
|
||||
];
|
||||
}
|
||||
],
|
||||
|
||||
// change template
|
||||
'page.changeTemplate' => [
|
||||
'pattern' => 'pages/(:any)/changeTemplate',
|
||||
'load' => function (string $id) {
|
||||
$page = Find::page($id);
|
||||
$blueprints = $page->blueprints();
|
||||
|
||||
if (count($blueprints) <= 1) {
|
||||
throw new Exception([
|
||||
'key' => 'page.changeTemplate.invalid',
|
||||
'data' => [
|
||||
'slug' => $id
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
return [
|
||||
'component' => 'k-form-dialog',
|
||||
'props' => [
|
||||
'fields' => [
|
||||
'template' => Field::template($blueprints, [
|
||||
'required' => true
|
||||
])
|
||||
],
|
||||
'submitButton' => t('change'),
|
||||
'value' => [
|
||||
'template' => $page->intendedTemplate()->name()
|
||||
]
|
||||
]
|
||||
];
|
||||
},
|
||||
'submit' => function (string $id) {
|
||||
Find::page($id)->changeTemplate(get('template'));
|
||||
return [
|
||||
'event' => 'page.changeTemplate',
|
||||
];
|
||||
}
|
||||
],
|
||||
|
||||
// change title
|
||||
'page.changeTitle' => [
|
||||
'pattern' => 'pages/(:any)/changeTitle',
|
||||
'load' => function (string $id) {
|
||||
$page = Find::page($id);
|
||||
$permissions = $page->permissions();
|
||||
$select = get('select', 'title');
|
||||
|
||||
return [
|
||||
'component' => 'k-form-dialog',
|
||||
'props' => [
|
||||
'fields' => [
|
||||
'title' => Field::title([
|
||||
'required' => true,
|
||||
'preselect' => $select === 'title',
|
||||
'disabled' => $permissions->can('changeTitle') === false
|
||||
]),
|
||||
'slug' => Field::slug([
|
||||
'required' => true,
|
||||
'preselect' => $select === 'slug',
|
||||
'path' => $page->parent() ? '/' . $page->parent()->id() . '/' : '/',
|
||||
'disabled' => $permissions->can('changeSlug') === false,
|
||||
'wizard' => [
|
||||
'text' => t('page.changeSlug.fromTitle'),
|
||||
'field' => 'title'
|
||||
]
|
||||
])
|
||||
],
|
||||
'autofocus' => false,
|
||||
'submitButton' => t('change'),
|
||||
'value' => [
|
||||
'title' => $page->title()->value(),
|
||||
'slug' => $page->slug(),
|
||||
]
|
||||
]
|
||||
];
|
||||
},
|
||||
'submit' => function (string $id) {
|
||||
$page = Find::page($id);
|
||||
$title = trim(get('title'));
|
||||
$slug = trim(get('slug'));
|
||||
|
||||
// basic input validation before we move on
|
||||
if (Str::length($title) === 0) {
|
||||
throw new InvalidArgumentException(['key' => 'page.changeTitle.empty']);
|
||||
}
|
||||
|
||||
if (Str::length($slug) === 0) {
|
||||
throw new InvalidArgumentException(['key' => 'page.slug.invalid']);
|
||||
}
|
||||
|
||||
// nothing changed
|
||||
if ($page->title()->value() === $title && $page->slug() === $slug) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// prepare the response
|
||||
$response = [
|
||||
'event' => []
|
||||
];
|
||||
|
||||
// the page title changed
|
||||
if ($page->title()->value() !== $title) {
|
||||
$page->changeTitle($title);
|
||||
$response['event'][] = 'page.changeTitle';
|
||||
}
|
||||
|
||||
// the slug changed
|
||||
if ($page->slug() !== $slug) {
|
||||
$newPage = $page->changeSlug($slug);
|
||||
$response['event'][] = 'page.changeSlug';
|
||||
$response['dispatch'] = [
|
||||
'content/move' => [
|
||||
$oldUrl = $page->panel()->url(true),
|
||||
$newUrl = $newPage->panel()->url(true)
|
||||
]
|
||||
];
|
||||
|
||||
// check for a necessary redirect after the slug has changed
|
||||
if (Panel::referrer() === $oldUrl && $oldUrl !== $newUrl) {
|
||||
$response['redirect'] = $newUrl;
|
||||
}
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
],
|
||||
|
||||
// create a new page
|
||||
'page.create' => [
|
||||
'pattern' => 'pages/create',
|
||||
'load' => function () {
|
||||
// the parent model for the new page
|
||||
$parent = get('parent', 'site');
|
||||
|
||||
// the view on which the add button is located
|
||||
// this is important to find the right section
|
||||
// and provide the correct templates for the new page
|
||||
$view = get('view', $parent);
|
||||
|
||||
// templates will be fetched depending on the
|
||||
// section settings in the blueprint
|
||||
$section = get('section');
|
||||
|
||||
// this is the parent model
|
||||
$model = Find::parent($parent);
|
||||
|
||||
// this is the view model
|
||||
// i.e. site if the add button is on
|
||||
// the dashboard
|
||||
$view = Find::parent($view);
|
||||
|
||||
// available blueprints/templates for the new page
|
||||
// are always loaded depending on the matching section
|
||||
// in the view model blueprint
|
||||
$blueprints = $view->blueprints($section);
|
||||
|
||||
// the pre-selected template
|
||||
$template = $blueprints[0]['name'] ?? $blueprints[0]['value'] ?? null;
|
||||
|
||||
$fields = [
|
||||
'parent' => Field::hidden(),
|
||||
'title' => Field::title([
|
||||
'required' => true,
|
||||
'preselect' => true
|
||||
]),
|
||||
'slug' => Field::slug([
|
||||
'required' => true,
|
||||
'sync' => 'title',
|
||||
'path' => empty($model->id()) === false ? '/' . $model->id() . '/' : '/'
|
||||
]),
|
||||
'template' => Field::hidden()
|
||||
];
|
||||
|
||||
// only show template field if > 1 templates available
|
||||
// or when in debug mode
|
||||
if (count($blueprints) > 1 || option('debug') === true) {
|
||||
$fields['template'] = Field::template($blueprints, [
|
||||
'required' => true
|
||||
]);
|
||||
}
|
||||
|
||||
return [
|
||||
'component' => 'k-form-dialog',
|
||||
'props' => [
|
||||
'fields' => $fields,
|
||||
'submitButton' => t('page.draft.create'),
|
||||
'value' => [
|
||||
'parent' => $parent,
|
||||
'slug' => '',
|
||||
'template' => $template,
|
||||
'title' => '',
|
||||
]
|
||||
]
|
||||
];
|
||||
},
|
||||
'submit' => function () {
|
||||
$title = trim(get('title'));
|
||||
|
||||
if (Str::length($title) === 0) {
|
||||
throw new InvalidArgumentException([
|
||||
'key' => 'page.changeTitle.empty'
|
||||
]);
|
||||
}
|
||||
|
||||
$page = Find::parent(get('parent', 'site'))->createChild([
|
||||
'content' => ['title' => $title],
|
||||
'slug' => get('slug'),
|
||||
'template' => get('template'),
|
||||
]);
|
||||
|
||||
return [
|
||||
'event' => 'page.create',
|
||||
'redirect' => $page->panel()->url(true)
|
||||
];
|
||||
}
|
||||
],
|
||||
|
||||
// delete page
|
||||
'page.delete' => [
|
||||
'pattern' => 'pages/(:any)/delete',
|
||||
'load' => function (string $id) {
|
||||
$page = Find::page($id);
|
||||
$text = tt('page.delete.confirm', [
|
||||
'title' => Escape::html($page->title()->value())
|
||||
]);
|
||||
|
||||
if ($page->childrenAndDrafts()->count() > 0) {
|
||||
return [
|
||||
'component' => 'k-form-dialog',
|
||||
'props' => [
|
||||
'fields' => [
|
||||
'info' => [
|
||||
'type' => 'info',
|
||||
'theme' => 'negative',
|
||||
'text' => t('page.delete.confirm.subpages')
|
||||
],
|
||||
'check' => [
|
||||
'label' => t('page.delete.confirm.title'),
|
||||
'type' => 'text',
|
||||
'counter' => false
|
||||
]
|
||||
],
|
||||
'size' => 'medium',
|
||||
'submitButton' => t('delete'),
|
||||
'text' => $text,
|
||||
'theme' => 'negative',
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'component' => 'k-remove-dialog',
|
||||
'props' => [
|
||||
'text' => $text
|
||||
]
|
||||
];
|
||||
},
|
||||
'submit' => function (string $id) {
|
||||
$page = Find::page($id);
|
||||
$redirect = false;
|
||||
$referrer = Panel::referrer();
|
||||
$url = $page->panel()->url(true);
|
||||
|
||||
if ($page->childrenAndDrafts()->count() > 0 && get('check') !== $page->title()->value()) {
|
||||
throw new InvalidArgumentException(['key' => 'page.delete.confirm']);
|
||||
}
|
||||
|
||||
$page->delete(true);
|
||||
|
||||
// redirect to the parent model URL
|
||||
// if the dialog has been opened in the page view
|
||||
if ($referrer === $url) {
|
||||
$redirect = $page->parentModel()->panel()->url(true);
|
||||
}
|
||||
|
||||
return [
|
||||
'event' => 'page.delete',
|
||||
'dispatch' => ['content/remove' => [$url]],
|
||||
'redirect' => $redirect
|
||||
];
|
||||
}
|
||||
],
|
||||
|
||||
// duplicate page
|
||||
'page.duplicate' => [
|
||||
'pattern' => 'pages/(:any)/duplicate',
|
||||
'load' => function (string $id) {
|
||||
$page = Find::page($id);
|
||||
$hasChildren = $page->hasChildren();
|
||||
$hasFiles = $page->hasFiles();
|
||||
$toggleWidth = '1/' . count(array_filter([$hasChildren, $hasFiles]));
|
||||
|
||||
$fields = [
|
||||
'title' => Field::title([
|
||||
'required' => true
|
||||
]),
|
||||
'slug' => Field::slug([
|
||||
'required' => true,
|
||||
'path' => $page->parent() ? '/' . $page->parent()->id() . '/' : '/',
|
||||
'wizard' => [
|
||||
'text' => t('page.changeSlug.fromTitle'),
|
||||
'field' => 'title'
|
||||
]
|
||||
])
|
||||
];
|
||||
|
||||
if ($hasFiles === true) {
|
||||
$fields['files'] = [
|
||||
'label' => t('page.duplicate.files'),
|
||||
'type' => 'toggle',
|
||||
'required' => true,
|
||||
'width' => $toggleWidth
|
||||
];
|
||||
}
|
||||
|
||||
if ($hasChildren === true) {
|
||||
$fields['children'] = [
|
||||
'label' => t('page.duplicate.pages'),
|
||||
'type' => 'toggle',
|
||||
'required' => true,
|
||||
'width' => $toggleWidth
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'component' => 'k-form-dialog',
|
||||
'props' => [
|
||||
'fields' => $fields,
|
||||
'submitButton' => t('duplicate'),
|
||||
'value' => [
|
||||
'children' => false,
|
||||
'files' => false,
|
||||
'slug' => $page->slug() . '-' . Str::slug(t('page.duplicate.appendix')),
|
||||
'title' => $page->title() . ' ' . t('page.duplicate.appendix')
|
||||
]
|
||||
]
|
||||
];
|
||||
},
|
||||
'submit' => function (string $id) {
|
||||
$newPage = Find::page($id)->duplicate(get('slug'), [
|
||||
'children' => (bool)get('children'),
|
||||
'files' => (bool)get('files'),
|
||||
'title' => (string)get('title'),
|
||||
]);
|
||||
|
||||
return [
|
||||
'event' => 'page.duplicate',
|
||||
'redirect' => $newPage->panel()->url(true)
|
||||
];
|
||||
}
|
||||
],
|
||||
|
||||
// change filename
|
||||
'page.file.changeName' => [
|
||||
'pattern' => '(pages/.*?)/files/(:any)/changeName',
|
||||
'load' => $files['changeName']['load'],
|
||||
'submit' => $files['changeName']['submit'],
|
||||
],
|
||||
|
||||
// change sort
|
||||
'page.file.changeSort' => [
|
||||
'pattern' => '(pages/.*?)/files/(:any)/changeSort',
|
||||
'load' => $files['changeSort']['load'],
|
||||
'submit' => $files['changeSort']['submit'],
|
||||
],
|
||||
|
||||
// delete
|
||||
'page.file.delete' => [
|
||||
'pattern' => '(pages/.*?)/files/(:any)/delete',
|
||||
'load' => $files['delete']['load'],
|
||||
'submit' => $files['delete']['submit'],
|
||||
],
|
||||
|
||||
// change site title
|
||||
'site.changeTitle' => [
|
||||
'pattern' => 'site/changeTitle',
|
||||
'load' => function () {
|
||||
return [
|
||||
'component' => 'k-form-dialog',
|
||||
'props' => [
|
||||
'fields' => [
|
||||
'title' => Field::title([
|
||||
'required' => true,
|
||||
'preselect' => true
|
||||
])
|
||||
],
|
||||
'submitButton' => t('rename'),
|
||||
'value' => [
|
||||
'title' => site()->title()->value()
|
||||
]
|
||||
]
|
||||
];
|
||||
},
|
||||
'submit' => function () {
|
||||
site()->changeTitle(get('title'));
|
||||
return [
|
||||
'event' => 'site.changeTitle',
|
||||
];
|
||||
}
|
||||
],
|
||||
|
||||
// change filename
|
||||
'site.file.changeName' => [
|
||||
'pattern' => '(site)/files/(:any)/changeName',
|
||||
'load' => $files['changeName']['load'],
|
||||
'submit' => $files['changeName']['submit'],
|
||||
],
|
||||
|
||||
// change sort
|
||||
'site.file.changeSort' => [
|
||||
'pattern' => '(site)/files/(:any)/changeSort',
|
||||
'load' => $files['changeSort']['load'],
|
||||
'submit' => $files['changeSort']['submit'],
|
||||
],
|
||||
|
||||
// delete
|
||||
'site.file.delete' => [
|
||||
'pattern' => '(site)/files/(:any)/delete',
|
||||
'load' => $files['delete']['load'],
|
||||
'submit' => $files['delete']['submit'],
|
||||
],
|
||||
|
||||
];
|
28
kirby/config/areas/site/dropdowns.php
Normal file
28
kirby/config/areas/site/dropdowns.php
Normal file
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
use Kirby\Panel\Dropdown;
|
||||
|
||||
$files = require __DIR__ . '/../files/dropdowns.php';
|
||||
|
||||
return [
|
||||
'changes' => [
|
||||
'pattern' => 'changes',
|
||||
'options' => function () {
|
||||
return Dropdown::changes();
|
||||
}
|
||||
],
|
||||
'page' => [
|
||||
'pattern' => 'pages/(:any)',
|
||||
'options' => function (string $path) {
|
||||
return Find::page($path)->panel()->dropdown();
|
||||
}
|
||||
],
|
||||
'page.file' => [
|
||||
'pattern' => '(pages/.*?)/files/(:any)',
|
||||
'options' => $files['file']
|
||||
],
|
||||
'site.file' => [
|
||||
'pattern' => '(site)/files/(:any)',
|
||||
'options' => $files['file']
|
||||
]
|
||||
];
|
55
kirby/config/areas/site/searches.php
Normal file
55
kirby/config/areas/site/searches.php
Normal file
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
|
||||
use Kirby\Toolkit\Escape;
|
||||
|
||||
return [
|
||||
'pages' => [
|
||||
'label' => t('pages'),
|
||||
'icon' => 'page',
|
||||
'query' => function (string $query = null) {
|
||||
$pages = site()
|
||||
->index(true)
|
||||
->search($query)
|
||||
->filter('isReadable', true)
|
||||
->limit(10);
|
||||
|
||||
$results = [];
|
||||
|
||||
foreach ($pages as $page) {
|
||||
$results[] = [
|
||||
'image' => $page->panel()->image(),
|
||||
'text' => Escape::html($page->title()->value()),
|
||||
'link' => $page->panel()->url(true),
|
||||
'info' => Escape::html($page->id())
|
||||
];
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
],
|
||||
'files' => [
|
||||
'label' => t('files'),
|
||||
'icon' => 'image',
|
||||
'query' => function (string $query = null) {
|
||||
$files = site()
|
||||
->index(true)
|
||||
->filter('isReadable', true)
|
||||
->files()
|
||||
->search($query)
|
||||
->limit(10);
|
||||
|
||||
$results = [];
|
||||
|
||||
foreach ($files as $file) {
|
||||
$results[] = [
|
||||
'image' => $file->panel()->image(),
|
||||
'text' => Escape::html($file->filename()),
|
||||
'link' => $file->panel()->url(true),
|
||||
'info' => Escape::html($file->id())
|
||||
];
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
]
|
||||
];
|
30
kirby/config/areas/site/views.php
Normal file
30
kirby/config/areas/site/views.php
Normal file
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
use Kirby\Cms\Find;
|
||||
|
||||
return [
|
||||
'page' => [
|
||||
'pattern' => 'pages/(:any)',
|
||||
'action' => function (string $path) {
|
||||
return Find::page($path)->panel()->view();
|
||||
}
|
||||
],
|
||||
'page.file' => [
|
||||
'pattern' => 'pages/(:any)/files/(:any)',
|
||||
'action' => function (string $id, string $filename) {
|
||||
return Find::file('pages/' . $id, $filename)->panel()->view();
|
||||
}
|
||||
],
|
||||
'site' => [
|
||||
'pattern' => 'site',
|
||||
'action' => function () {
|
||||
return site()->panel()->view();
|
||||
}
|
||||
],
|
||||
'site.file' => [
|
||||
'pattern' => 'site/files/(:any)',
|
||||
'action' => function (string $filename) {
|
||||
return Find::file('site', $filename)->panel()->view();
|
||||
}
|
||||
],
|
||||
];
|
11
kirby/config/areas/system.php
Normal file
11
kirby/config/areas/system.php
Normal file
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
|
||||
return function ($kirby) {
|
||||
return [
|
||||
'icon' => 'settings',
|
||||
'label' => t('view.system'),
|
||||
'menu' => true,
|
||||
'dialogs' => require __DIR__ . '/system/dialogs.php',
|
||||
'views' => require __DIR__ . '/system/views.php'
|
||||
];
|
||||
};
|
43
kirby/config/areas/system/dialogs.php
Normal file
43
kirby/config/areas/system/dialogs.php
Normal file
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
use Kirby\Panel\Field;
|
||||
|
||||
return [
|
||||
// license registration
|
||||
'registration' => [
|
||||
'load' => function () {
|
||||
return [
|
||||
'component' => 'k-form-dialog',
|
||||
'props' => [
|
||||
'fields' => [
|
||||
'license' => [
|
||||
'label' => t('license.register.label'),
|
||||
'type' => 'text',
|
||||
'required' => true,
|
||||
'counter' => false,
|
||||
'placeholder' => 'K3-',
|
||||
'help' => t('license.register.help')
|
||||
],
|
||||
'email' => Field::email([
|
||||
'required' => true
|
||||
])
|
||||
],
|
||||
'submitButton' => t('license.register'),
|
||||
'value' => [
|
||||
'license' => null,
|
||||
'email' => null
|
||||
]
|
||||
]
|
||||
];
|
||||
},
|
||||
'submit' => function () {
|
||||
// @codeCoverageIgnoreStart
|
||||
kirby()->system()->register(get('license'), get('email'));
|
||||
return [
|
||||
'event' => 'system.register',
|
||||
'message' => t('license.register.success')
|
||||
];
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
],
|
||||
];
|
46
kirby/config/areas/system/views.php
Normal file
46
kirby/config/areas/system/views.php
Normal file
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
|
||||
return [
|
||||
'system' => [
|
||||
'pattern' => 'system',
|
||||
'action' => function () {
|
||||
$kirby = kirby();
|
||||
$system = $kirby->system();
|
||||
$license = $system->license();
|
||||
|
||||
// @codeCoverageIgnoreStart
|
||||
if ($license === true) {
|
||||
// valid license, but user is not admin
|
||||
$license = 'Kirby 3';
|
||||
} elseif ($license === false) {
|
||||
// no valid license
|
||||
$license = null;
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
$plugins = $system->plugins()->values(function ($plugin) {
|
||||
return [
|
||||
'author' => $plugin->authorsNames(),
|
||||
'license' => $plugin->license(),
|
||||
'link' => $plugin->link(),
|
||||
'name' => $plugin->name(),
|
||||
'version' => $plugin->version(),
|
||||
];
|
||||
});
|
||||
|
||||
return [
|
||||
'component' => 'k-system-view',
|
||||
'props' => [
|
||||
'debug' => $kirby->option('debug', false),
|
||||
'license' => $license,
|
||||
'plugins' => $plugins,
|
||||
'php' => phpversion(),
|
||||
'server' => $system->serverSoftware(),
|
||||
'ssl' => Server::https(),
|
||||
'version' => $kirby->version(),
|
||||
]
|
||||
];
|
||||
}
|
||||
],
|
||||
];
|
14
kirby/config/areas/users.php
Normal file
14
kirby/config/areas/users.php
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
return function ($kirby) {
|
||||
return [
|
||||
'icon' => 'users',
|
||||
'label' => t('view.users'),
|
||||
'search' => 'users',
|
||||
'menu' => true,
|
||||
'dialogs' => require __DIR__ . '/users/dialogs.php',
|
||||
'dropdowns' => require __DIR__ . '/users/dropdowns.php',
|
||||
'searches' => require __DIR__ . '/users/searches.php',
|
||||
'views' => require __DIR__ . '/users/views.php'
|
||||
];
|
||||
};
|
295
kirby/config/areas/users/dialogs.php
Normal file
295
kirby/config/areas/users/dialogs.php
Normal file
|
@ -0,0 +1,295 @@
|
|||
<?php
|
||||
|
||||
use Kirby\Cms\Find;
|
||||
use Kirby\Cms\UserRules;
|
||||
use Kirby\Exception\InvalidArgumentException;
|
||||
use Kirby\Panel\Field;
|
||||
use Kirby\Panel\Panel;
|
||||
use Kirby\Toolkit\Escape;
|
||||
|
||||
$files = require __DIR__ . '/../files/dialogs.php';
|
||||
|
||||
return [
|
||||
|
||||
// create
|
||||
'user.create' => [
|
||||
'pattern' => 'users/create',
|
||||
'load' => function () {
|
||||
$kirby = kirby();
|
||||
return [
|
||||
'component' => 'k-form-dialog',
|
||||
'props' => [
|
||||
'fields' => [
|
||||
'name' => Field::username(),
|
||||
'email' => Field::email([
|
||||
'link' => false,
|
||||
'required' => true
|
||||
]),
|
||||
'password' => Field::password(),
|
||||
'language' => Field::translation([
|
||||
'required' => true
|
||||
]),
|
||||
'role' => Field::role([
|
||||
'required' => true
|
||||
])
|
||||
],
|
||||
'submitButton' => t('create'),
|
||||
'value' => [
|
||||
'name' => '',
|
||||
'email' => '',
|
||||
'password' => '',
|
||||
'language' => $kirby->panelLanguage(),
|
||||
'role' => $kirby->user()->role()->name()
|
||||
]
|
||||
]
|
||||
];
|
||||
},
|
||||
'submit' => function () {
|
||||
kirby()->users()->create([
|
||||
'name' => get('name'),
|
||||
'email' => get('email'),
|
||||
'password' => get('password'),
|
||||
'language' => get('language'),
|
||||
'role' => get('role')
|
||||
]);
|
||||
return [
|
||||
'event' => 'user.create'
|
||||
];
|
||||
}
|
||||
],
|
||||
|
||||
// change email
|
||||
'user.changeEmail' => [
|
||||
'pattern' => 'users/(:any)/changeEmail',
|
||||
'load' => function (string $id) {
|
||||
$user = Find::user($id);
|
||||
|
||||
return [
|
||||
'component' => 'k-form-dialog',
|
||||
'props' => [
|
||||
'fields' => [
|
||||
'email' => [
|
||||
'label' => t('email'),
|
||||
'required' => true,
|
||||
'type' => 'email',
|
||||
'preselect' => true
|
||||
]
|
||||
],
|
||||
'submitButton' => t('change'),
|
||||
'value' => [
|
||||
'email' => $user->email()
|
||||
]
|
||||
]
|
||||
];
|
||||
},
|
||||
'submit' => function (string $id) {
|
||||
Find::user($id)->changeEmail(get('email'));
|
||||
return [
|
||||
'event' => 'user.changeEmail'
|
||||
];
|
||||
}
|
||||
],
|
||||
|
||||
// change language
|
||||
'user.changeLanguage' => [
|
||||
'pattern' => 'users/(:any)/changeLanguage',
|
||||
'load' => function (string $id) {
|
||||
$user = Find::user($id);
|
||||
|
||||
return [
|
||||
'component' => 'k-form-dialog',
|
||||
'props' => [
|
||||
'fields' => [
|
||||
'translation' => Field::translation(['required' => true])
|
||||
],
|
||||
'submitButton' => t('change'),
|
||||
'value' => [
|
||||
'translation' => $user->language()
|
||||
]
|
||||
]
|
||||
];
|
||||
},
|
||||
'submit' => function (string $id) {
|
||||
Find::user($id)->changeLanguage(get('translation'));
|
||||
|
||||
return [
|
||||
'event' => 'user.changeLanguage',
|
||||
'reload' => [
|
||||
'globals' => '$translation'
|
||||
]
|
||||
];
|
||||
}
|
||||
],
|
||||
|
||||
// change name
|
||||
'user.changeName' => [
|
||||
'pattern' => 'users/(:any)/changeName',
|
||||
'load' => function (string $id) {
|
||||
$user = Find::user($id);
|
||||
|
||||
return [
|
||||
'component' => 'k-form-dialog',
|
||||
'props' => [
|
||||
'fields' => [
|
||||
'name' => Field::username([
|
||||
'preselect' => true
|
||||
])
|
||||
],
|
||||
'submitButton' => t('rename'),
|
||||
'value' => [
|
||||
'name' => $user->name()->value()
|
||||
]
|
||||
]
|
||||
];
|
||||
},
|
||||
'submit' => function (string $id) {
|
||||
Find::user($id)->changeName(get('name'));
|
||||
|
||||
return [
|
||||
'event' => 'user.changeName'
|
||||
];
|
||||
}
|
||||
],
|
||||
|
||||
// change password
|
||||
'user.changePassword' => [
|
||||
'pattern' => 'users/(:any)/changePassword',
|
||||
'load' => function (string $id) {
|
||||
$user = Find::user($id);
|
||||
|
||||
return [
|
||||
'component' => 'k-form-dialog',
|
||||
'props' => [
|
||||
'fields' => [
|
||||
'password' => Field::password([
|
||||
'label' => t('user.changePassword.new'),
|
||||
]),
|
||||
'passwordConfirmation' => Field::password([
|
||||
'label' => t('user.changePassword.new.confirm'),
|
||||
])
|
||||
],
|
||||
'submitButton' => t('change'),
|
||||
]
|
||||
];
|
||||
},
|
||||
'submit' => function (string $id) {
|
||||
$user = Find::user($id);
|
||||
$password = get('password');
|
||||
$passwordConfirmation = get('passwordConfirmation');
|
||||
|
||||
// validate the password
|
||||
UserRules::validPassword($user, $password ?? '');
|
||||
|
||||
// compare passwords
|
||||
if ($password !== $passwordConfirmation) {
|
||||
throw new InvalidArgumentException([
|
||||
'key' => 'user.password.notSame'
|
||||
]);
|
||||
}
|
||||
|
||||
// change password if everything's fine
|
||||
$user->changePassword($password);
|
||||
|
||||
return [
|
||||
'event' => 'user.changePassword'
|
||||
];
|
||||
}
|
||||
],
|
||||
|
||||
// change role
|
||||
'user.changeRole' => [
|
||||
'pattern' => 'users/(:any)/changeRole',
|
||||
'load' => function (string $id) {
|
||||
$user = Find::user($id);
|
||||
|
||||
return [
|
||||
'component' => 'k-form-dialog',
|
||||
'props' => [
|
||||
'fields' => [
|
||||
'role' => Field::role([
|
||||
'label' => t('user.changeRole.select'),
|
||||
'required' => true,
|
||||
])
|
||||
],
|
||||
'submitButton' => t('user.changeRole'),
|
||||
'value' => [
|
||||
'role' => $user->role()->name()
|
||||
]
|
||||
]
|
||||
];
|
||||
},
|
||||
'submit' => function (string $id) {
|
||||
$user = Find::user($id)->changeRole(get('role'));
|
||||
|
||||
return [
|
||||
'event' => 'user.changeRole',
|
||||
'user' => $user->toArray()
|
||||
];
|
||||
}
|
||||
],
|
||||
|
||||
// delete
|
||||
'user.delete' => [
|
||||
'pattern' => 'users/(:any)/delete',
|
||||
'load' => function (string $id) {
|
||||
$user = Find::user($id);
|
||||
$i18nPrefix = $user->isLoggedIn() ? 'account' : 'user';
|
||||
|
||||
return [
|
||||
'component' => 'k-remove-dialog',
|
||||
'props' => [
|
||||
'text' => tt($i18nPrefix . '.delete.confirm', [
|
||||
'email' => Escape::html($user->email())
|
||||
])
|
||||
]
|
||||
];
|
||||
},
|
||||
'submit' => function (string $id) {
|
||||
$user = Find::user($id);
|
||||
$redirect = false;
|
||||
$referrer = Panel::referrer();
|
||||
$url = $user->panel()->url(true);
|
||||
|
||||
$user->delete();
|
||||
|
||||
// redirect to the users view
|
||||
// if the dialog has been opened in the user view
|
||||
if ($referrer === $url) {
|
||||
$redirect = '/users';
|
||||
}
|
||||
|
||||
// logout the user if they deleted themselves
|
||||
if ($user->isLoggedIn()) {
|
||||
$redirect = '/logout';
|
||||
}
|
||||
|
||||
return [
|
||||
'event' => 'user.delete',
|
||||
'dispatch' => ['content/remove' => [$url]],
|
||||
'redirect' => $redirect
|
||||
];
|
||||
}
|
||||
],
|
||||
|
||||
// change file name
|
||||
'user.file.changeName' => [
|
||||
'pattern' => '(users/.*?)/files/(:any)/changeName',
|
||||
'load' => $files['changeName']['load'],
|
||||
'submit' => $files['changeName']['submit'],
|
||||
],
|
||||
|
||||
// change file sort
|
||||
'user.file.changeSort' => [
|
||||
'pattern' => '(users/.*?)/files/(:any)/changeSort',
|
||||
'load' => $files['changeSort']['load'],
|
||||
'submit' => $files['changeSort']['submit'],
|
||||
],
|
||||
|
||||
// delete file
|
||||
'user.file.delete' => [
|
||||
'pattern' => '(users/.*?)/files/(:any)/delete',
|
||||
'load' => $files['delete']['load'],
|
||||
'submit' => $files['delete']['submit'],
|
||||
]
|
||||
|
||||
];
|
18
kirby/config/areas/users/dropdowns.php
Normal file
18
kirby/config/areas/users/dropdowns.php
Normal file
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
use Kirby\Cms\Find;
|
||||
|
||||
$files = require __DIR__ . '/../files/dropdowns.php';
|
||||
|
||||
return [
|
||||
'user' => [
|
||||
'pattern' => 'users/(:any)',
|
||||
'options' => function (string $id) {
|
||||
return Find::user($id)->panel()->dropdown();
|
||||
}
|
||||
],
|
||||
'user.file' => [
|
||||
'pattern' => '(users/.*?)/files/(:any)',
|
||||
'options' => $files['file']
|
||||
]
|
||||
];
|
25
kirby/config/areas/users/searches.php
Normal file
25
kirby/config/areas/users/searches.php
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
use Kirby\Toolkit\Escape;
|
||||
|
||||
return [
|
||||
'users' => [
|
||||
'label' => t('users'),
|
||||
'icon' => 'users',
|
||||
'query' => function (string $query = null) {
|
||||
$users = kirby()->users()->search($query)->limit(10);
|
||||
$results = [];
|
||||
|
||||
foreach ($users as $user) {
|
||||
$results[] = [
|
||||
'image' => $user->panel()->image(),
|
||||
'text' => Escape::html($user->username()),
|
||||
'link' => $user->panel()->url(true),
|
||||
'info' => Escape::html($user->role()->title())
|
||||
];
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
]
|
||||
];
|
69
kirby/config/areas/users/views.php
Normal file
69
kirby/config/areas/users/views.php
Normal file
|
@ -0,0 +1,69 @@
|
|||
<?php
|
||||
|
||||
use Kirby\Cms\Find;
|
||||
use Kirby\Toolkit\Escape;
|
||||
|
||||
return [
|
||||
'users' => [
|
||||
'pattern' => 'users',
|
||||
'action' => function () {
|
||||
$kirby = kirby();
|
||||
$role = get('role');
|
||||
$roles = $kirby->roles()->toArray(function ($role) {
|
||||
return [
|
||||
'id' => $role->id(),
|
||||
'title' => $role->title(),
|
||||
];
|
||||
});
|
||||
|
||||
return [
|
||||
'component' => 'k-users-view',
|
||||
'props' => [
|
||||
'role' => function () use ($kirby, $roles, $role) {
|
||||
if ($role) {
|
||||
return $roles[$role] ?? null;
|
||||
}
|
||||
},
|
||||
'roles' => array_values($roles),
|
||||
'users' => function () use ($kirby, $role) {
|
||||
$users = $kirby->users();
|
||||
|
||||
if (empty($role) === false) {
|
||||
$users = $users->role($role);
|
||||
}
|
||||
|
||||
$users = $users->paginate([
|
||||
'limit' => 20,
|
||||
'page' => get('page')
|
||||
]);
|
||||
|
||||
return [
|
||||
'data' => $users->values(function ($user) {
|
||||
return [
|
||||
'id' => $user->id(),
|
||||
'image' => $user->panel()->image(),
|
||||
'info' => Escape::html($user->role()->title()),
|
||||
'link' => $user->panel()->url(true),
|
||||
'text' => Escape::html($user->username())
|
||||
];
|
||||
}),
|
||||
'pagination' => $users->pagination()->toArray()
|
||||
];
|
||||
},
|
||||
]
|
||||
];
|
||||
}
|
||||
],
|
||||
'user' => [
|
||||
'pattern' => 'users/(:any)',
|
||||
'action' => function (string $id) {
|
||||
return Find::user($id)->panel()->view();
|
||||
}
|
||||
],
|
||||
'user.file' => [
|
||||
'pattern' => 'users/(:any)/files/(:any)',
|
||||
'action' => function (string $id, string $filename) {
|
||||
return Find::file('users/' . $id, $filename)->panel()->view();
|
||||
}
|
||||
],
|
||||
];
|
|
@ -9,7 +9,7 @@ $ratio = $block->ratio()->or('auto');
|
|||
$src = null;
|
||||
|
||||
if ($block->location() == 'web') {
|
||||
$src = $block->src();
|
||||
$src = $block->src()->esc();
|
||||
} elseif ($image = $block->image()->toFile()) {
|
||||
$alt = $alt ?? $image->alt();
|
||||
$src = $image->url();
|
||||
|
@ -19,11 +19,11 @@ if ($block->location() == 'web') {
|
|||
<?php if ($src): ?>
|
||||
<figure<?= attr(['data-ratio' => $ratio, 'data-crop' => $crop], ' ') ?>>
|
||||
<?php if ($link->isNotEmpty()): ?>
|
||||
<a href="<?= $link->toUrl() ?>">
|
||||
<img src="<?= $src ?>" alt="<?= $alt ?>">
|
||||
<a href="<?= esc($link->toUrl()) ?>">
|
||||
<img src="<?= $src ?>" alt="<?= $alt->esc() ?>">
|
||||
</a>
|
||||
<?php else: ?>
|
||||
<img src="<?= $src ?>" alt="<?= $alt ?>">
|
||||
<img src="<?= $src ?>" alt="<?= $alt->esc() ?>">
|
||||
<?php endif ?>
|
||||
|
||||
<?php if ($caption->isNotEmpty()): ?>
|
||||
|
|
1
kirby/config/blocks/line/line.php
Normal file
1
kirby/config/blocks/line/line.php
Normal file
|
@ -0,0 +1 @@
|
|||
<hr />
|
4
kirby/config/blocks/line/line.yml
Normal file
4
kirby/config/blocks/line/line.yml
Normal file
|
@ -0,0 +1,4 @@
|
|||
name: field.blocks.line.name
|
||||
icon: divider
|
||||
preview: line
|
||||
wysiwyg: true
|
|
@ -1,7 +1,7 @@
|
|||
<?php /** @var \Kirby\Cms\Block $block */ ?>
|
||||
<?php if ($block->url()->isNotEmpty()): ?>
|
||||
<?php if ($video = video($block->url())): ?>
|
||||
<figure>
|
||||
<?= video($block->url()) ?>
|
||||
<?= $video ?>
|
||||
<?php if ($block->caption()->isNotEmpty()): ?>
|
||||
<figcaption><?= $block->caption() ?></figcaption>
|
||||
<?php endif ?>
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
<?php
|
||||
|
||||
$blocksRoot = __DIR__ . '/blocks';
|
||||
|
||||
return [
|
||||
// blocks
|
||||
'blocks/code' => $blocksRoot . '/code/code.yml',
|
||||
'blocks/gallery' => $blocksRoot . '/gallery/gallery.yml',
|
||||
'blocks/heading' => $blocksRoot . '/heading/heading.yml',
|
||||
'blocks/image' => $blocksRoot . '/image/image.yml',
|
||||
'blocks/list' => $blocksRoot . '/list/list.yml',
|
||||
'blocks/markdown' => $blocksRoot . '/markdown/markdown.yml',
|
||||
'blocks/quote' => $blocksRoot . '/quote/quote.yml',
|
||||
'blocks/table' => $blocksRoot . '/table/table.yml',
|
||||
'blocks/text' => $blocksRoot . '/text/text.yml',
|
||||
'blocks/video' => $blocksRoot . '/video/video.yml',
|
||||
|
||||
// file blueprints
|
||||
'files/default' => __DIR__ . '/blueprints/files/default.yml',
|
||||
|
||||
// page blueprints
|
||||
'pages/default' => __DIR__ . '/blueprints/pages/default.yml',
|
||||
|
||||
// site blueprints
|
||||
'site' => __DIR__ . '/blueprints/site.yml'
|
||||
];
|
|
@ -5,7 +5,6 @@ fields:
|
|||
level:
|
||||
type: select
|
||||
width: 1/2
|
||||
default: 1
|
||||
empty: false
|
||||
default: "2"
|
||||
options:
|
||||
|
|
|
@ -3,10 +3,12 @@
|
|||
use Kirby\Cms\App;
|
||||
use Kirby\Cms\Collection;
|
||||
use Kirby\Cms\File;
|
||||
use Kirby\Cms\Filename;
|
||||
use Kirby\Cms\FileVersion;
|
||||
use Kirby\Cms\Template;
|
||||
use Kirby\Data\Data;
|
||||
use Kirby\Email\PHPMailer as Emailer;
|
||||
use Kirby\Filesystem\F;
|
||||
use Kirby\Filesystem\Filename;
|
||||
use Kirby\Http\Server;
|
||||
use Kirby\Http\Uri;
|
||||
use Kirby\Http\Url;
|
||||
|
@ -14,7 +16,6 @@ use Kirby\Image\Darkroom;
|
|||
use Kirby\Text\Markdown;
|
||||
use Kirby\Text\SmartyPants;
|
||||
use Kirby\Toolkit\A;
|
||||
use Kirby\Toolkit\F;
|
||||
use Kirby\Toolkit\Str;
|
||||
use Kirby\Toolkit\Tpl as Snippet;
|
||||
|
||||
|
@ -55,6 +56,17 @@ return [
|
|||
return $output;
|
||||
},
|
||||
|
||||
/**
|
||||
* Add your own email provider
|
||||
*
|
||||
* @param \Kirby\Cms\App $kirby Kirby instance
|
||||
* @param array $props
|
||||
* @param bool $debug
|
||||
*/
|
||||
'email' => function (App $kirby, array $props = [], bool $debug = false) {
|
||||
return new Emailer($props, $debug);
|
||||
},
|
||||
|
||||
/**
|
||||
* Modify URLs for file objects
|
||||
*
|
||||
|
@ -70,7 +82,7 @@ return [
|
|||
* Adapt file characteristics
|
||||
*
|
||||
* @param \Kirby\Cms\App $kirby Kirby instance
|
||||
* @param \Kirby\Cms\File|\Kirby\Cms\FileModifications $file The file object
|
||||
* @param \Kirby\Cms\File|\Kirby\Filesystem\Asset $file The file object
|
||||
* @param array $options All thumb options (width, height, crop, blur, grayscale)
|
||||
* @return \Kirby\Cms\File|\Kirby\Cms\FileVersion
|
||||
*/
|
||||
|
@ -233,7 +245,7 @@ return [
|
|||
}
|
||||
}
|
||||
|
||||
return $item->searchHits > 0 ? true : false;
|
||||
return $item->searchHits > 0;
|
||||
});
|
||||
|
||||
return $results->sort('searchScore', 'desc');
|
||||
|
@ -305,15 +317,18 @@ return [
|
|||
* Add your own thumb generator
|
||||
*
|
||||
* @param \Kirby\Cms\App $kirby Kirby instance
|
||||
* @param string $src The root of the original file
|
||||
* @param string $template The template for the root to the desired destination
|
||||
* @param string $src Root of the original file
|
||||
* @param string $dst Template string for the root to the desired destination
|
||||
* @param array $options All thumb options that should be applied: `width`, `height`, `crop`, `blur`, `grayscale`
|
||||
* @return string
|
||||
*/
|
||||
'thumb' => function (App $kirby, string $src, string $template, array $options): string {
|
||||
$darkroom = Darkroom::factory(option('thumbs.driver', 'gd'), option('thumbs', []));
|
||||
'thumb' => function (App $kirby, string $src, string $dst, array $options): string {
|
||||
$darkroom = Darkroom::factory(
|
||||
option('thumbs.driver', 'gd'),
|
||||
option('thumbs', [])
|
||||
);
|
||||
$options = $darkroom->preprocess($src, $options);
|
||||
$root = (new Filename($src, $template, $options))->toString();
|
||||
$root = (new Filename($src, $dst, $options))->toString();
|
||||
|
||||
F::copy($src, $root, true);
|
||||
$darkroom->process($root, $options);
|
||||
|
@ -327,13 +342,9 @@ return [
|
|||
* @param \Kirby\Cms\App $kirby Kirby instance
|
||||
* @param string $path URL path
|
||||
* @param array|string|null $options Array of options for the Uri class
|
||||
* @param Closure $originalHandler Deprecated: Callback function to the original URL handler with `$path` and `$options` as parameters
|
||||
* Use `$kirby->nativeComponent('url')` inside your URL component instead.
|
||||
* @return string
|
||||
*
|
||||
* @todo Remove $originalHandler parameter in 3.6.0
|
||||
*/
|
||||
'url' => function (App $kirby, string $path = null, $options = null, Closure $originalHandler = null): string {
|
||||
'url' => function (App $kirby, string $path = null, $options = null): string {
|
||||
$language = null;
|
||||
|
||||
// get language from simple string option
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'blocks' => 'Kirby\Form\Field\BlocksField',
|
||||
'checkboxes' => __DIR__ . '/fields/checkboxes.php',
|
||||
'date' => __DIR__ . '/fields/date.php',
|
||||
'email' => __DIR__ . '/fields/email.php',
|
||||
'files' => __DIR__ . '/fields/files.php',
|
||||
'gap' => __DIR__ . '/fields/gap.php',
|
||||
'headline' => __DIR__ . '/fields/headline.php',
|
||||
'hidden' => __DIR__ . '/fields/hidden.php',
|
||||
'info' => __DIR__ . '/fields/info.php',
|
||||
'layout' => 'Kirby\Form\Field\LayoutField',
|
||||
'line' => __DIR__ . '/fields/line.php',
|
||||
'list' => __DIR__ . '/fields/list.php',
|
||||
'multiselect' => __DIR__ . '/fields/multiselect.php',
|
||||
'number' => __DIR__ . '/fields/number.php',
|
||||
'pages' => __DIR__ . '/fields/pages.php',
|
||||
'radio' => __DIR__ . '/fields/radio.php',
|
||||
'range' => __DIR__ . '/fields/range.php',
|
||||
'select' => __DIR__ . '/fields/select.php',
|
||||
'structure' => __DIR__ . '/fields/structure.php',
|
||||
'tags' => __DIR__ . '/fields/tags.php',
|
||||
'tel' => __DIR__ . '/fields/tel.php',
|
||||
'text' => __DIR__ . '/fields/text.php',
|
||||
'textarea' => __DIR__ . '/fields/textarea.php',
|
||||
'time' => __DIR__ . '/fields/time.php',
|
||||
'toggle' => __DIR__ . '/fields/toggle.php',
|
||||
'url' => __DIR__ . '/fields/url.php',
|
||||
'users' => __DIR__ . '/fields/users.php',
|
||||
'writer' => __DIR__ . '/fields/writer.php'
|
||||
];
|
|
@ -5,9 +5,10 @@ use Kirby\Toolkit\A;
|
|||
|
||||
return [
|
||||
'mixins' => [
|
||||
'picker',
|
||||
'filepicker',
|
||||
'layout',
|
||||
'min',
|
||||
'picker',
|
||||
'upload'
|
||||
],
|
||||
'props' => [
|
||||
|
@ -27,20 +28,6 @@ return [
|
|||
return $default;
|
||||
},
|
||||
|
||||
/**
|
||||
* Changes the layout of the selected files. Available layouts: `list`, `cards`
|
||||
*/
|
||||
'layout' => function (string $layout = 'list') {
|
||||
return $layout;
|
||||
},
|
||||
|
||||
/**
|
||||
* Layout size for cards: `tiny`, `small`, `medium`, `large` or `huge`
|
||||
*/
|
||||
'size' => function (string $size = 'auto') {
|
||||
return $size;
|
||||
},
|
||||
|
||||
'value' => function ($value = null) {
|
||||
return $value;
|
||||
}
|
||||
|
@ -68,11 +55,12 @@ return [
|
|||
],
|
||||
'methods' => [
|
||||
'fileResponse' => function ($file) {
|
||||
return $file->panelPickerData([
|
||||
'image' => $this->image,
|
||||
'info' => $this->info ?? false,
|
||||
'model' => $this->model(),
|
||||
'text' => $this->text,
|
||||
return $file->panel()->pickerData([
|
||||
'image' => $this->image,
|
||||
'info' => $this->info ?? false,
|
||||
'layout' => $this->layout,
|
||||
'model' => $this->model(),
|
||||
'text' => $this->text,
|
||||
]);
|
||||
},
|
||||
'toFiles' => function ($value = null) {
|
||||
|
@ -101,6 +89,7 @@ return [
|
|||
return $field->filepicker([
|
||||
'image' => $field->image(),
|
||||
'info' => $field->info(),
|
||||
'layout' => $field->layout(),
|
||||
'limit' => $field->limit(),
|
||||
'page' => $this->requestQuery('page'),
|
||||
'query' => $field->query(),
|
||||
|
@ -116,14 +105,18 @@ return [
|
|||
$field = $this->field();
|
||||
$uploads = $field->uploads();
|
||||
|
||||
// move_uploaded_file() not working with unit test
|
||||
// @codeCoverageIgnoreStart
|
||||
return $field->upload($this, $uploads, function ($file, $parent) use ($field) {
|
||||
return $file->panelPickerData([
|
||||
'image' => $field->image(),
|
||||
'info' => $field->info(),
|
||||
'model' => $field->model(),
|
||||
'text' => $field->text(),
|
||||
return $file->panel()->pickerData([
|
||||
'image' => $field->image(),
|
||||
'info' => $field->info(),
|
||||
'layout' => $field->layout(),
|
||||
'model' => $field->model(),
|
||||
'text' => $field->text(),
|
||||
]);
|
||||
});
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
]
|
||||
];
|
||||
|
|
|
@ -34,7 +34,7 @@ return [
|
|||
'computed' => [
|
||||
'text' => function () {
|
||||
if ($text = $this->text) {
|
||||
$text = $this->model()->toString($text);
|
||||
$text = $this->model()->toSafeString($text);
|
||||
$text = $this->kirby()->kirbytext($text);
|
||||
return $text;
|
||||
}
|
||||
|
|
21
kirby/config/fields/mixins/layout.php
Normal file
21
kirby/config/fields/mixins/layout.php
Normal file
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'props' => [
|
||||
/**
|
||||
* Changes the layout of the selected entries.
|
||||
* Available layouts: `list`, `cardlets`, `cards`
|
||||
*/
|
||||
'layout' => function (string $layout = 'list') {
|
||||
$layouts = ['list', 'cardlets', 'cards'];
|
||||
return in_array($layout, $layouts) ? $layout : 'list';
|
||||
},
|
||||
|
||||
/**
|
||||
* Layout size for cards: `tiny`, `small`, `medium`, `large` or `huge`
|
||||
*/
|
||||
'size' => function (string $size = 'auto') {
|
||||
return $size;
|
||||
},
|
||||
]
|
||||
];
|
|
@ -27,6 +27,7 @@ return [
|
|||
if ($template) {
|
||||
$file = new File([
|
||||
'filename' => 'tmp',
|
||||
'parent' => $this->model(),
|
||||
'template' => $template
|
||||
]);
|
||||
|
||||
|
|
|
@ -4,7 +4,12 @@ use Kirby\Data\Data;
|
|||
use Kirby\Toolkit\A;
|
||||
|
||||
return [
|
||||
'mixins' => ['min', 'pagepicker', 'picker'],
|
||||
'mixins' => [
|
||||
'layout',
|
||||
'min',
|
||||
'pagepicker',
|
||||
'picker',
|
||||
],
|
||||
'props' => [
|
||||
/**
|
||||
* Unset inherited props
|
||||
|
@ -22,13 +27,6 @@ return [
|
|||
return $this->toPages($default);
|
||||
},
|
||||
|
||||
/**
|
||||
* Changes the layout of the selected files. Available layouts: `list`, `cards`
|
||||
*/
|
||||
'layout' => function (string $layout = 'list') {
|
||||
return $layout;
|
||||
},
|
||||
|
||||
/**
|
||||
* Optional query to select a specific set of pages
|
||||
*/
|
||||
|
@ -36,13 +34,6 @@ return [
|
|||
return $query;
|
||||
},
|
||||
|
||||
/**
|
||||
* Layout size for cards: `tiny`, `small`, `medium`, `large` or `huge`
|
||||
*/
|
||||
'size' => function (string $size = 'auto') {
|
||||
return $size;
|
||||
},
|
||||
|
||||
/**
|
||||
* Optionally include subpages of pages
|
||||
*/
|
||||
|
@ -62,10 +53,11 @@ return [
|
|||
],
|
||||
'methods' => [
|
||||
'pageResponse' => function ($page) {
|
||||
return $page->panelPickerData([
|
||||
'image' => $this->image,
|
||||
'info' => $this->info,
|
||||
'text' => $this->text,
|
||||
return $page->panel()->pickerData([
|
||||
'image' => $this->image,
|
||||
'info' => $this->info,
|
||||
'layout' => $this->layout,
|
||||
'text' => $this->text,
|
||||
]);
|
||||
},
|
||||
'toPages' => function ($value = null) {
|
||||
|
@ -95,6 +87,7 @@ return [
|
|||
return $field->pagepicker([
|
||||
'image' => $field->image(),
|
||||
'info' => $field->info(),
|
||||
'layout' => $field->layout(),
|
||||
'limit' => $field->limit(),
|
||||
'page' => $this->requestQuery('page'),
|
||||
'parent' => $this->requestQuery('parent'),
|
||||
|
|
55
kirby/config/fields/slug.php
Normal file
55
kirby/config/fields/slug.php
Normal file
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
|
||||
|
||||
return [
|
||||
'extends' => 'text',
|
||||
'props' => [
|
||||
/**
|
||||
* Unset inherited props
|
||||
*/
|
||||
'converter' => null,
|
||||
'counter' => null,
|
||||
'spellcheck' => null,
|
||||
|
||||
/**
|
||||
* Set of characters allowed in the slug
|
||||
*/
|
||||
'allow' => function (string $allow = '') {
|
||||
return $allow;
|
||||
},
|
||||
|
||||
/**
|
||||
* Changes the link icon
|
||||
*/
|
||||
'icon' => function (string $icon = 'url') {
|
||||
return $icon;
|
||||
},
|
||||
|
||||
/**
|
||||
* Set prefix for the help text
|
||||
*/
|
||||
'path' => function (string $path = null) {
|
||||
return $path;
|
||||
},
|
||||
|
||||
/**
|
||||
* Name of another field that should be used to
|
||||
* automatically update this field's value
|
||||
*/
|
||||
'sync' => function (string $sync = null) {
|
||||
return $sync;
|
||||
},
|
||||
|
||||
/**
|
||||
* Set to object with keys `field` and `text` to add
|
||||
* button to generate from another field
|
||||
*/
|
||||
'wizard' => function ($wizard = false) {
|
||||
return $wizard;
|
||||
}
|
||||
],
|
||||
'validations' => [
|
||||
'minlength',
|
||||
'maxlength'
|
||||
],
|
||||
];
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
|
||||
use Kirby\Cms\Form;
|
||||
use Kirby\Data\Data;
|
||||
use Kirby\Form\Form;
|
||||
use Kirby\Toolkit\I18n;
|
||||
|
||||
return [
|
||||
|
|
|
@ -109,7 +109,7 @@ return [
|
|||
|
||||
return [
|
||||
'filename' => $file->filename(),
|
||||
'dragText' => $file->dragText('auto', $absolute),
|
||||
'dragText' => $file->panel()->dragText('auto', $absolute),
|
||||
];
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
|
||||
use Kirby\Exception\InvalidArgumentException;
|
||||
use Kirby\Toolkit\A;
|
||||
use Kirby\Toolkit\I18n;
|
||||
|
||||
return [
|
||||
|
@ -20,19 +21,25 @@ return [
|
|||
* Sets the text next to the toggle. The text can be a string or an array of two options. The first one is the negative text and the second one the positive. The text will automatically switch when the toggle is triggered.
|
||||
*/
|
||||
'text' => function ($value = null) {
|
||||
$model = $this->model();
|
||||
|
||||
if (is_array($value) === true) {
|
||||
if (A::isAssociative($value) === true) {
|
||||
return I18n::translate($value, $value);
|
||||
return $model->toSafeString(I18n::translate($value, $value));
|
||||
}
|
||||
|
||||
foreach ($value as $key => $val) {
|
||||
$value[$key] = I18n::translate($val, $val);
|
||||
$value[$key] = $model->toSafeString(I18n::translate($val, $val));
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
return I18n::translate($value, $value);
|
||||
if (empty($value) === false) {
|
||||
return $model->toSafeString(I18n::translate($value, $value));
|
||||
}
|
||||
|
||||
return $value;
|
||||
},
|
||||
],
|
||||
'computed' => [
|
||||
|
|
|
@ -4,7 +4,12 @@ use Kirby\Data\Data;
|
|||
use Kirby\Toolkit\A;
|
||||
|
||||
return [
|
||||
'mixins' => ['min', 'picker', 'userpicker'],
|
||||
'mixins' => [
|
||||
'layout',
|
||||
'min',
|
||||
'picker',
|
||||
'userpicker'
|
||||
],
|
||||
'props' => [
|
||||
/**
|
||||
* Unset inherited props
|
||||
|
@ -44,10 +49,11 @@ return [
|
|||
],
|
||||
'methods' => [
|
||||
'userResponse' => function ($user) {
|
||||
return $user->panelPickerData([
|
||||
'info' => $this->info,
|
||||
'image' => $this->image,
|
||||
'text' => $this->text,
|
||||
return $user->panel()->pickerData([
|
||||
'info' => $this->info,
|
||||
'image' => $this->image,
|
||||
'layout' => $this->layout,
|
||||
'text' => $this->text,
|
||||
]);
|
||||
},
|
||||
'toUsers' => function ($value = null) {
|
||||
|
@ -77,6 +83,7 @@ return [
|
|||
return $field->userpicker([
|
||||
'image' => $field->image(),
|
||||
'info' => $field->info(),
|
||||
'layout' => $field->layout(),
|
||||
'limit' => $field->limit(),
|
||||
'page' => $this->requestQuery('page'),
|
||||
'query' => $field->query(),
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
<?php
|
||||
|
||||
use Kirby\Sane\Sane;
|
||||
|
||||
return [
|
||||
'props' => [
|
||||
/**
|
||||
|
@ -11,14 +13,14 @@ return [
|
|||
return $inline;
|
||||
},
|
||||
/**
|
||||
* Sets the allowed HTML formats. Available formats: `bold`, `italic`, `underline`, `strike`, `code`, `link`. Activate them all by passing `true`. Deactivate them all by passing `false`
|
||||
* Sets the allowed HTML formats. Available formats: `bold`, `italic`, `underline`, `strike`, `code`, `link`, `email`. Activate them all by passing `true`. Deactivate them all by passing `false`
|
||||
* @param array|bool $marks
|
||||
*/
|
||||
'marks' => function ($marks = true) {
|
||||
return $marks;
|
||||
},
|
||||
/**
|
||||
* Sets the allowed nodes. Available nodes: `bulletList`, `orderedList`, `heading`, `horizontalRule`, `listItem`. Activate/deactivate them all by passing `true`/`false`. Default nodes are `heading`, `bulletList`, `orderedList`.
|
||||
* Sets the allowed nodes. Available nodes: `paragraph`, `heading`, `bulletList`, `orderedList`. Activate/deactivate them all by passing `true`/`false`. Default nodes are `paragraph`, `heading`, `bulletList`, `orderedList`.
|
||||
* @param array|bool|null $nodes
|
||||
*/
|
||||
'nodes' => function ($nodes = null) {
|
||||
|
@ -27,7 +29,7 @@ return [
|
|||
],
|
||||
'computed' => [
|
||||
'value' => function () {
|
||||
return trim($this->value);
|
||||
return Sane::sanitize(trim($this->value), 'html');
|
||||
}
|
||||
],
|
||||
];
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
<?php
|
||||
|
||||
use Kirby\Cms\App;
|
||||
use Kirby\Cms\Asset;
|
||||
use Kirby\Cms\Html;
|
||||
use Kirby\Cms\Response;
|
||||
use Kirby\Cms\Url;
|
||||
use Kirby\Exception\InvalidArgumentException;
|
||||
use Kirby\Filesystem\Asset;
|
||||
use Kirby\Filesystem\F;
|
||||
use Kirby\Http\Router;
|
||||
use Kirby\Toolkit\Escape;
|
||||
use Kirby\Toolkit\F;
|
||||
use Kirby\Toolkit\I18n;
|
||||
use Kirby\Toolkit\Str;
|
||||
use Kirby\Toolkit\V;
|
||||
|
@ -16,7 +17,7 @@ use Kirby\Toolkit\V;
|
|||
* Helper to create an asset object
|
||||
*
|
||||
* @param string $path
|
||||
* @return \Kirby\Cms\Asset
|
||||
* @return \Kirby\Filesystem\Asset
|
||||
*/
|
||||
function asset(string $path)
|
||||
{
|
||||
|
@ -26,12 +27,12 @@ function asset(string $path)
|
|||
/**
|
||||
* Generates a list of HTML attributes
|
||||
*
|
||||
* @param array $attr A list of attributes as key/value array
|
||||
* @param string $before An optional string that will be prepended if the result is not empty
|
||||
* @param string $after An optional string that will be appended if the result is not empty
|
||||
* @return string
|
||||
* @param array|null $attr A list of attributes as key/value array
|
||||
* @param string|null $before An optional string that will be prepended if the result is not empty
|
||||
* @param string|null $after An optional string that will be appended if the result is not empty
|
||||
* @return string|null
|
||||
*/
|
||||
function attr(array $attr = null, $before = null, $after = null)
|
||||
function attr(?array $attr = null, ?string $before = null, ?string $after = null): ?string
|
||||
{
|
||||
if ($attrs = Html::attr($attr)) {
|
||||
return $before . $attrs . $after;
|
||||
|
@ -54,28 +55,33 @@ function collection(string $name)
|
|||
/**
|
||||
* Checks / returns a CSRF token
|
||||
*
|
||||
* @param string $check Pass a token here to compare it to the one in the session
|
||||
* @param string|null $check Pass a token here to compare it to the one in the session
|
||||
* @return string|bool Either the token or a boolean check result
|
||||
*/
|
||||
function csrf(string $check = null)
|
||||
function csrf(?string $check = null)
|
||||
{
|
||||
$session = App::instance()->session();
|
||||
|
||||
// check explicitly if there have been no arguments at all;
|
||||
// no arguments, generate/return a token
|
||||
// (check explicitly if there have been no arguments at all;
|
||||
// checking for null introduces a security issue because null could come
|
||||
// from user input or bugs in the calling code!
|
||||
// from user input or bugs in the calling code!)
|
||||
if (func_num_args() === 0) {
|
||||
// no arguments, generate/return a token
|
||||
|
||||
$token = $session->get('kirby.csrf');
|
||||
|
||||
if (is_string($token) !== true) {
|
||||
$token = bin2hex(random_bytes(32));
|
||||
$session->set('kirby.csrf', $token);
|
||||
}
|
||||
|
||||
return $token;
|
||||
} elseif (is_string($check) === true && is_string($session->get('kirby.csrf')) === true) {
|
||||
// argument has been passed, check the token
|
||||
}
|
||||
|
||||
// argument has been passed, check the token
|
||||
if (
|
||||
is_string($check) === true &&
|
||||
is_string($session->get('kirby.csrf')) === true
|
||||
) {
|
||||
return hash_equals($session->get('kirby.csrf'), $check) === true;
|
||||
}
|
||||
|
||||
|
@ -174,7 +180,7 @@ if (function_exists('e') === false) {
|
|||
* @param string $context Location of output (`html`, `attr`, `js`, `css`, `url` or `xml`)
|
||||
* @return string Escaped data
|
||||
*/
|
||||
function esc($string, $context = 'html')
|
||||
function esc(string $string, string $context = 'html'): string
|
||||
{
|
||||
if (method_exists('Kirby\Toolkit\Escape', $context) === true) {
|
||||
return Escape::$context($string);
|
||||
|
@ -200,10 +206,10 @@ function get($key = null, $default = null)
|
|||
* Embeds a Github Gist
|
||||
*
|
||||
* @param string $url
|
||||
* @param string $file
|
||||
* @param string|null $file
|
||||
* @return string
|
||||
*/
|
||||
function gist(string $url, string $file = null): string
|
||||
function gist(string $url, ?string $file = null): string
|
||||
{
|
||||
return kirbytag([
|
||||
'gist' => $url,
|
||||
|
@ -255,10 +261,10 @@ function html(?string $string, bool $keepTags = false)
|
|||
* Example:
|
||||
* <?= image('some/page/myimage.jpg') ?>
|
||||
*
|
||||
* @param string $path
|
||||
* @param string|null $path
|
||||
* @return \Kirby\Cms\File|null
|
||||
*/
|
||||
function image(string $path = null)
|
||||
function image(?string $path = null)
|
||||
{
|
||||
if ($path === null) {
|
||||
return page()->image();
|
||||
|
@ -296,9 +302,9 @@ function image(string $path = null)
|
|||
* @param array $data
|
||||
* @param array $rules
|
||||
* @param array $messages
|
||||
* @return false|array
|
||||
* @return array
|
||||
*/
|
||||
function invalid(array $data = [], array $rules = [], array $messages = [])
|
||||
function invalid(array $data = [], array $rules = [], array $messages = []): array
|
||||
{
|
||||
$errors = [];
|
||||
|
||||
|
@ -407,12 +413,12 @@ function kirby()
|
|||
* Makes it possible to use any defined Kirbytag as standalone function
|
||||
*
|
||||
* @param string|array $type
|
||||
* @param string $value
|
||||
* @param string|null $value
|
||||
* @param array $attr
|
||||
* @param array $data
|
||||
* @return string
|
||||
*/
|
||||
function kirbytag($type, string $value = null, array $attr = [], array $data = []): string
|
||||
function kirbytag($type, ?string $value = null, array $attr = [], array $data = []): string
|
||||
{
|
||||
if (is_array($type) === true) {
|
||||
$kirbytag = $type;
|
||||
|
@ -434,11 +440,11 @@ function kirbytag($type, string $value = null, array $attr = [], array $data = [
|
|||
* Parses KirbyTags in the given string. Shortcut
|
||||
* for `$kirby->kirbytags($text, $data)`
|
||||
*
|
||||
* @param string $text
|
||||
* @param string|null $text
|
||||
* @param array $data
|
||||
* @return string
|
||||
*/
|
||||
function kirbytags(string $text = null, array $data = []): string
|
||||
function kirbytags(?string $text = null, array $data = []): string
|
||||
{
|
||||
return App::instance()->kirbytags($text, $data);
|
||||
}
|
||||
|
@ -447,11 +453,11 @@ function kirbytags(string $text = null, array $data = []): string
|
|||
* Parses KirbyTags and Markdown in the
|
||||
* given string. Shortcut for `$kirby->kirbytext()`
|
||||
*
|
||||
* @param string $text
|
||||
* @param string|null $text
|
||||
* @param array $data
|
||||
* @return string
|
||||
*/
|
||||
function kirbytext(string $text = null, array $data = []): string
|
||||
function kirbytext(?string $text = null, array $data = []): string
|
||||
{
|
||||
return App::instance()->kirbytext($text, $data);
|
||||
}
|
||||
|
@ -461,11 +467,11 @@ function kirbytext(string $text = null, array $data = []): string
|
|||
* given string.
|
||||
* @since 3.1.0
|
||||
*
|
||||
* @param string $text
|
||||
* @param string|null $text
|
||||
* @param array $data
|
||||
* @return string
|
||||
*/
|
||||
function kirbytextinline(string $text = null, array $data = []): string
|
||||
function kirbytextinline(?string $text = null, array $data = []): string
|
||||
{
|
||||
return App::instance()->kirbytext($text, $data, true);
|
||||
}
|
||||
|
@ -473,11 +479,11 @@ function kirbytextinline(string $text = null, array $data = []): string
|
|||
/**
|
||||
* Shortcut for `kirbytext()` helper
|
||||
*
|
||||
* @param string $text
|
||||
* @param string|null $text
|
||||
* @param array $data
|
||||
* @return string
|
||||
*/
|
||||
function kt(string $text = null, array $data = []): string
|
||||
function kt(?string $text = null, array $data = []): string
|
||||
{
|
||||
return kirbytext($text, $data);
|
||||
}
|
||||
|
@ -486,11 +492,11 @@ function kt(string $text = null, array $data = []): string
|
|||
* Shortcut for `kirbytextinline()` helper
|
||||
* @since 3.1.0
|
||||
*
|
||||
* @param string $text
|
||||
* @param string|null $text
|
||||
* @param array $data
|
||||
* @return string
|
||||
*/
|
||||
function kti(string $text = null, array $data = []): string
|
||||
function kti(?string $text = null, array $data = []): string
|
||||
{
|
||||
return kirbytextinline($text, $data);
|
||||
}
|
||||
|
@ -499,10 +505,10 @@ function kti(string $text = null, array $data = []): string
|
|||
* A super simple class autoloader
|
||||
*
|
||||
* @param array $classmap
|
||||
* @param string $base
|
||||
* @param string|null $base
|
||||
* @return void
|
||||
*/
|
||||
function load(array $classmap, string $base = null)
|
||||
function load(array $classmap, ?string $base = null)
|
||||
{
|
||||
// convert all classnames to lowercase
|
||||
$classmap = array_change_key_case($classmap);
|
||||
|
@ -526,10 +532,10 @@ function load(array $classmap, string $base = null)
|
|||
* Parses markdown in the given string. Shortcut for
|
||||
* `$kirby->markdown($text)`
|
||||
*
|
||||
* @param string $text
|
||||
* @param string|null $text
|
||||
* @return string
|
||||
*/
|
||||
function markdown(string $text = null): string
|
||||
function markdown(?string $text = null): string
|
||||
{
|
||||
return App::instance()->markdown($text);
|
||||
}
|
||||
|
@ -551,7 +557,8 @@ function option(string $key, $default = null)
|
|||
* id or the current page when no id is specified
|
||||
*
|
||||
* @param string|array ...$id
|
||||
* @return \Kirby\Cms\Page|null
|
||||
* @return \Kirby\Cms\Page|\Kirby\Cms\Pages|null
|
||||
* @todo reduce to one parameter in 3.7.0 (also change return and return type)
|
||||
*/
|
||||
function page(...$id)
|
||||
{
|
||||
|
@ -559,6 +566,12 @@ function page(...$id)
|
|||
return App::instance()->site()->page();
|
||||
}
|
||||
|
||||
if (count($id) > 1) {
|
||||
// @codeCoverageIgnoreStart
|
||||
deprecated('Passing multiple parameters to the `page()` helper has been deprecated. Please use the `pages()` helper instead.');
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
return App::instance()->site()->find(...$id);
|
||||
}
|
||||
|
||||
|
@ -566,10 +579,17 @@ function page(...$id)
|
|||
* Helper to build page collections
|
||||
*
|
||||
* @param string|array ...$id
|
||||
* @return \Kirby\Cms\Pages
|
||||
* @return \Kirby\Cms\Page|\Kirby\Cms\Pages|null
|
||||
* @todo return only Pages|null in 3.7.0, wrap in Pages for single passed id
|
||||
*/
|
||||
function pages(...$id)
|
||||
{
|
||||
if (count($id) === 1) {
|
||||
// @codeCoverageIgnoreStart
|
||||
deprecated('Passing a single id to the `pages()` helper will return a Kirby\Cms\Pages collection with a single element instead of the single Kirby\Cms\Page object itself - starting in 3.7.0.');
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
return App::instance()->site()->find(...$id);
|
||||
}
|
||||
|
||||
|
@ -577,10 +597,10 @@ function pages(...$id)
|
|||
* Returns a single param from the URL
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $fallback
|
||||
* @param string|null $fallback
|
||||
* @return string|null
|
||||
*/
|
||||
function param(string $key, string $fallback = null): ?string
|
||||
function param(string $key, ?string $fallback = null): ?string
|
||||
{
|
||||
return App::instance()->request()->url()->params()->$key ?? $fallback;
|
||||
}
|
||||
|
@ -608,6 +628,22 @@ function r($condition, $value, $alternative = null)
|
|||
return $condition ? $value : $alternative;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a micro-router and executes
|
||||
* the routing action immediately
|
||||
* @since 3.6.0
|
||||
*
|
||||
* @param string|null $path
|
||||
* @param string $method
|
||||
* @param array $routes
|
||||
* @param \Closure|null $callback
|
||||
* @return mixed
|
||||
*/
|
||||
function router(?string $path = null, string $method = 'GET', array $routes = [], ?Closure $callback = null)
|
||||
{
|
||||
return (new Router($routes))->call($path, $method, $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current site object
|
||||
*
|
||||
|
@ -623,6 +659,7 @@ function site()
|
|||
*
|
||||
* @param mixed $value
|
||||
* @return int
|
||||
* @throws \Kirby\Exception\InvalidArgumentException
|
||||
*/
|
||||
function size($value): int
|
||||
{
|
||||
|
@ -655,10 +692,10 @@ function size($value): int
|
|||
* Enhances the given string with
|
||||
* smartypants. Shortcut for `$kirby->smartypants($text)`
|
||||
*
|
||||
* @param string $text
|
||||
* @param string|null $text
|
||||
* @return string
|
||||
*/
|
||||
function smartypants(string $text = null): string
|
||||
function smartypants(?string $text = null): string
|
||||
{
|
||||
return App::instance()->smartypants($text);
|
||||
}
|
||||
|
@ -725,7 +762,7 @@ function svg($file)
|
|||
*
|
||||
* @param string|array $key
|
||||
* @param string|null $fallback
|
||||
* @return mixed
|
||||
* @return array|string|null
|
||||
*/
|
||||
function t($key, string $fallback = null)
|
||||
{
|
||||
|
@ -735,11 +772,11 @@ function t($key, string $fallback = null)
|
|||
/**
|
||||
* Translates a count
|
||||
*
|
||||
* @param string|array $key
|
||||
* @param string $key
|
||||
* @param int $count
|
||||
* @return mixed
|
||||
*/
|
||||
function tc($key, int $count)
|
||||
function tc(string $key, int $count)
|
||||
{
|
||||
return I18n::translateCount($key, $count);
|
||||
}
|
||||
|
@ -748,11 +785,11 @@ function tc($key, int $count)
|
|||
* Rounds the minutes of the given date
|
||||
* by the defined step
|
||||
*
|
||||
* @param string $date
|
||||
* @param int $step array of `unit` and `size` to round to nearest
|
||||
* @param string|null $date
|
||||
* @param int|array|null $step array of `unit` and `size` to round to nearest
|
||||
* @return int|null
|
||||
*/
|
||||
function timestamp(string $date = null, $step = null): ?int
|
||||
function timestamp(?string $date = null, $step = null): ?int
|
||||
{
|
||||
if (V::date($date) === false) {
|
||||
return null;
|
||||
|
@ -807,7 +844,7 @@ function timestamp(string $date = null, $step = null): ?int
|
|||
);
|
||||
|
||||
// on error, convert `false` into `null`
|
||||
return $timestamp ? $timestamp : null;
|
||||
return $timestamp ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -815,12 +852,12 @@ function timestamp(string $date = null, $step = null): ?int
|
|||
* placeholders in the text
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $fallback
|
||||
* @param array $replace
|
||||
* @param string $locale
|
||||
* @param string|array|null $fallback
|
||||
* @param array|null $replace
|
||||
* @param string|null $locale
|
||||
* @return string
|
||||
*/
|
||||
function tt(string $key, $fallback = null, array $replace = null, string $locale = null)
|
||||
function tt(string $key, $fallback = null, ?array $replace = null, ?string $locale = null)
|
||||
{
|
||||
return I18n::template($key, $fallback, $replace, $locale);
|
||||
}
|
||||
|
@ -829,12 +866,12 @@ function tt(string $key, $fallback = null, array $replace = null, string $locale
|
|||
* Builds a Twitter link
|
||||
*
|
||||
* @param string $username
|
||||
* @param string $text
|
||||
* @param string $title
|
||||
* @param string $class
|
||||
* @param string|null $text
|
||||
* @param string|null $title
|
||||
* @param string|null $class
|
||||
* @return string
|
||||
*/
|
||||
function twitter(string $username, string $text = null, string $title = null, string $class = null): string
|
||||
function twitter(string $username, ?string $text = null, ?string $title = null, ?string $class = null): string
|
||||
{
|
||||
return kirbytag([
|
||||
'twitter' => $username,
|
||||
|
@ -847,11 +884,11 @@ function twitter(string $username, string $text = null, string $title = null, st
|
|||
/**
|
||||
* Shortcut for url()
|
||||
*
|
||||
* @param string $path
|
||||
* @param string|null $path
|
||||
* @param array|string|null $options
|
||||
* @return string
|
||||
*/
|
||||
function u(string $path = null, $options = null): string
|
||||
function u(?string $path = null, $options = null): string
|
||||
{
|
||||
return Url::to($path, $options);
|
||||
}
|
||||
|
@ -859,11 +896,11 @@ function u(string $path = null, $options = null): string
|
|||
/**
|
||||
* Builds an absolute URL for a given path
|
||||
*
|
||||
* @param string $path
|
||||
* @param string|null $path
|
||||
* @param array|string|null $options
|
||||
* @return string
|
||||
*/
|
||||
function url(string $path = null, $options = null): string
|
||||
function url(?string $path = null, $options = null): string
|
||||
{
|
||||
return Url::to($path, $options);
|
||||
}
|
||||
|
@ -906,9 +943,9 @@ function uuid(): string
|
|||
* @param string $url
|
||||
* @param array $options
|
||||
* @param array $attr
|
||||
* @return string
|
||||
* @return string|null
|
||||
*/
|
||||
function video(string $url, array $options = [], array $attr = []): string
|
||||
function video(string $url, array $options = [], array $attr = []): ?string
|
||||
{
|
||||
return Html::video($url, $options, $attr);
|
||||
}
|
||||
|
@ -919,9 +956,9 @@ function video(string $url, array $options = [], array $attr = []): string
|
|||
* @param string $url
|
||||
* @param array $options
|
||||
* @param array $attr
|
||||
* @return string
|
||||
* @return string|null
|
||||
*/
|
||||
function vimeo(string $url, array $options = [], array $attr = []): string
|
||||
function vimeo(string $url, array $options = [], array $attr = []): ?string
|
||||
{
|
||||
return Html::vimeo($url, $options, $attr);
|
||||
}
|
||||
|
@ -945,9 +982,9 @@ function widont(string $string = null): string
|
|||
* @param string $url
|
||||
* @param array $options
|
||||
* @param array $attr
|
||||
* @return string
|
||||
* @return string|null
|
||||
*/
|
||||
function youtube(string $url, array $options = [], array $attr = []): string
|
||||
function youtube(string $url, array $options = [], array $attr = []): ?string
|
||||
{
|
||||
return Html::youtube($url, $options, $attr);
|
||||
}
|
||||
|
|
|
@ -366,7 +366,7 @@ return function (App $app) {
|
|||
* @return \Kirby\Cms\Field
|
||||
*/
|
||||
'html' => function (Field $field) {
|
||||
$field->value = htmlentities($field->value, ENT_COMPAT, 'utf-8');
|
||||
$field->value = Html::encode($field->value);
|
||||
return $field;
|
||||
},
|
||||
|
||||
|
@ -498,13 +498,14 @@ return function (App $app) {
|
|||
*/
|
||||
'replace' => function (Field $field, array $data = [], string $fallback = '') use ($app) {
|
||||
if ($parent = $field->parent()) {
|
||||
$field->value = $field->parent()->toString($field->value, $data, $fallback);
|
||||
// never pass `null` as the $template to avoid the fallback to the model ID
|
||||
$field->value = $parent->toString($field->value ?? '', $data, $fallback);
|
||||
} else {
|
||||
$field->value = Str::template($field->value, array_replace([
|
||||
'kirby' => $app,
|
||||
'site' => $app->site(),
|
||||
'page' => $app->page()
|
||||
], $data), $fallback);
|
||||
], $data), ['fallback' => $fallback]);
|
||||
}
|
||||
|
||||
return $field;
|
||||
|
|
|
@ -1,93 +0,0 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
// kirby
|
||||
'kirby' => function (array $roots) {
|
||||
return realpath(__DIR__ . '/../');
|
||||
},
|
||||
|
||||
// i18n
|
||||
'i18n' => function (array $roots) {
|
||||
return $roots['kirby'] . '/i18n';
|
||||
},
|
||||
'i18n:translations' => function (array $roots) {
|
||||
return $roots['i18n'] . '/translations';
|
||||
},
|
||||
'i18n:rules' => function (array $roots) {
|
||||
return $roots['i18n'] . '/rules';
|
||||
},
|
||||
|
||||
// index
|
||||
'index' => function (array $roots) {
|
||||
return realpath(__DIR__ . '/../../');
|
||||
},
|
||||
|
||||
// assets
|
||||
'assets' => function (array $roots) {
|
||||
return $roots['index'] . '/assets';
|
||||
},
|
||||
|
||||
// content
|
||||
'content' => function (array $roots) {
|
||||
return $roots['index'] . '/content';
|
||||
},
|
||||
|
||||
// media
|
||||
'media' => function (array $roots) {
|
||||
return $roots['index'] . '/media';
|
||||
},
|
||||
|
||||
// panel
|
||||
'panel' => function (array $roots) {
|
||||
return $roots['kirby'] . '/panel';
|
||||
},
|
||||
|
||||
// site
|
||||
'site' => function (array $roots) {
|
||||
return $roots['index'] . '/site';
|
||||
},
|
||||
'accounts' => function (array $roots) {
|
||||
return $roots['site'] . '/accounts';
|
||||
},
|
||||
'blueprints' => function (array $roots) {
|
||||
return $roots['site'] . '/blueprints';
|
||||
},
|
||||
'cache' => function (array $roots) {
|
||||
return $roots['site'] . '/cache';
|
||||
},
|
||||
'collections' => function (array $roots) {
|
||||
return $roots['site'] . '/collections';
|
||||
},
|
||||
'config' => function (array $roots) {
|
||||
return $roots['site'] . '/config';
|
||||
},
|
||||
'controllers' => function (array $roots) {
|
||||
return $roots['site'] . '/controllers';
|
||||
},
|
||||
'languages' => function (array $roots) {
|
||||
return $roots['site'] . '/languages';
|
||||
},
|
||||
'logs' => function (array $roots) {
|
||||
return $roots['site'] . '/logs';
|
||||
},
|
||||
'models' => function (array $roots) {
|
||||
return $roots['site'] . '/models';
|
||||
},
|
||||
'plugins' => function (array $roots) {
|
||||
return $roots['site'] . '/plugins';
|
||||
},
|
||||
'sessions' => function (array $roots) {
|
||||
return $roots['site'] . '/sessions';
|
||||
},
|
||||
'snippets' => function (array $roots) {
|
||||
return $roots['site'] . '/snippets';
|
||||
},
|
||||
'templates' => function (array $roots) {
|
||||
return $roots['site'] . '/templates';
|
||||
},
|
||||
|
||||
// blueprints
|
||||
'roles' => function (array $roots) {
|
||||
return $roots['blueprints'] . '/users';
|
||||
},
|
||||
];
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
use Kirby\Cms\LanguageRoutes;
|
||||
use Kirby\Cms\Media;
|
||||
use Kirby\Cms\Panel;
|
||||
use Kirby\Cms\PanelPlugins;
|
||||
use Kirby\Cms\PluginAssets;
|
||||
use Kirby\Panel\Panel;
|
||||
use Kirby\Panel\Plugins;
|
||||
use Kirby\Toolkit\Str;
|
||||
|
||||
return function ($kirby) {
|
||||
|
@ -50,7 +50,7 @@ return function ($kirby) {
|
|||
'pattern' => $media . '/plugins/index.(css|js)',
|
||||
'env' => 'media',
|
||||
'action' => function (string $type) use ($kirby) {
|
||||
$plugins = new PanelPlugins();
|
||||
$plugins = new Plugins();
|
||||
|
||||
return $kirby
|
||||
->response()
|
||||
|
@ -65,17 +65,6 @@ return function ($kirby) {
|
|||
return PluginAssets::resolve($provider . '/' . $pluginName, $filename . '.' . $extension);
|
||||
}
|
||||
],
|
||||
[
|
||||
'pattern' => $panel . '/(:all?)',
|
||||
'env' => 'panel',
|
||||
'action' => function () use ($kirby) {
|
||||
if ($kirby->option('panel') === false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Panel::render($kirby);
|
||||
}
|
||||
],
|
||||
[
|
||||
'pattern' => $media . '/pages/(:all)/(:any)/(:any)',
|
||||
'env' => 'media',
|
||||
|
@ -103,7 +92,15 @@ return function ($kirby) {
|
|||
'action' => function ($path, $hash, $filename) {
|
||||
return Media::thumb($path, $hash, $filename);
|
||||
}
|
||||
]
|
||||
],
|
||||
[
|
||||
'pattern' => $panel . '/(:all?)',
|
||||
'method' => 'ALL',
|
||||
'env' => 'panel',
|
||||
'action' => function ($path = null) {
|
||||
return Panel::router($path);
|
||||
}
|
||||
],
|
||||
];
|
||||
|
||||
// Multi-language setup
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
use Kirby\Cms\Form;
|
||||
use Kirby\Form\Form;
|
||||
|
||||
return [
|
||||
'props' => [
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<?php
|
||||
|
||||
use Kirby\Cms\File;
|
||||
use Kirby\Toolkit\Escape;
|
||||
use Kirby\Toolkit\I18n;
|
||||
|
||||
return [
|
||||
|
@ -29,7 +28,7 @@ return [
|
|||
return $image ?? [];
|
||||
},
|
||||
/**
|
||||
* Optional info text setup. Info text is shown on the right (lists) or below (cards) the filename.
|
||||
* Optional info text setup. Info text is shown on the right (lists, cardlets) or below (cards) the filename.
|
||||
*/
|
||||
'info' => function ($info = null) {
|
||||
return I18n::translate($info, $info);
|
||||
|
@ -70,6 +69,7 @@ return [
|
|||
if ($this->template) {
|
||||
$file = new File([
|
||||
'filename' => 'tmp',
|
||||
'parent' => $this->model(),
|
||||
'template' => $this->template
|
||||
]);
|
||||
|
||||
|
@ -90,7 +90,7 @@ return [
|
|||
if ($this->sortBy) {
|
||||
$files = $files->sort(...$files::sortArgs($this->sortBy));
|
||||
} else {
|
||||
$files = $files->sort('sort', 'asc', 'filename', 'asc');
|
||||
$files = $files->sorted();
|
||||
}
|
||||
|
||||
// flip
|
||||
|
@ -115,28 +115,21 @@ return [
|
|||
$dragTextAbsolute = $this->model->is($this->parent) === false;
|
||||
|
||||
foreach ($this->files as $file) {
|
||||
$image = $file->panelImage($this->image);
|
||||
|
||||
// escape the default text
|
||||
// TODO: no longer needed in 3.6
|
||||
$text = $file->toString($this->text);
|
||||
if ($this->text === '{{ file.filename }}') {
|
||||
$text = Escape::html($text);
|
||||
}
|
||||
$panel = $file->panel();
|
||||
|
||||
$data[] = [
|
||||
'dragText' => $file->dragText('auto', $dragTextAbsolute),
|
||||
'dragText' => $panel->dragText('auto', $dragTextAbsolute),
|
||||
'extension' => $file->extension(),
|
||||
'filename' => $file->filename(),
|
||||
'id' => $file->id(),
|
||||
'icon' => $file->panelIcon($image),
|
||||
'image' => $image,
|
||||
'info' => $file->toString($this->info ?? false),
|
||||
'link' => $file->panelUrl(true),
|
||||
'mime' => $file->mime(),
|
||||
'parent' => $file->parent()->panelPath(),
|
||||
'text' => $text,
|
||||
'url' => $file->url(),
|
||||
'filename' => $file->filename(),
|
||||
'id' => $file->id(),
|
||||
'image' => $panel->image($this->image, $this->layout),
|
||||
'info' => $file->toSafeString($this->info ?? false),
|
||||
'link' => $panel->url(true),
|
||||
'mime' => $file->mime(),
|
||||
'parent' => $file->parent()->panel()->path(),
|
||||
'template' => $file->template(),
|
||||
'text' => $file->toSafeString($this->text),
|
||||
'url' => $file->url(),
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -174,8 +167,8 @@ return [
|
|||
];
|
||||
},
|
||||
'link' => function () {
|
||||
$modelLink = $this->model->panelUrl(true);
|
||||
$parentLink = $this->parent->panelUrl(true);
|
||||
$modelLink = $this->model->panel()->url(true);
|
||||
$parentLink = $this->parent->panel()->url(true);
|
||||
|
||||
if ($modelLink !== $parentLink) {
|
||||
return $parentLink;
|
||||
|
@ -222,6 +215,7 @@ return [
|
|||
'max' => $max,
|
||||
'api' => $this->parent->apiUrl(true) . '/files',
|
||||
'attributes' => array_filter([
|
||||
'sort' => $this->sortable === true ? $total + 1 : null,
|
||||
'template' => $template
|
||||
])
|
||||
];
|
||||
|
|
|
@ -17,7 +17,7 @@ return [
|
|||
'computed' => [
|
||||
'text' => function () {
|
||||
if ($this->text) {
|
||||
$text = $this->model()->toString($this->text);
|
||||
$text = $this->model()->toSafeString($this->text);
|
||||
$text = $this->kirby()->kirbytext($text);
|
||||
return $text;
|
||||
}
|
||||
|
@ -25,11 +25,9 @@ return [
|
|||
],
|
||||
'toArray' => function () {
|
||||
return [
|
||||
'options' => [
|
||||
'headline' => $this->headline,
|
||||
'text' => $this->text,
|
||||
'theme' => $this->theme
|
||||
]
|
||||
'headline' => $this->headline,
|
||||
'text' => $this->text,
|
||||
'theme' => $this->theme
|
||||
];
|
||||
}
|
||||
];
|
||||
|
|
|
@ -14,7 +14,7 @@ return [
|
|||
'computed' => [
|
||||
'empty' => function () {
|
||||
if ($this->empty) {
|
||||
return $this->model()->toString($this->empty);
|
||||
return $this->model()->toSafeString($this->empty);
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
@ -14,7 +14,7 @@ return [
|
|||
'computed' => [
|
||||
'help' => function () {
|
||||
if ($this->help) {
|
||||
$help = $this->model()->toString($this->help);
|
||||
$help = $this->model()->toSafeString($this->help);
|
||||
$help = $this->kirby()->kirbytext($help);
|
||||
return $help;
|
||||
}
|
||||
|
|
|
@ -3,10 +3,12 @@
|
|||
return [
|
||||
'props' => [
|
||||
/**
|
||||
* Section layout. Available layout methods: `list`, `cards`.
|
||||
* Section layout.
|
||||
* Available layout methods: `list`, `cardlets`, `cards`.
|
||||
*/
|
||||
'layout' => function (string $layout = 'list') {
|
||||
return $layout === 'cards' ? 'cards' : 'list';
|
||||
$layouts = ['list', 'cardlets', 'cards'];
|
||||
return in_array($layout, $layouts) ? $layout : 'list';
|
||||
}
|
||||
]
|
||||
];
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<?php
|
||||
|
||||
use Kirby\Cms\Blueprint;
|
||||
use Kirby\Exception\InvalidArgumentException;
|
||||
use Kirby\Toolkit\A;
|
||||
use Kirby\Toolkit\Escape;
|
||||
use Kirby\Toolkit\I18n;
|
||||
|
||||
return [
|
||||
|
@ -89,7 +89,13 @@ return [
|
|||
],
|
||||
'computed' => [
|
||||
'parent' => function () {
|
||||
return $this->parentModel();
|
||||
$parent = $this->parentModel();
|
||||
|
||||
if (is_a($parent, 'Kirby\Cms\Site') === false && is_a($parent, 'Kirby\Cms\Page') === false) {
|
||||
throw new InvalidArgumentException('The parent is invalid. You must choose the site or a page as parent.');
|
||||
}
|
||||
|
||||
return $parent;
|
||||
},
|
||||
'pages' => function () {
|
||||
switch ($this->status) {
|
||||
|
@ -151,32 +157,25 @@ return [
|
|||
$data = [];
|
||||
|
||||
foreach ($this->pages as $item) {
|
||||
$panel = $item->panel();
|
||||
$permissions = $item->permissions();
|
||||
$image = $item->panelImage($this->image);
|
||||
|
||||
// escape the default text
|
||||
// TODO: no longer needed in 3.6
|
||||
$text = $item->toString($this->text);
|
||||
if ($this->text === '{{ page.title }}') {
|
||||
$text = Escape::html($text);
|
||||
}
|
||||
|
||||
$data[] = [
|
||||
'dragText' => $panel->dragText(),
|
||||
'id' => $item->id(),
|
||||
'dragText' => $item->dragText(),
|
||||
'text' => $text,
|
||||
'info' => $item->toString($this->info ?? false),
|
||||
'image' => $panel->image($this->image, $this->layout),
|
||||
'info' => $item->toSafeString($this->info ?? false),
|
||||
'link' => $panel->url(true),
|
||||
'parent' => $item->parentId(),
|
||||
'icon' => $item->panelIcon($image),
|
||||
'image' => $image,
|
||||
'link' => $item->panelUrl(true),
|
||||
'status' => $item->status(),
|
||||
'permissions' => [
|
||||
'sort' => $permissions->can('sort'),
|
||||
'changeSlug' => $permissions->can('changeSlug'),
|
||||
'changeStatus' => $permissions->can('changeStatus'),
|
||||
'changeTitle' => $permissions->can('changeTitle')
|
||||
]
|
||||
'changeTitle' => $permissions->can('changeTitle'),
|
||||
],
|
||||
'status' => $item->status(),
|
||||
'template' => $item->intendedTemplate()->name(),
|
||||
'text' => $item->toSafeString($this->text),
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -226,8 +225,8 @@ return [
|
|||
return true;
|
||||
},
|
||||
'link' => function () {
|
||||
$modelLink = $this->model->panelUrl(true);
|
||||
$parentLink = $this->parent->panelUrl(true);
|
||||
$modelLink = $this->model->panel()->url(true);
|
||||
$parentLink = $this->parent->panel()->url(true);
|
||||
|
||||
if ($modelLink !== $parentLink) {
|
||||
return $parentLink;
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
<?php
|
||||
|
||||
$blocksRoot = __DIR__ . '/blocks';
|
||||
|
||||
return [
|
||||
// blocks
|
||||
'blocks/code' => $blocksRoot . '/code/code.php',
|
||||
'blocks/gallery' => $blocksRoot . '/gallery/gallery.php',
|
||||
'blocks/heading' => $blocksRoot . '/heading/heading.php',
|
||||
'blocks/image' => $blocksRoot . '/image/image.php',
|
||||
'blocks/list' => $blocksRoot . '/list/list.php',
|
||||
'blocks/markdown' => $blocksRoot . '/markdown/markdown.php',
|
||||
'blocks/quote' => $blocksRoot . '/quote/quote.php',
|
||||
'blocks/table' => $blocksRoot . '/table/table.php',
|
||||
'blocks/text' => $blocksRoot . '/text/text.php',
|
||||
'blocks/video' => $blocksRoot . '/video/video.php',
|
||||
];
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
use Kirby\Cms\Html;
|
||||
use Kirby\Cms\Url;
|
||||
use Kirby\Text\KirbyTag;
|
||||
use Kirby\Toolkit\F;
|
||||
use Kirby\Toolkit\Str;
|
||||
|
||||
/**
|
||||
|
@ -252,29 +250,6 @@ return [
|
|||
'width',
|
||||
],
|
||||
'html' => function ($tag) {
|
||||
// all available video tag attributes
|
||||
$availableAttrs = KirbyTag::$types[$tag->type]['attr'];
|
||||
|
||||
// global video tag options
|
||||
$attrs = $tag->kirby()->option('kirbytext.video', []);
|
||||
$options = $attrs['options'] ?? [];
|
||||
|
||||
// removes options from attributes
|
||||
if (isset($attrs['options']) === true) {
|
||||
unset($attrs['options']);
|
||||
}
|
||||
|
||||
// injects default values from global options
|
||||
// applies only defined attributes to safely update tag props
|
||||
foreach ($attrs as $key => $value) {
|
||||
if (
|
||||
in_array($key, $availableAttrs) === true &&
|
||||
(isset($tag->{$key}) === false || $tag->{$key} === null)
|
||||
) {
|
||||
$tag->{$key} = $value;
|
||||
}
|
||||
}
|
||||
|
||||
// checks and gets if poster is local file
|
||||
if (
|
||||
empty($tag->poster) === false &&
|
||||
|
@ -286,26 +261,41 @@ return [
|
|||
}
|
||||
}
|
||||
|
||||
// converts tag attributes to supported formats (listed below) to output correct html
|
||||
// booleans: autoplay, controls, loop, muted
|
||||
// strings : height, poster, preload, width
|
||||
// for ex : `autoplay` will not work if `false` is a `string` instead of a `boolean`
|
||||
$attrs = [
|
||||
'autoplay' => $autoplay = Str::toType($tag->autoplay, 'bool'),
|
||||
'controls' => Str::toType($tag->controls ?? true, 'bool'),
|
||||
'height' => $tag->height,
|
||||
'loop' => Str::toType($tag->loop, 'bool'),
|
||||
'muted' => Str::toType($tag->muted ?? $autoplay, 'bool'),
|
||||
'poster' => $tag->poster,
|
||||
'preload' => $tag->preload,
|
||||
'width' => $tag->width
|
||||
];
|
||||
|
||||
// handles local and remote video file
|
||||
if (
|
||||
// checks video is local or provider(remote)
|
||||
$isLocalVideo = (
|
||||
Str::startsWith($tag->value, 'http://') !== true &&
|
||||
Str::startsWith($tag->value, 'https://') !== true
|
||||
) {
|
||||
);
|
||||
$isProviderVideo = (
|
||||
$isLocalVideo === false &&
|
||||
(
|
||||
Str::contains($tag->value, 'youtu', true) === true ||
|
||||
Str::contains($tag->value, 'vimeo', true) === true
|
||||
)
|
||||
);
|
||||
|
||||
// default attributes for local and remote videos
|
||||
$attrs = [
|
||||
'height' => $tag->height,
|
||||
'width' => $tag->width
|
||||
];
|
||||
|
||||
// don't use attributes that iframe doesn't support
|
||||
if ($isProviderVideo === false) {
|
||||
// converts tag attributes to supported formats (listed below) to output correct html
|
||||
// booleans: autoplay, controls, loop, muted
|
||||
// strings : poster, preload
|
||||
// for ex : `autoplay` will not work if `false` is a `string` instead of a `boolean`
|
||||
$attrs['autoplay'] = $autoplay = Str::toType($tag->autoplay, 'bool');
|
||||
$attrs['controls'] = Str::toType($tag->controls ?? true, 'bool');
|
||||
$attrs['loop'] = Str::toType($tag->loop, 'bool');
|
||||
$attrs['muted'] = Str::toType($tag->muted ?? $autoplay, 'bool');
|
||||
$attrs['poster'] = $tag->poster;
|
||||
$attrs['preload'] = $tag->preload;
|
||||
}
|
||||
|
||||
// handles local and remote video file
|
||||
if ($isLocalVideo === true) {
|
||||
// handles local video file
|
||||
if ($tag->file = $tag->file($tag->value)) {
|
||||
$source = Html::tag('source', null, [
|
||||
|
@ -315,32 +305,11 @@ return [
|
|||
$video = Html::tag('video', [$source], $attrs);
|
||||
}
|
||||
} else {
|
||||
// firstly handles supported video providers as youtube, vimeo, etc
|
||||
try {
|
||||
$video = Html::video(
|
||||
$tag->value,
|
||||
$options,
|
||||
// providers only support width and height attributes
|
||||
[
|
||||
'height' => $tag->height,
|
||||
'width' => $tag->width
|
||||
]
|
||||
);
|
||||
} catch (Exception $e) {
|
||||
// if not one of the supported video providers
|
||||
// it checks if there is a valid remote video file
|
||||
$extension = F::extension($tag->value);
|
||||
$type = F::extensionToType($extension);
|
||||
$mime = F::extensionToMime($extension);
|
||||
|
||||
if ($type === 'video') {
|
||||
$source = Html::tag('source', null, [
|
||||
'src' => $tag->value,
|
||||
'type' => $mime
|
||||
]);
|
||||
$video = Html::tag('video', [$source], $attrs);
|
||||
}
|
||||
}
|
||||
$video = Html::video(
|
||||
$tag->value,
|
||||
$tag->kirby()->option('kirbytext.video.options', []),
|
||||
$attrs
|
||||
);
|
||||
}
|
||||
|
||||
return Html::figure([$video ?? ''], $tag->caption, [
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
<?php
|
||||
|
||||
// @codeCoverageIgnoreStart
|
||||
return [
|
||||
'emails/auth/login' => __DIR__ . '/templates/emails/auth/login.php',
|
||||
'emails/auth/password-reset' => __DIR__ . '/templates/emails/auth/password-reset.php'
|
||||
];
|
||||
// @codeCoverageIgnoreEnd
|
|
@ -1,8 +1,16 @@
|
|||
<?php
|
||||
|
||||
use Kirby\Toolkit\I18n;
|
||||
|
||||
/**
|
||||
* @var \Kirby\Cms\User $user
|
||||
* @var string $site
|
||||
* @var string $code
|
||||
* @var int $timeout
|
||||
*/
|
||||
echo I18n::template('login.email.login.body', null, compact('user', 'code', 'timeout'), $user->language());
|
||||
echo I18n::template(
|
||||
'login.email.login.body',
|
||||
null,
|
||||
compact('user', 'site', 'code', 'timeout'),
|
||||
$user->language()
|
||||
);
|
||||
|
|
|
@ -1,8 +1,16 @@
|
|||
<?php
|
||||
|
||||
use Kirby\Toolkit\I18n;
|
||||
|
||||
/**
|
||||
* @var \Kirby\Cms\User $user
|
||||
* @var string $site
|
||||
* @var string $code
|
||||
* @var int $timeout
|
||||
*/
|
||||
echo I18n::template('login.email.password-reset.body', null, compact('user', 'code', 'timeout'), $user->language());
|
||||
echo I18n::template(
|
||||
'login.email.password-reset.body',
|
||||
null,
|
||||
compact('user', 'site', 'code', 'timeout'),
|
||||
$user->language()
|
||||
);
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
<?php
|
||||
|
||||
use Kirby\Cms\Url;
|
||||
|
||||
return [
|
||||
'index' => function () {
|
||||
return Url::index();
|
||||
},
|
||||
'base' => function (array $urls) {
|
||||
return rtrim($urls['index'], '/');
|
||||
},
|
||||
'current' => function (array $urls) {
|
||||
$path = trim($this->path(), '/');
|
||||
|
||||
if (empty($path) === true) {
|
||||
return $urls['index'];
|
||||
} else {
|
||||
return $urls['base'] . '/' . $path;
|
||||
}
|
||||
},
|
||||
'assets' => function (array $urls) {
|
||||
return $urls['base'] . '/assets';
|
||||
},
|
||||
'api' => function (array $urls) {
|
||||
return $urls['base'] . '/' . ($this->options['api']['slug'] ?? 'api');
|
||||
},
|
||||
'media' => function (array $urls) {
|
||||
return $urls['base'] . '/media';
|
||||
},
|
||||
'panel' => function (array $urls) {
|
||||
return $urls['base'] . '/' . ($this->options['panel']['slug'] ?? 'panel');
|
||||
}
|
||||
];
|
Loading…
Add table
Add a link
Reference in a new issue