Upgrade to 3.2.0

This commit is contained in:
Bastian Allgeier
2019-06-25 09:56:08 +02:00
parent 9e18cf635d
commit 9c89153d35
296 changed files with 14408 additions and 2504 deletions

View File

@@ -22,6 +22,9 @@ return [
'name' => function (Language $language) {
return $language->name();
},
'rules' => function (Language $language) {
return $language->rules();
},
'url' => function (Language $language) {
return $language->url();
},
@@ -32,6 +35,8 @@ return [
'code',
'default',
'name',
'rules',
'direction'
]
]
];

View File

@@ -35,6 +35,9 @@ return [
'hasDrafts' => function (Page $page) {
return $page->hasDrafts();
},
'hasFiles' => function (Page $page) {
return $page->hasFiles();
},
'id' => function (Page $page) {
return $page->id();
},
@@ -125,7 +128,6 @@ return [
'id',
'blueprint',
'content',
'errors',
'status',
'options',
'next' => ['id', 'slug', 'title'],

View File

@@ -29,6 +29,9 @@ return [
'options' => function (Site $site) {
return $site->permissions()->toArray();
},
'previewUrl' => function (Site $site) {
return $site->previewUrl();
},
'title' => function (Site $site) {
return $site->title()->value();
},
@@ -53,6 +56,7 @@ return [
'blueprint',
'content',
'options',
'previewUrl',
'url'
],
'selector' => [

View File

@@ -1,12 +1,16 @@
<?php
use Kirby\Cms\System;
use Kirby\Toolkit\Str;
/**
* System
*/
return [
'fields' => [
'ascii' => function () {
return Str::$ascii;
},
'isOk' => function (System $system) {
return $system->isOk();
},
@@ -38,6 +42,9 @@ return [
return $this->site()->title()->value();
}
},
'slugs' => function () {
return Str::$language;
},
'title' => function () {
return $this->site()->title()->value();
},
@@ -82,6 +89,7 @@ return [
'requirements'
],
'panel' => [
'ascii',
'breadcrumbTitle',
'isOk',
'isInstalled',
@@ -91,10 +99,11 @@ return [
'license',
'multilang',
'requirements',
'slugs',
'title',
'translation',
'user' => 'auth',
'version'
'version'
]
],
];

View File

@@ -11,6 +11,7 @@ return function ($kirby) {
include __DIR__ . '/routes/site.php',
include __DIR__ . '/routes/users.php',
include __DIR__ . '/routes/files.php',
include __DIR__ . '/routes/lock.php',
include __DIR__ . '/routes/system.php',
include __DIR__ . '/routes/translations.php'
);

View File

@@ -43,8 +43,14 @@ return [
'user' => $this->resolve($user)->view('auth')->toArray()
];
}
throw new NotFoundException(['key' => 'user.undefined']);
} catch (Throwable $e) {
// catch any kind of login error
if ($this->kirby()->option('debug') === true) {
throw $e;
} else {
// catch any kind of login error
}
}
throw new InvalidArgumentException('Invalid email or password');

View File

@@ -0,0 +1,52 @@
<?php
/**
* Content Lock Routes
*/
return [
[
'pattern' => '(:all)/lock',
'method' => 'GET',
'action' => function (string $path) {
return $this->parent($path)->lock()->get();
}
],
[
'pattern' => '(:all)/lock',
'method' => 'PATCH',
'action' => function (string $path) {
return $this->parent($path)->lock()->create();
}
],
[
'pattern' => '(:all)/lock',
'method' => 'DELETE',
'action' => function (string $path) {
return $this->parent($path)->lock()->remove();
}
],
[
'pattern' => '(:all)/unlock',
'method' => 'GET',
'action' => function (string $path) {
return [
'isUnlocked' => $this->parent($path)->lock()->isUnlocked()
];
}
],
[
'pattern' => '(:all)/unlock',
'method' => 'PATCH',
'action' => function (string $path) {
return $this->parent($path)->lock()->unlock();
}
],
[
'pattern' => '(:all)/unlock',
'method' => 'DELETE',
'action' => function (string $path) {
return $this->parent($path)->lock()->resolve();
}
],
];

View File

@@ -62,6 +62,16 @@ return [
}
}
],
[
'pattern' => 'pages/(:any)/duplicate',
'method' => 'POST',
'action' => function (string $id) {
return $this->page($id)->duplicate($this->requestBody('slug'), [
'children' => $this->requestBody('children'),
'files' => $this->requestBody('files'),
]);
}
],
[
'pattern' => 'pages/(:any)/slug',
'method' => 'PATCH',

View File

@@ -13,6 +13,7 @@ use Kirby\Exception\NotFoundException;
use Kirby\Image\Darkroom;
use Kirby\Text\Markdown;
use Kirby\Text\SmartyPants;
use Kirby\Toolkit\A;
use Kirby\Toolkit\F;
use Kirby\Toolkit\Tpl as Snippet;
@@ -53,20 +54,16 @@ return [
return $file;
}
// pre-calculate all thumb attributes
$darkroom = Darkroom::factory(option('thumbs.driver', 'gd'), option('thumbs', []));
$attributes = $darkroom->preprocess($file->root(), $options);
// create url and root
$mediaRoot = dirname($file->mediaRoot());
$dst = $mediaRoot . '/{{ name }}{{ attributes }}.{{ extension }}';
$thumbRoot = (new Filename($file->root(), $dst, $attributes))->toString();
$thumbRoot = (new Filename($file->root(), $dst, $options))->toString();
$thumbName = basename($thumbRoot);
$job = $mediaRoot . '/.jobs/' . $thumbName . '.json';
if (file_exists($thumbRoot) === false) {
try {
Data::write($job, array_merge($attributes, [
Data::write($job, array_merge($options, [
'filename' => $file->filename()
]));
} catch (Throwable $e) {
@@ -104,8 +101,14 @@ return [
*/
'markdown' => function (App $kirby, string $text = null, array $options = [], bool $inline = false): string {
static $markdown;
static $config;
$markdown = $markdown ?? new Markdown($options);
// if the config options have changed or the component is called for the first time,
// (re-)initialize the parser object
if ($config !== $options) {
$markdown = new Markdown($options);
$config = $options;
}
return $markdown->parse($text, $inline);
},
@@ -120,8 +123,14 @@ return [
*/
'smartypants' => function (App $kirby, string $text = null, array $options = []): string {
static $smartypants;
static $config;
$smartypants = $smartypants ?? new Smartypants($options);
// if the config options have changed or the component is called for the first time,
// (re-)initialize the parser object
if ($config !== $options) {
$smartypants = new Smartypants($options);
$config = $options;
}
return $smartypants->parse($text);
},
@@ -130,15 +139,23 @@ return [
* Add your own snippet loader
*
* @param Kirby\Cms\App $kirby Kirby instance
* @param string $name Snippet name
* @param string|array $name Snippet name
* @param array $data Data array for the snippet
* @return string|null
*/
'snippet' => function (App $kirby, string $name, array $data = []): ?string {
$file = $kirby->root('snippets') . '/' . $name . '.php';
'snippet' => function (App $kirby, $name, array $data = []): ?string {
$snippets = A::wrap($name);
if (file_exists($file) === false) {
$file = $kirby->extensions('snippets')[$name] ?? null;
foreach ($snippets as $name) {
$file = $kirby->root('snippets') . '/' . $name . '.php';
if (file_exists($file) === false) {
$file = $kirby->extensions('snippets')[$name] ?? null;
}
if ($file) {
break;
}
}
return Snippet::load($file, $data);
@@ -171,7 +188,7 @@ return [
$options = $darkroom->preprocess($src, $options);
$root = (new Filename($src, $dst, $options))->toString();
F::copy($src, $root);
F::copy($src, $root, true);
$darkroom->process($root, $options);
return $root;

View File

@@ -43,9 +43,6 @@ return [
},
],
'computed' => [
'options' => function (): array {
return $this->getOptions();
},
'default' => function () {
return $this->sanitizeOptions($this->default);
},

View File

@@ -3,7 +3,12 @@
use Kirby\Toolkit\A;
return [
'mixins' => ['min'],
'mixins' => [
'picker',
'filepicker',
'min',
'upload'
],
'props' => [
/**
* Unset inherited props
@@ -21,27 +26,6 @@ return [
return $default;
},
/**
* The placeholder text if no pages have been selected yet
*/
'empty' => function ($empty = null) {
return I18n::translate($empty, $empty);
},
/**
* Image settings for each item
*/
'image' => function (array $image = null) {
return $image ?? [];
},
/**
* Info text
*/
'info' => function (string $info = null) {
return $info;
},
/**
* Changes the layout of the selected files. Available layouts: `list`, `cards`
*/
@@ -49,48 +33,13 @@ return [
return $layout;
},
/**
* Minimum number of required files
*/
'min' => function (int $min = null) {
return $min;
},
/**
* Maximum number of allowed files
*/
'max' => function (int $max = null) {
return $max;
},
/**
* If false, only a single file can be selected
*/
'multiple' => function (bool $multiple = true) {
return $multiple;
},
/**
* Query for the files to be included
*/
'query' => function (string $query = null) {
return $query;
},
/**
* Layout size for cards: `tiny`, `small`, `medium`, `large` or `huge`
*/
'size' => function (string $size = null) {
'size' => function (string $size = 'auto') {
return $size;
},
/**
* Main text
*/
'text' => function (string $text = '{{ file.filename }}') {
return $text;
},
'value' => function ($value = null) {
return $value;
}
@@ -118,38 +67,15 @@ return [
],
'methods' => [
'fileResponse' => function ($file) {
if ($this->layout === 'list') {
$thumb = [
'width' => 100,
'height' => 100
];
} else {
$thumb = [
'width' => 400,
'height' => 400
];
}
$image = $file->panelImage($this->image, $thumb);
$model = $this->model();
$uuid = $file->parent() === $model ? $file->filename() : $file->id();
return [
'filename' => $file->filename(),
'text' => $file->toString($this->text),
'link' => $file->panelUrl(true),
'id' => $file->id(),
'uuid' => $uuid,
'url' => $file->url(),
'info' => $file->toString($this->info ?? false),
'image' => $image,
'icon' => $file->panelIcon($image),
'type' => $file->type(),
];
return $file->panelPickerData([
'image' => $this->image,
'info' => $this->info ?? false,
'model' => $this->model(),
'text' => $this->text,
]);
},
'toFiles' => function ($value = null) {
$files = [];
$kirby = kirby();
foreach (Yaml::decode($value) as $id) {
if (is_array($id) === true) {
@@ -168,16 +94,32 @@ return [
return [
[
'pattern' => '/',
'action' => function () {
'action' => function () {
$field = $this->field();
$files = $field->model()->query($field->query(), 'Kirby\Cms\Files');
$data = [];
foreach ($files as $index => $file) {
$data[] = $field->fileResponse($file);
}
return $field->filepicker([
'query' => $field->query(),
'image' => $field->image(),
'info' => $field->info(),
'text' => $field->text()
]);
}
],
[
'pattern' => 'upload',
'method' => 'POST',
'action' => function () {
$field = $this->field();
$uploads = $field->uploads();
return $data;
return $field->upload($this, $uploads, function ($file) use ($field) {
return $file->panelPickerData([
'image' => $field->image(),
'info' => $field->info(),
'model' => $field->model(),
'text' => $field->text(),
]);
});
}
]
];

View File

@@ -0,0 +1,40 @@
<?php
return [
'methods' => [
'filepicker' => function (array $params = []) {
// fetch the parent model
$model = $this->model();
// find the right default query
if (empty($params['query']) === false) {
$query = $params['query'];
} elseif (is_a($model, 'Kirby\Cms\File') === true) {
$query = 'file.siblings';
} else {
$query = $model::CLASS_ALIAS . '.files';
}
// fetch all files for the picker
$files = $model->query($query, 'Kirby\Cms\Files');
$data = [];
// prepare the response for each file
foreach ($files as $index => $file) {
if (empty($params['map']) === false) {
$data[] = $params['map']($file);
} else {
$data[] = $file->panelPickerData([
'image' => $params['image'] ?? [],
'info' => $params['info'] ?? false,
'model' => $model,
'text' => $params['text'] ?? '{{ file.filename }}',
]);
}
}
return $data;
}
]
];

View File

@@ -23,6 +23,11 @@ return [
return $query;
},
],
'computed' => [
'options' => function (): array {
return $this->getOptions();
}
],
'methods' => [
'getOptions' => function () {
return Options::factory(

View File

@@ -0,0 +1,49 @@
<?php
return [
'methods' => [
'pagepicker' => function (array $params = []) {
$query = $params['query'] ?? null;
$model = $this->model();
$site = $this->kirby()->site();
if ($query) {
$pages = $model->query($query, 'Kirby\Cms\Pages');
$self = null;
} else {
if (!$parent = $site->find($params['parent'] ?? null)) {
$parent = $site;
}
$pages = $parent->children();
$self = [
'id' => $parent->id() == '' ? null : $parent->id(),
'title' => $parent->title()->value(),
'parent' => is_a($parent->parent(), Page::class) === true ? $parent->parent()->id() : null,
];
}
$children = [];
foreach ($pages as $index => $page) {
if ($page->isReadable() === true) {
if (empty($params['map']) === false) {
$children[] = $params['map']($page);
} else {
$children[] = $page->panelPickerData([
'image' => $params['image'] ?? [],
'info' => $params['info'] ?? false,
'model' => $model,
'text' => $params['text'] ?? null,
]);
}
}
}
return [
'model' => $self,
'pages' => $children
];
}
]
];

View File

@@ -0,0 +1,63 @@
<?php
return [
'props' => [
/**
* The placeholder text if none have been selected yet
*/
'empty' => function ($empty = null) {
return I18n::translate($empty, $empty);
},
/**
* Image settings for each item
*/
'image' => function (array $image = null) {
return $image ?? [];
},
/**
* Info text for each item
*/
'info' => function (string $info = null) {
return $info;
},
/**
* The minimum number of required selected
*/
'min' => function (int $min = null) {
return $min;
},
/**
* The maximum number of allowed selected
*/
'max' => function (int $max = null) {
return $max;
},
/**
* If `false`, only a single one can be selected
*/
'multiple' => function (bool $multiple = true) {
return $multiple;
},
/**
* Query for the items to be included in the picker
*/
'query' => function (string $query = null) {
return $query;
},
/**
* Main text for each item
*/
'text' => function (string $text = '{{ file.filename }}') {
return $text;
},
],
];

View File

@@ -0,0 +1,57 @@
<?php
use Kirby\Cms\Api;
return [
'props' => [
/**
* Sets the upload options for linked files
*/
'uploads' => function ($uploads = []) {
if ($uploads === false) {
return false;
}
if (is_string($uploads) === true) {
return ['template' => $uploads];
}
if (is_array($uploads) === false) {
$uploads = [];
}
return $uploads;
},
],
'methods' => [
'upload' => function (Api $api, $params, Closure $map) {
if ($params === false) {
throw new Exception('Uploads are disabled for this field');
}
if ($parentQuery = ($params['parent'] ?? null)) {
$parent = $this->model()->query($parentQuery);
} else {
$parent = $this->model();
}
if (is_a($parent, 'Kirby\Cms\File') === true) {
$parent = $parent->parent();
}
return $api->upload(function ($source, $filename) use ($parent, $params, $map) {
$file = $parent->createFile([
'source' => $source,
'template' => $params['template'] ?? null,
'filename' => $filename,
]);
if (is_a($file, 'Kirby\Cms\File') === false) {
throw new Exception('The file could not be uploaded');
}
return $map($file);
});
}
]
];

View File

@@ -0,0 +1,44 @@
<?php
return [
'methods' => [
'userpicker' => function (array $params = []) {
// fetch the parent model
$model = $this->model();
// find the right default query
if (empty($params['query']) === false) {
$query = $params['query'];
} elseif (is_a($model, 'Kirby\Cms\User') === true) {
$query = 'user.siblings';
} else {
$query = 'kirby.users';
}
// fetch all users for the picker
$users = $model->query($query, 'Kirby\Cms\Users');
$data = [];
if (!$users) {
return [];
}
// prepare the response for each user
foreach ($users->sortBy('username', 'asc') as $index => $user) {
if (empty($params['map']) === false) {
$data[] = $params['map']($user);
} else {
$data[] = $user->panelPickerData([
'image' => $params['image'] ?? [],
'info' => $params['info'] ?? false,
'model' => $model,
'text' => $params['text'] ?? '{{ user.username }}',
]);
}
}
return $data;
}
]
];

View File

@@ -4,7 +4,7 @@ use Kirby\Toolkit\A;
use Kirby\Toolkit\I18n;
return [
'mixins' => ['min'],
'mixins' => ['min', 'pagepicker', 'picker'],
'props' => [
/**
* Unset inherited props
@@ -22,13 +22,6 @@ return [
return $this->toPages($default);
},
/**
* The placeholder text if no pages have been selected yet
*/
'empty' => function ($empty = null) {
return I18n::translate($empty, $empty);
},
/**
* Image settings for each item
*/
@@ -37,7 +30,7 @@ return [
},
/**
* Info text
* Info text for each item
*/
'info' => function (string $info = null) {
return $info;
@@ -50,27 +43,6 @@ return [
return $layout;
},
/**
* The minimum number of required selected pages
*/
'min' => function (int $min = null) {
return $min;
},
/**
* The maximum number of allowed selected pages
*/
'max' => function (int $max = null) {
return $max;
},
/**
* If `false`, only a single page can be selected
*/
'multiple' => function (bool $multiple = true) {
return $multiple;
},
/**
* Optional query to select a specific set of pages
*/
@@ -81,12 +53,12 @@ return [
/**
* Layout size for cards: `tiny`, `small`, `medium`, `large` or `huge`
*/
'size' => function (string $size = null) {
'size' => function (string $size = 'auto') {
return $size;
},
/**
* Main text
* Main text for each item
*/
'text' => function (string $text = null) {
return $text;
@@ -98,30 +70,11 @@ return [
],
'methods' => [
'pageResponse' => function ($page) {
if ($this->layout === 'list') {
$thumb = [
'width' => 100,
'height' => 100
];
} else {
$thumb = [
'width' => 400,
'height' => 400
];
}
$image = $page->panelImage($this->image, $thumb);
$model = $this->model();
return [
'text' => $page->toString($this->text ?? '{{ page.title }}'),
'link' => $page->panelUrl(true),
'id' => $page->id(),
'info' => $page->toString($this->info ?? false),
'image' => $image,
'icon' => $page->panelIcon($image),
'hasChildren' => $page->hasChildren(),
];
return $page->panelPickerData([
'image' => $this->image,
'info' => $this->info,
'text' => $this->text,
]);
},
'toPages' => function ($value = null) {
$pages = [];
@@ -146,35 +99,14 @@ return [
'pattern' => '/',
'action' => function () {
$field = $this->field();
$query = $field->query();
if ($query) {
$pages = $field->model()->query($query, 'Kirby\Cms\Pages');
$model = null;
} else {
if (!$parent = $this->site()->find($this->requestQuery('parent'))) {
$parent = $this->site();
}
$pages = $parent->children();
$model = [
'id' => $parent->id() == '' ? null : $parent->id(),
'title' => $parent->title()->value()
];
}
$children = [];
foreach ($pages as $index => $page) {
if ($page->isReadable() === true) {
$children[] = $field->pageResponse($page);
}
}
return [
'model' => $model,
'pages' => $children
];
return $field->pagepicker([
'image' => $field->image(),
'info' => $field->info(),
'parent' => $this->requestQuery('parent'),
'query' => $field->query(),
'text' => $field->text()
]);
}
]
];

View File

@@ -19,9 +19,6 @@ return [
},
],
'computed' => [
'options' => function (): array {
return $this->getOptions();
},
'default' => function () {
return $this->sanitizeOption($this->default);
},

View File

@@ -14,5 +14,11 @@ return [
'icon' => function (string $icon = null) {
return $icon;
},
/**
* Custom placeholder string for empty option.
*/
'placeholder' => function (string $placeholder = '—') {
return $placeholder;
},
]
];

View File

@@ -43,9 +43,6 @@ return [
},
],
'computed' => [
'options' => function () {
return $this->getOptions();
},
'default' => function (): array {
return $this->toTags($this->default);
},
@@ -55,6 +52,10 @@ return [
],
'methods' => [
'toTags' => function ($value) {
if (is_null($value) === true) {
return [];
}
$options = $this->options();
// transform into value-text objects

View File

@@ -1,6 +1,7 @@
<?php
return [
'mixins' => ['filepicker', 'upload'],
'props' => [
/**
* Unset inherited props
@@ -44,6 +45,13 @@ return [
return $files;
},
/**
* Sets the font family (sans or monospace)
*/
'font' => function (string $font = null) {
return $font === 'monospace' ? 'monospace' : 'sans-serif';
},
/**
* Maximum number of allowed characters
*/
@@ -65,24 +73,6 @@ return [
return $size;
},
/**
* Sets the upload options for linked files
*/
'uploads' => function ($uploads = []) {
if ($uploads === false) {
return false;
}
if (is_string($uploads) === true) {
return ['template' => $uploads];
}
if (is_array($uploads) === false) {
$uploads = [];
}
return $uploads;
},
'value' => function (string $value = null) {
return trim($value);
@@ -93,66 +83,13 @@ return [
[
'pattern' => 'files',
'action' => function () {
$field = $this->field();
$model = $field->model();
if (empty($filed->files['query']) === false) {
$query = $filed->files['query'];
} elseif (is_a($model, 'Kirby\Cms\File') === true) {
$query = 'file.siblings';
} else {
$query = $model::CLASS_ALIAS . '.files';
}
$files = $model->query($query, 'Kirby\Cms\Files');
$data = [];
foreach ($files as $index => $file) {
$image = $file->panelImage($field->files['image'] ?? []);
$model = $field->model();
$data[] = [
'filename' => $file->filename(),
'dragText' => $file->dragText(),
'image' => $image,
'icon' => $file->panelIcon($image)
];
}
return $data;
return $this->field()->filepicker($this->field()->files());
}
],
[
'pattern' => 'upload',
'action' => function () {
$field = $this->field();
$uploads = $field->uploads();
if ($uploads === false) {
throw new Exception('Uploads are disabled for this field');
}
if ($parentQuery = ($uploads['parent'] ?? null)) {
$parent = $field->model()->query($parentQuery);
} else {
$parent = $field->model();
}
if (is_a($parent, 'Kirby\Cms\File') === true) {
$parent = $parent->parent();
}
return $this->upload(function ($source, $filename) use ($field, $parent, $uploads) {
$file = $parent->createFile([
'source' => $source,
'template' => $uploads['template'] ?? null,
'filename' => $filename,
]);
if (is_a($file, 'Kirby\Cms\File') === false) {
throw new Exception('The file could not be uploaded');
}
return $this->field()->upload($this, $this->field()->uploads(), function ($file) {
return [
'filename' => $file->filename(),
'dragText' => $file->dragText(),

View File

@@ -1,7 +1,7 @@
<?php
return [
'mixins' => ['min', 'selector'],
'mixins' => ['min', 'picker', 'userpicker'],
'props' => [
/**
* Unset inherited props
@@ -29,56 +29,17 @@ return [
return $this->toUsers($default);
},
/**
* The placeholder text if none have been selected yet
*/
'empty' => function ($empty = null) {
return I18n::translate($empty, $empty);
},
/**
* The minimum number of required selected
*/
'min' => function (int $min = null) {
return $min;
},
/**
* The maximum number of allowed selected
*/
'max' => function (int $max = null) {
return $max;
},
/**
* If `false`, only a single one can be selected
*/
'multiple' => function (bool $multiple = true) {
return $multiple;
},
'value' => function ($value = null) {
return $this->toUsers($value);
},
],
'methods' => [
'userResponse' => function ($user) {
$avatar = function ($user) {
if ($avatar = $user->avatar()) {
return [
'url' => $avatar->crop(512)->url()
];
}
return null;
};
return [
'username' => $user->username(),
'id' => $user->id(),
'email' => $user->email(),
'avatar' => $avatar($user)
];
return $user->panelPickerData([
'info' => $this->info,
'image' => $this->image,
'text' => $this->text,
]);
},
'toUsers' => function ($value = null) {
$users = [];
@@ -97,6 +58,23 @@ return [
return $users;
}
],
'api' => function () {
return [
[
'pattern' => '/',
'action' => function () {
$field = $this->field();
return $field->userpicker([
'query' => $field->query(),
'image' => $field->image(),
'info' => $field->info(),
'text' => $field->text()
]);
}
]
];
},
'save' => function ($value = null) {
return A::pluck($value, 'email');
},

View File

@@ -16,7 +16,7 @@ use Kirby\Toolkit\View;
* Helper to create an asset object
*
* @param string $path
* @return Asset
* @return Kirby\Cms\Asset
*/
function asset(string $path)
{
@@ -44,7 +44,7 @@ function attr(array $attr = null, $before = null, $after = null)
* Returns the result of a collection by name
*
* @param string $name
* @return Collection|null
* @return Kirby\Cms\Collection|null
*/
function collection(string $name)
{
@@ -246,7 +246,7 @@ function html(string $string = null, bool $keepTags = false)
* <?= image('some/page/myimage.jpg') ?>
*
* @param string $path
* @return File|null
* @return Kirby\Cms\File|null
*/
function image(string $path = null)
{
@@ -382,9 +382,9 @@ function js($url, $options = null)
/**
* Returns the Kirby object in any situation
*
* @return App
* @return Kirby\Cms\App
*/
function kirby(): App
function kirby()
{
return App::instance();
}
@@ -527,7 +527,7 @@ function option(string $key, $default = null)
* id or the current page when no id is specified
*
* @param string|array ...$id
* @return Page|null
* @return Kirby\Cms\Page|null
*/
function page(...$id)
{
@@ -542,7 +542,7 @@ function page(...$id)
* Helper to build page collections
*
* @param string|array ...$id
* @return Pages
* @return Kirby\Cms\Pages
*/
function pages(...$id)
{
@@ -616,7 +616,7 @@ function timestamp(string $date = null, int $step = null): ?string
/**
* Returns the currrent site object
*
* @return Site
* @return Kirby\Cms\Site
*/
function site()
{
@@ -669,12 +669,12 @@ function smartypants(string $text = null): string
/**
* Embeds a snippet from the snippet folder
*
* @param string $name
* @param string|array $name
* @param array|object $data
* @param boolean $return
* @return string
*/
function snippet(string $name, $data = [], bool $return = false)
function snippet($name, $data = [], bool $return = false)
{
if (is_object($data) === true) {
$data = ['item' => $data];
@@ -742,6 +742,21 @@ function tc($key, int $count)
return I18n::translateCount($key, $count);
}
/**
* Translate by key and then replace
* placeholders in the text
*
* @param string $key
* @param string $fallback
* @param array $replace
* @param string $locale
* @return string
*/
function tt(string $key, $fallback = null, array $replace = null, string $locale = null)
{
return I18n::template($key, $fallback, $replace, $locale);
}
/**
* Builds a Twitter link
*

View File

@@ -25,7 +25,7 @@ return function (App $app) {
/**
* Converts the field value into a proper boolean and inverts it
*
* @param Field $field
* @param Kirby\Cms\Field $field
* @return boolean
*/
'isFalse' => function (Field $field): bool {
@@ -35,7 +35,7 @@ return function (App $app) {
/**
* Converts the field value into a proper boolean
*
* @param Field $field
* @param Kirby\Cms\Field $field
* @return boolean
*/
'isTrue' => function (Field $field): bool {
@@ -58,7 +58,7 @@ return function (App $app) {
/**
* Parses the field value with the given method
*
* @param Field $field
* @param Kirby\Cms\Field $field
* @param string $method [',', 'yaml', 'json']
* @return array
*/
@@ -76,7 +76,7 @@ return function (App $app) {
/**
* Converts the field value into a proper boolean
*
* @param Field $field
* @param Kirby\Cms\Field $field
* @param bool $default Default value if the field is empty
* @return bool
*/
@@ -88,27 +88,30 @@ return function (App $app) {
/**
* Converts the field value to a timestamp or a formatted date
*
* @param Field $field
* @param string $format PHP date formatting string
* @param Kirby\Cms\Field $field
* @param string|null $format PHP date formatting string
* @param string|null $fallback Fallback string for `strtotime` (since 3.2)
* @return string|int
*/
'toDate' => function (Field $field, string $format = null) use ($app) {
if (empty($field->value) === true) {
'toDate' => function (Field $field, string $format = null, string $fallback = null) use ($app) {
if (empty($field->value) === true && $fallback === null) {
return null;
}
$time = empty($field->value) === true ? strtotime($fallback) : $field->toTimestamp();
if ($format === null) {
return $field->toTimestamp();
return $time;
}
return $app->option('date.handler', 'date')($format, $field->toTimestamp());
return $app->option('date.handler', 'date')($format, $time);
},
/**
* Returns a file object from a filename in the field
*
* @param Field $field
* @return File|null
* @param Kirby\Cms\Field $field
* @return Kirby\Cms\File|null
*/
'toFile' => function (Field $field) {
return $field->toFiles()->first();
@@ -117,7 +120,9 @@ return function (App $app) {
/**
* Returns a file collection from a yaml list of filenames in the field
*
* @return Files
* @param Kirby\Cms\Field $field
* @param string $separator
* @return Kirby\Cms\Files
*/
'toFiles' => function (Field $field, string $separator = 'yaml') {
$parent = $field->parent();
@@ -135,7 +140,7 @@ return function (App $app) {
/**
* Converts the field value into a proper float
*
* @param Field $field
* @param Kirby\Cms\Field $field
* @param float $default Default value if the field is empty
* @return float
*/
@@ -147,7 +152,7 @@ return function (App $app) {
/**
* Converts the field value into a proper integer
*
* @param Field $field
* @param Kirby\Cms\Field $field
* @param int $default Default value if the field is empty
* @return int
*/
@@ -159,7 +164,7 @@ return function (App $app) {
/**
* Wraps a link tag around the field value. The field value is used as the link text
*
* @param Field $field
* @param Kirby\Cms\Field $field
* @param mixed $attr1 Can be an optional Url. If no Url is set, the Url of the Page, File or Site will be used. Can also be an array of link attributes
* @param mixed $attr2 If `$attr1` is used to set the Url, you can use `$attr2` to pass an array of additional attributes.
* @return string
@@ -183,8 +188,8 @@ return function (App $app) {
/**
* Returns a page object from a page id in the field
*
* @param Field $field
* @return Page|null
* @param Kirby\Cms\Field $field
* @return Kirby\Cms\Page|null
*/
'toPage' => function (Field $field) use ($app) {
return $field->toPages()->first();
@@ -193,8 +198,9 @@ return function (App $app) {
/**
* Returns a pages collection from a yaml list of page ids in the field
*
* @param Kirby\Cms\Field $field
* @param string $separator Can be any other separator to split the field value by
* @return Pages
* @return Kirby\Cms\Pages
*/
'toPages' => function (Field $field, string $separator = 'yaml') use ($app) {
return $app->site()->find(false, false, ...$field->toData($separator));
@@ -202,6 +208,9 @@ return function (App $app) {
/**
* Converts a yaml field to a Structure object
*
* @param Kirby\Cms\Field $field
* @return Kirby\Cms\Structure
*/
'toStructure' => function (Field $field) {
return new Structure(Yaml::decode($field->value), $field->parent());
@@ -209,22 +218,29 @@ return function (App $app) {
/**
* Converts the field value to a Unix timestamp
*
* @param Kirby\Cms\Field $field
* @return int
*/
'toTimestamp' => function (Field $field) {
'toTimestamp' => function (Field $field): int {
return strtotime($field->value);
},
/**
* Turns the field value into an absolute Url
*
* @param Kirby\Cms\Field $field
* @return string
*/
'toUrl' => function (Field $field) {
'toUrl' => function (Field $field): string {
return Url::to($field->value);
},
/**
* Converts a user email address to a user object
*
* @return User|null
* @param Kirby\Cms\Field $field
* @return Kirby\Cms\User|null
*/
'toUser' => function (Field $field) use ($app) {
return $field->toUsers()->first();
@@ -233,7 +249,9 @@ return function (App $app) {
/**
* Returns a users collection from a yaml list of user email addresses in the field
*
* @return Users
* @param Kirby\Cms\Field $field
* @param string $separator
* @return Kirby\Cms\Users
*/
'toUsers' => function (Field $field, string $separator = 'yaml') use ($app) {
return $app->users()->find(false, false, ...$field->toData($separator));
@@ -261,7 +279,7 @@ return function (App $app) {
* Escapes the field value to be safely used in HTML
* templates without the risk of XSS attacks
*
* @param Field $field
* @param Kirby\Cms\Field $field
* @param string $context html, attr, js or css
*/
'escape' => function (Field $field, string $context = 'html') {
@@ -272,6 +290,12 @@ return function (App $app) {
/**
* Creates an excerpt of the field value without html
* or any other formatting.
*
* @param Kirby\Cms\Field $field
* @param int $cahrs
* @param boolean $strip
* @param string $rep
* @return Kirby\Cms\Field
*/
'excerpt' => function (Field $field, int $chars = 0, bool $strip = true, string $rep = '…') {
$field->value = Str::excerpt($field->kirbytext()->value(), $chars, $strip, $rep);
@@ -280,6 +304,9 @@ return function (App $app) {
/**
* Converts the field content to valid HTML
*
* @param Kirby\Cms\Field $field
* @return Kirby\Cms\Field
*/
'html' => function (Field $field) {
$field->value = htmlentities($field->value, ENT_COMPAT, 'utf-8');
@@ -288,6 +315,9 @@ return function (App $app) {
/**
* Converts the field content from Markdown/Kirbytext to valid HTML
*
* @param Kirby\Cms\Field $field
* @return Kirby\Cms\Field
*/
'kirbytext' => function (Field $field) use ($app) {
$field->value = $app->kirbytext($field->value, [
@@ -299,8 +329,12 @@ return function (App $app) {
},
/**
* Converts the field content from inline Markdown/Kirbytext to valid HTML
* Converts the field content from inline Markdown/Kirbytext
* to valid HTML
* @since 3.1.0
*
* @param Kirby\Cms\Field $field
* @return Kirby\Cms\Field
*/
'kirbytextinline' => function (Field $field) use ($app) {
$field->value = $app->kirbytext($field->value, [
@@ -313,6 +347,9 @@ return function (App $app) {
/**
* Parses all KirbyTags without also parsing Markdown
*
* @param Kirby\Cms\Field $field
* @return Kirby\Cms\Field
*/
'kirbytags' => function (Field $field) use ($app) {
$field->value = $app->kirbytags($field->value, [
@@ -325,6 +362,9 @@ return function (App $app) {
/**
* Converts the field content to lowercase
*
* @param Kirby\Cms\Field $field
* @return Kirby\Cms\Field
*/
'lower' => function (Field $field) {
$field->value = Str::lower($field->value);
@@ -333,6 +373,9 @@ return function (App $app) {
/**
* Converts markdown to valid HTML
*
* @param Kirby\Cms\Field $field
* @return Kirby\Cms\Field
*/
'markdown' => function (Field $field) use ($app) {
$field->value = $app->markdown($field->value);
@@ -341,6 +384,9 @@ return function (App $app) {
/**
* Converts the field content to valid XML
*
* @param Kirby\Cms\Field $field
* @return Kirby\Cms\Field
*/
'xml' => function (Field $field) {
$field->value = Xml::encode($field->value);
@@ -348,11 +394,13 @@ return function (App $app) {
},
/**
* Cuts the string after the given length and adds "…" if it is longer
* Cuts the string after the given length and
* adds "…" if it is longer
*
* @param Kirby\Cms\Field $field
* @param int $length The number of characters in the string
* @param string $appendix An optional replacement for the missing rest
* @return Field
* @return Kirby\Cms\Field
*/
'short' => function (Field $field, int $length, string $appendix = '…') {
$field->value = Str::short($field->value, $length, $appendix);
@@ -361,6 +409,9 @@ return function (App $app) {
/**
* Converts the field content to a slug
*
* @param Kirby\Cms\Field $field
* @return Kirby\cms\Field
*/
'slug' => function (Field $field) {
$field->value = Str::slug($field->value);
@@ -369,6 +420,9 @@ return function (App $app) {
/**
* Applies SmartyPants to the field
*
* @param Kirby\Cms\Field $field
* @return Kirby\cms\Field
*/
'smartypants' => function (Field $field) use ($app) {
$field->value = $app->smartypants($field->value);
@@ -377,6 +431,9 @@ return function (App $app) {
/**
* Splits the field content into an array
*
* @param Kirby\Cms\Field $field
* @return Kirby\cms\Field
*/
'split' => function (Field $field, $separator = ',') {
return Str::split((string)$field->value, $separator);
@@ -384,6 +441,9 @@ return function (App $app) {
/**
* Converts the field content to uppercase
*
* @param Kirby\Cms\Field $field
* @return Kirby\cms\Field
*/
'upper' => function (Field $field) {
$field->value = Str::upper($field->value);
@@ -391,7 +451,11 @@ return function (App $app) {
},
/**
* Avoids typographical widows in strings by replacing the last space with &nbsp;
* Avoids typographical widows in strings by replacing
* the last space with `&nbsp;`
*
* @param Kirby\Cms\Field $field
* @return Kirby\cms\Field
*/
'widont' => function (Field $field) {
$field->value = Str::widont($field->value);
@@ -402,6 +466,9 @@ return function (App $app) {
/**
* Parses yaml in the field content and returns an array
*
* @param Kirby\Cms\Field $field
* @return array
*/
'yaml' => function (Field $field): array {
return $field->toData('yaml');

View File

@@ -6,9 +6,17 @@ return function (array $props) {
'headline' => $props['headline'] ?? t('files'),
'type' => 'files',
'layout' => $props['layout'] ?? 'cards',
'template' => $props['template'] ?? null,
'info' => '{{ file.dimensions }}'
]
];
// remove global options
unset(
$props['headline'],
$props['layout'],
$props['template']
);
return $props;
};

View File

@@ -5,8 +5,23 @@ return [
'kirby' => function (array $roots) {
return realpath(__DIR__ . '/../');
},
// i18n
'i18n' => function (array $roots) {
return $roots['kirby'] . '/i18n';
},
'i18n:translations' => function (array $roots) {
return $roots['translations'];
},
'i18n:rules' => function (array $roots) {
return $roots['i18n'] . '/rules';
},
/**
* @deprecated 3.2.0 Use `i18n:translations` instead
* @TODO move logic over to i18n:translations before removing
*/
'translations' => function (array $roots) {
return $roots['kirby'] . '/translations';
return $roots['i18n'] . '/translations';
},
// index

View File

@@ -9,6 +9,7 @@ use Kirby\Cms\PluginAssets;
use Kirby\Cms\Response;
use Kirby\Exception\NotFoundException;
use Kirby\Http\Response\Redirect;
use Kirby\Http\Router;
use Kirby\Http\Router\Route;
use Kirby\Toolkit\F;
use Kirby\Toolkit\Str;
@@ -54,27 +55,15 @@ return function ($kirby) {
}
],
[
'pattern' => $media . '/panel/(:any)/plugins/(css|js)/(:any)/index.(css|js)',
'pattern' => $media . '/plugins/index.(css|js)',
'env' => 'media',
'action' => function (string $version, string $type) use ($kirby) {
$plugins = new PanelPlugins($type);
$plugins->publish();
'action' => function (string $type) use ($kirby) {
$plugins = new PanelPlugins();
return $kirby
->response()
->type($type)
->body($plugins->read());
}
],
[
'pattern' => $media . '/panel/plugins/index.(css|js)',
'env' => 'media',
'action' => function (string $type) use ($kirby) {
$plugins = new PanelPlugins($type);
return $kirby
->response()
->redirect($plugins->url(), 302);
->body($plugins->read($type));
}
],
[
@@ -150,7 +139,7 @@ return function ($kirby) {
// default home page
} else {
return $kirby->resolve(null, $kirby->defaultLanguage()->code());
return $kirby->defaultLanguage()->router()->call();
}
}
];
@@ -161,7 +150,7 @@ return function ($kirby) {
'method' => 'ALL',
'env' => 'site',
'action' => function ($path = null) use ($kirby, $language) {
return $kirby->resolve($path, $language->code());
return $language->router()->call($path);
}
];
}
@@ -191,7 +180,7 @@ return function ($kirby) {
}
}
return $kirby->resolve($path, $kirby->defaultLanguage()->code());
return $kirby->defaultLanguage()->router()->call($path);
}
];
} else {

View File

@@ -98,24 +98,12 @@ return [
'data' => function () {
$data = [];
if ($this->layout === 'list') {
$thumb = [
'width' => 100,
'height' => 100
];
} else {
$thumb = [
'width' => 400,
'height' => 400
];
}
// the drag text needs to be absolute when the files come from
// a different parent model
$dragTextAbsolute = $this->model->is($this->parent) === false;
foreach ($this->files as $file) {
$image = $file->panelImage($this->image, $thumb);
$image = $file->panelImage($this->image);
$data[] = [
'dragText' => $file->dragText($this->dragTextType, $dragTextAbsolute),
@@ -220,6 +208,7 @@ return [
'accept' => $this->accept,
'empty' => $this->empty,
'headline' => $this->headline,
'help' => $this->help,
'layout' => $this->layout,
'link' => $this->link,
'max' => $this->max,

View File

@@ -1,5 +1,7 @@
<?php
use Kirby\Toolkit\I18n;
return [
'props' => [
/**

View File

@@ -16,7 +16,12 @@ return [
$parent = $this->parent;
if (is_string($parent) === true) {
$parent = $this->model->query($parent);
$query = $parent;
$parent = $this->model->query($query);
if (!$parent) {
throw new Exception('The parent for the query "' . $query . '" cannot be found in the section "' . $this->name() . '"');
}
}
if ($parent === null) {

View File

@@ -1,9 +1,7 @@
<?php
use Kirby\Cms\App;
use Kirby\Cms\Blueprint;
use Kirby\Toolkit\A;
use Kirby\Toolkit\F;
use Kirby\Toolkit\Str;
return [
@@ -141,22 +139,9 @@ return [
'data' => function () {
$data = [];
if ($this->layout === 'list') {
$thumb = [
'width' => 100,
'height' => 100
];
} else {
$thumb = [
'width' => 400,
'height' => 400
];
}
foreach ($this->pages as $item) {
$permissions = $item->permissions();
$blueprint = $item->blueprint();
$image = $item->panelImage($this->image, $thumb);
$image = $item->panelImage($this->image);
$data[] = [
'id' => $item->id(),
@@ -281,6 +266,7 @@ return [
'add' => $this->add,
'empty' => $this->empty,
'headline' => $this->headline,
'help' => $this->help,
'layout' => $this->layout,
'link' => $this->link,
'max' => $this->max,

View File

@@ -1,7 +1,19 @@
<?php
$aliases = [
/**
* Constants
*/
define('DS', '/');
/**
* Load files that can't be autoloaded
*/
require_once __DIR__ . '/helpers.php';
/**
* Class aliases
*/
$aliases = [
// cms classes
'asset' => 'Kirby\Cms\Asset',
'collection' => 'Kirby\Cms\Collection',
@@ -64,3 +76,20 @@ spl_autoload_register(function ($class) use ($aliases) {
class_alias($aliases[$class], $class);
}
});
/**
* Tests
*/
$testDir = dirname(__DIR__) . '/tests';
if (is_dir($testDir) === true) {
spl_autoload_register(function ($className) use ($testDir) {
$path = str_replace('Kirby\\', '', $className);
$path = str_replace('\\', '/', $path);
$file = $testDir . '/' . $path . '.php';
if (file_exists($file)) {
include $file;
}
});
}

View File

@@ -39,6 +39,7 @@ return [
'file' => [
'attr' => [
'class',
'download',
'rel',
'target',
'text',
@@ -57,7 +58,7 @@ return [
return Html::a($file->url(), $tag->text, [
'class' => $tag->class,
'download' => true,
'download' => $tag->download !== 'false',
'rel' => $tag->rel,
'target' => $tag->target,
'title' => $tag->title,
@@ -105,8 +106,14 @@ return [
if (empty($tag->link) === true) {
return $img;
}
if ($link = $tag->file($tag->link)) {
$link = $link->url();
} else {
$link = $tag->link === 'self' ? $tag->src : $tag->link;
}
return Html::a($tag->link === 'self' ? $tag->src : $tag->link, [$img], [
return Html::a($link, [$img], [
'rel' => $tag->rel,
'class' => $tag->linkclass,
'target' => $tag->target

View File

@@ -1,15 +0,0 @@
<?php
$testDir = dirname(__DIR__) . '/tests';
if (is_dir($testDir) === true) {
spl_autoload_register(function ($className) use ($testDir) {
$path = str_replace('Kirby\\', '', $className);
$path = str_replace('\\', '/', $path);
$file = $testDir . '/' . $path . '.php';
if (file_exists($file)) {
include $file;
}
});
}