Upgrade to 3.1.0

This commit is contained in:
Bastian Allgeier
2019-03-19 11:07:14 +01:00
parent 418db4b09b
commit 6e074142f1
98 changed files with 1266 additions and 299 deletions

View File

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

View File

@@ -17,6 +17,9 @@ return [
'dimensions' => function (File $file) { 'dimensions' => function (File $file) {
return $file->dimensions()->toArray(); return $file->dimensions()->toArray();
}, },
'dragText' => function (File $file) {
return $file->dragText();
},
'exists' => function (File $file) { 'exists' => function (File $file) {
return $file->exists(); return $file->exists();
}, },
@@ -53,6 +56,15 @@ return [
'options' => function (File $file) { 'options' => function (File $file) {
return $file->permissions()->toArray(); return $file->permissions()->toArray();
}, },
'panelIcon' => function (File $file) {
return $file->panelIcon();
},
'panelImage' => function (File $file) {
return $file->panelImage();
},
'panelUrl' => function (File $file) {
return $file->panelUrl(true);
},
'prev' => function (File $file) { 'prev' => function (File $file) {
return $file->prev(); return $file->prev();
}, },

View File

@@ -7,6 +7,24 @@ use Kirby\Exception\InvalidArgumentException;
*/ */
return [ return [
[
'pattern' => '(:all)/files/(:any)/sections/(:any)',
'method' => 'GET',
'action' => function (string $path, string $filename, string $sectionName) {
if ($section = $this->file($path, $filename)->blueprint()->section($sectionName)) {
return $section->toResponse();
}
}
],
[
'pattern' => '(:all)/files/(:any)/fields/(:any)/(:all?)',
'method' => 'ALL',
'action' => function (string $parent, string $filename, string $fieldName, string $path = null) {
if ($file = $this->file($parent, $filename)) {
return $this->fieldApi($file, $fieldName, $path);
}
}
],
[ [
'pattern' => '(:all)/files', 'pattern' => '(:all)/files',
'method' => 'GET', 'method' => 'GET',
@@ -29,9 +47,15 @@ return [
], ],
[ [
'pattern' => '(:all)/files/search', 'pattern' => '(:all)/files/search',
'method' => 'POST', 'method' => 'GET|POST',
'action' => function (string $path) { 'action' => function (string $path) {
return $this->parent($path)->files()->query($this->requestBody()); $files = $this->parent($path)->files();
if ($this->requestMethod() === 'GET') {
return $files->search($this->requestQuery('q'));
} else {
return $files->query($this->requestBody());
}
} }
], ],
[ [
@@ -78,23 +102,5 @@ return [
return $this->file($path, $filename)->changeName($this->requestBody('name')); return $this->file($path, $filename)->changeName($this->requestBody('name'));
} }
], ],
[
'pattern' => '(:all)/files/(:any)/sections/(:any)',
'method' => 'GET',
'action' => function (string $path, string $filename, string $sectionName) {
if ($section = $this->file($path, $filename)->blueprint()->section($sectionName)) {
return $section->toResponse();
}
}
],
[
'pattern' => '(:all)/files/(:any)/fields/(:any)/(:all?)',
'method' => 'ALL',
'action' => function (string $parent, string $filename, string $fieldName, string $path = null) {
if ($file = $this->file($parent, $filename)) {
return $this->fieldApi($file, $fieldName, $path);
}
}
]
]; ];

View File

@@ -51,9 +51,15 @@ return [
], ],
[ [
'pattern' => 'pages/(:any)/children/search', 'pattern' => 'pages/(:any)/children/search',
'method' => 'POST', 'method' => 'GET|POST',
'action' => function (string $id) { 'action' => function (string $id) {
return $this->page($id)->children()->query($this->requestBody()); $pages = $this->page($id)->children();
if ($this->requestMethod() === 'GET') {
return $pages->search($this->requestQuery('q'));
} else {
return $pages->query($this->requestBody());
}
} }
], ],
[ [

View File

@@ -62,17 +62,18 @@ return [
], ],
[ [
'pattern' => 'site/search', 'pattern' => 'site/search',
'method' => 'GET', 'method' => 'GET|POST',
'action' => function () { 'action' => function () {
return $this->site() $pages = $this
->index(true) ->site()
->filterBy('isReadable', true) ->index(true)
->search($this->requestQuery('q'), [ ->filterBy('isReadable', true);
'score' => [
'id' => 64, if ($this->requestMethod() === 'GET') {
'title' => 64, return $pages->search($this->requestQuery('q'));
] } else {
]); return $pages->query($this->requestBody());
}
} }
], ],
[ [

View File

@@ -23,9 +23,13 @@ return [
], ],
[ [
'pattern' => 'users/search', 'pattern' => 'users/search',
'method' => 'POST', 'method' => 'GET|POST',
'action' => function () { 'action' => function () {
return $this->users()->query($this->requestBody()); if ($this->requestMethod() === 'GET') {
return $this->users()->search($this->requestQuery('q'));
} else {
return $this->users()->query($this->requestBody());
}
} }
], ],
[ [

View File

@@ -9,6 +9,7 @@ use Kirby\Cms\Template;
use Kirby\Data\Data; use Kirby\Data\Data;
use Kirby\Exception\NotFoundException; use Kirby\Exception\NotFoundException;
use Kirby\Image\Darkroom; use Kirby\Image\Darkroom;
use Kirby\Text\Markdown;
use Kirby\Text\SmartyPants; use Kirby\Text\SmartyPants;
use Kirby\Toolkit\F; use Kirby\Toolkit\F;
use Kirby\Toolkit\Tpl as Snippet; use Kirby\Toolkit\Tpl as Snippet;
@@ -50,17 +51,12 @@ return [
'file::url' => function (App $kirby, $file) { 'file::url' => function (App $kirby, $file) {
return $file->mediaUrl(); return $file->mediaUrl();
}, },
'markdown' => function (App $kirby, string $text = null, array $options = []): string { 'markdown' => function (App $kirby, string $text = null, array $options = [], bool $inline = false): string {
static $markdown; static $markdown;
if (isset($markdown) === false) { $markdown = $markdown ?? new Markdown($options);
$parser = ($options['extra'] ?? false) === true ? 'ParsedownExtra' : 'Parsedown';
$markdown = new $parser;
$markdown->setBreaksEnabled($options['breaks'] ?? true);
}
// we need the @ here, because parsedown has some notice issues :( return $markdown->parse($text, $inline);
return @$markdown->text($text);
}, },
'smartypants' => function (App $kirby, string $text = null, array $options = []): string { 'smartypants' => function (App $kirby, string $text = null, array $options = []): string {
static $smartypants; static $smartypants;

View File

@@ -22,7 +22,8 @@ return [
return $search; return $search;
}, },
/** /**
* If true, entries will be sorted alphabetically on selection * If true, selected entries will be sorted
* according to their position in the dropdown
*/ */
'sort' => function (bool $sort = false) { 'sort' => function (bool $sort = false) {
return $sort; return $sort;

View File

@@ -1,6 +1,6 @@
<?php <?php
use Kirby\Form\Form; use Kirby\Cms\Form;
use Kirby\Cms\Blueprint; use Kirby\Cms\Blueprint;
return [ return [

View File

@@ -29,6 +29,21 @@ return [
return trim($default); return trim($default);
}, },
/**
* Sets the options for the files picker
*/
'files' => function ($files = []) {
if (is_string($files) === true) {
return ['query' => $files];
}
if (is_array($files) === false) {
$files = [];
}
return $files;
},
/** /**
* Maximum number of allowed characters * Maximum number of allowed characters
*/ */
@@ -50,10 +65,103 @@ return [
return $size; 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) { 'value' => function (string $value = null) {
return trim($value); return trim($value);
} }
], ],
'api' => function () {
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;
}
],
[
'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 [
'filename' => $file->filename(),
'dragText' => $file->dragText(),
];
});
}
]
];
},
'validations' => [ 'validations' => [
'minlength', 'minlength',
'maxlength' 'maxlength'

View File

@@ -428,6 +428,45 @@ function kirbytext(string $text = null, array $data = []): string
return App::instance()->kirbytext($text, $data); return App::instance()->kirbytext($text, $data);
} }
/**
* Parses KirbyTags and inline Markdown in the
* given string.
* @since 3.1.0
*
* @param string $text
* @param array $data
* @return string
*/
function kirbytextinline(string $text = null, array $data = []): string
{
return App::instance()->kirbytext($text, $data, true);
}
/**
* Shortcut for `kirbytext()` helper
*
* @param string $text
* @param array $data
* @return string
*/
function kt(string $text = null, array $data = []): string
{
return kirbytext($text, $data);
}
/**
* Shortcut for `kirbytextinline()` helper
* @since 3.1.0
*
* @param string $text
* @param array $data
* @return string
*/
function kti(string $text = null, array $data = []): string
{
return kirbytextinline($text, $data);
}
/** /**
* A super simple class autoloader * A super simple class autoloader
* *

View File

@@ -298,6 +298,19 @@ return function (App $app) {
return $field; return $field;
}, },
/**
* Converts the field content from inline Markdown/Kirbytext to valid HTML
* @since 3.1.0
*/
'kirbytextinline' => function (Field $field) use ($app) {
$field->value = $app->kirbytext($field->value, [
'parent' => $field->parent(),
'field' => $field
], true);
return $field;
},
/** /**
* Parses all KirbyTags without also parsing Markdown * Parses all KirbyTags without also parsing Markdown
*/ */

View File

@@ -56,11 +56,7 @@ return function ($kirby) {
'pattern' => 'media/plugins/(:any)/(:any)/(:all).(css|gif|js|jpg|png|svg|webp|woff2|woff)', 'pattern' => 'media/plugins/(:any)/(:any)/(:all).(css|gif|js|jpg|png|svg|webp|woff2|woff)',
'env' => 'media', 'env' => 'media',
'action' => function (string $provider, string $pluginName, string $filename, string $extension) use ($kirby) { 'action' => function (string $provider, string $pluginName, string $filename, string $extension) use ($kirby) {
if ($url = PluginAssets::resolve($provider . '/' . $pluginName, $filename . '.' . $extension)) { return PluginAssets::resolve($provider . '/' . $pluginName, $filename . '.' . $extension);
return $kirby
->response()
->redirect($url, 307);
}
} }
], ],
[ [
@@ -115,7 +111,7 @@ return function ($kirby) {
'action' => function () use ($kirby) { 'action' => function () use ($kirby) {
$home = $kirby->site()->homePage(); $home = $kirby->site()->homePage();
if ($kirby->url() !== $home->url()) { if ($home && $kirby->url() !== $home->url()) {
if ($kirby->option('languages.detect') === true) { if ($kirby->option('languages.detect') === true) {
return $kirby return $kirby
->response() ->response()
@@ -126,7 +122,7 @@ return function ($kirby) {
->redirect($kirby->site()->url()); ->redirect($kirby->site()->url());
} }
} else { } else {
return $home; return $kirby->resolve(null, $kirby->detectedLanguage()->code());
} }
} }
]; ];
@@ -178,7 +174,7 @@ return function ($kirby) {
'method' => 'ALL', 'method' => 'ALL',
'env' => 'site', 'env' => 'site',
'action' => function () use ($kirby) { 'action' => function () use ($kirby) {
return $kirby->site()->homePage(); return $kirby->resolve();
} }
]; ];

View File

@@ -8,6 +8,7 @@ return [
'mixins' => [ 'mixins' => [
'empty', 'empty',
'headline', 'headline',
'help',
'layout', 'layout',
'min', 'min',
'max', 'max',

View File

@@ -4,7 +4,8 @@ use Kirby\Toolkit\I18n;
return [ return [
'mixins' => [ 'mixins' => [
'headline' 'headline',
'help'
], ],
'props' => [ 'props' => [
'text' => function ($text = null) { 'text' => function ($text = null) {

View File

@@ -0,0 +1,12 @@
<?php
return [
'props' => [
/**
* Sets the help text
*/
'help' => function ($help = null) {
return I18n::translate($help, $help);
}
]
];

View File

@@ -10,6 +10,7 @@ return [
'mixins' => [ 'mixins' => [
'empty', 'empty',
'headline', 'headline',
'help',
'layout', 'layout',
'min', 'min',
'max', 'max',

File diff suppressed because one or more lines are too long

View File

@@ -1,4 +1,4 @@
<svg aria-hidden="true" style="position:absolute;width:0;height:0" xmlns="http://www.w3.org/2000/svg" overflow="hidden"> <svg aria-hidden="true" class="k-icons" xmlns="http://www.w3.org/2000/svg" overflow="hidden">
<defs> <defs>
<symbol id="icon-account" viewBox="0 0 16 16"> <symbol id="icon-account" viewBox="0 0 16 16">
<path d="M11 7a3 3 0 1 1-6 0 3 3 0 0 1 6 0z" /> <path d="M11 7a3 3 0 1 1-6 0 3 3 0 0 1 6 0z" />
@@ -27,6 +27,9 @@
<symbol id="icon-angle-up" viewBox="0 0 16 16"> <symbol id="icon-angle-up" viewBox="0 0 16 16">
<path d="M12 11.4l-4-4-4 4L2.6 10 8 4.6l5.4 5.4z" /> <path d="M12 11.4l-4-4-4 4L2.6 10 8 4.6l5.4 5.4z" />
</symbol> </symbol>
<symbol id="icon-attachment" viewBox="0 0 16 16">
<path d="M5,5v4c0,1.7,1.3,3,3,3s3-1.3,3-3V4.5C11,2,9,0,6.5,0S2,2,2,4.5V10c0,3.3,2.7,6,6,6s6-2.7,6-6V4h-2v6 c0,2.2-1.8,4-4,4s-4-1.8-4-4V4.5C4,3.1,5.1,2,6.5,2S9,3.1,9,4.5V9c0,0.6-0.4,1-1,1S7,9.6,7,9V5H5z" />
</symbol>
<symbol id="icon-bars" viewBox="0 0 16 16"> <symbol id="icon-bars" viewBox="0 0 16 16">
<path d="M15 7H1c-.6 0-1 .4-1 1s.4 1 1 1h14c.6 0 1-.4 1-1s-.4-1-1-1zM15 1H1c-.6 0-1 .4-1 1s.4 1 1 1h14c.6 0 1-.4 1-1s-.4-1-1-1zM15 13H1c-.6 0-1 .4-1 1s.4 1 1 1h14c.6 0 1-.4 1-1s-.4-1-1-1z" <path d="M15 7H1c-.6 0-1 .4-1 1s.4 1 1 1h14c.6 0 1-.4 1-1s-.4-1-1-1zM15 1H1c-.6 0-1 .4-1 1s.4 1 1 1h14c.6 0 1-.4 1-1s-.4-1-1-1zM15 13H1c-.6 0-1 .4-1 1s.4 1 1 1h14c.6 0 1-.4 1-1s-.4-1-1-1z"
/> />

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

File diff suppressed because one or more lines are too long

23
kirby/panel/jest.config.js Executable file
View File

@@ -0,0 +1,23 @@
module.exports = {
moduleFileExtensions: [
'js',
'jsx',
'json',
'vue'
],
transform: {
'^.+\\.vue$': 'vue-jest',
'.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$': 'jest-transform-stub',
'^.+\\.jsx?$': 'babel-jest'
},
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1'
},
snapshotSerializers: [
'jest-serializer-vue'
],
testMatch: [
'**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)'
],
testURL: 'http://localhost/'
}

View File

@@ -22,25 +22,106 @@ class Api
{ {
use Properties; use Properties;
/**
* Authentication callback
*
* @var Closure
*/
protected $authentication; protected $authentication;
/**
* Debugging flag
*
* @var boolean
*/
protected $debug = false; protected $debug = false;
/**
* Collection definition
*
* @var array
*/
protected $collections = []; protected $collections = [];
/**
* Injected data/dependencies
*
* @var array
*/
protected $data = []; protected $data = [];
/**
* Model definitions
*
* @var array
*/
protected $models = []; protected $models = [];
/**
* The current route
*
* @var Route
*/
protected $route;
/**
* The Router instance
*
* @var Router
*/
protected $router;
/**
* Route definition
*
* @var array
*/
protected $routes = []; protected $routes = [];
/**
* Request data
* [query, body, files]
*
* @var array
*/
protected $requestData = []; protected $requestData = [];
/**
* The applied request method
* (GET, POST, PATCH, etc.)
*
* @var string
*/
protected $requestMethod; protected $requestMethod;
public function __call($method, $args) /**
* Magic accessor for any given data
*
* @param string $method
* @param array $args
* @return mixed
*/
public function __call(string $method, array $args = [])
{ {
return $this->data($method, ...$args); return $this->data($method, ...$args);
} }
/**
* Creates a new API instance
*
* @param array $props
*/
public function __construct(array $props) public function __construct(array $props)
{ {
$this->setProperties($props); $this->setProperties($props);
} }
/**
* Runs the authentication method
* if set
*
* @return mixed
*/
public function authenticate() public function authenticate()
{ {
if ($auth = $this->authentication()) { if ($auth = $this->authentication()) {
@@ -50,11 +131,25 @@ class Api
return true; return true;
} }
/**
* Returns the authentication callback
*
* @return Closure|null
*/
public function authentication() public function authentication()
{ {
return $this->authentication; return $this->authentication;
} }
/**
* Execute an API call for the given path,
* request method and optional request data
*
* @param string $path
* @param string $method
* @param array $requestData
* @return mixed
*/
public function call(string $path = null, string $method = 'GET', array $requestData = []) public function call(string $path = null, string $method = 'GET', array $requestData = [])
{ {
$path = rtrim($path, '/'); $path = rtrim($path, '/');
@@ -62,15 +157,15 @@ class Api
$this->setRequestMethod($method); $this->setRequestMethod($method);
$this->setRequestData($requestData); $this->setRequestData($requestData);
$router = new Router($this->routes()); $this->router = new Router($this->routes());
$result = $router->find($path, $method); $this->route = $this->router->find($path, $method);
$auth = $result->attributes()['auth'] ?? true; $auth = $this->route->attributes()['auth'] ?? true;
if ($auth !== false) { if ($auth !== false) {
$this->authenticate(); $this->authenticate();
} }
$output = $result->action()->call($this, ...$result->arguments()); $output = $this->route->action()->call($this, ...$this->route->arguments());
if (is_object($output) === true) { if (is_object($output) === true) {
return $this->resolve($output)->toResponse(); return $this->resolve($output)->toResponse();
@@ -79,6 +174,13 @@ class Api
return $output; return $output;
} }
/**
* Setter and getter for an API collection
*
* @param string $name
* @param array|null $collection
* @return Collection
*/
public function collection(string $name, $collection = null) public function collection(string $name, $collection = null)
{ {
if (isset($this->collections[$name]) === false) { if (isset($this->collections[$name]) === false) {
@@ -88,11 +190,24 @@ class Api
return new Collection($this, $collection, $this->collections[$name]); return new Collection($this, $collection, $this->collections[$name]);
} }
/**
* Returns the collections definition
*
* @return array
*/
public function collections(): array public function collections(): array
{ {
return $this->collections; return $this->collections;
} }
/**
* Returns the injected data array
* or certain parts of it by key
*
* @param string|null $key
* @param mixed ...$args
* @return mixed
*/
public function data($key = null, ...$args) public function data($key = null, ...$args)
{ {
if ($key === null) { if ($key === null) {
@@ -111,11 +226,34 @@ class Api
return $this->data[$key]; return $this->data[$key];
} }
public function hasData($key): bool /**
* Returns the debugging flag
*
* @return boolean
*/
public function debug(): bool
{
return $this->debug;
}
/**
* Checks if injected data exists for the given key
*
* @param string $key
* @return boolean
*/
public function hasData(string $key): bool
{ {
return isset($this->data[$key]) === true; return isset($this->data[$key]) === true;
} }
/**
* Returns an API model instance by name
*
* @param string $name
* @param mixed $object
* @return Model
*/
public function model(string $name, $object = null) public function model(string $name, $object = null)
{ {
if (isset($this->models[$name]) === false) { if (isset($this->models[$name]) === false) {
@@ -125,12 +263,27 @@ class Api
return new Model($this, $object, $this->models[$name]); return new Model($this, $object, $this->models[$name]);
} }
/**
* Returns all model definitions
*
* @return array
*/
public function models(): array public function models(): array
{ {
return $this->models; return $this->models;
} }
public function requestData($type = null, $key = null, $default = null) /**
* Getter for request data
* Can either get all the data
* or certain parts of it.
*
* @param string $type
* @param string $key
* @param mixed $default
* @return mixed
*/
public function requestData(string $type = null, string $key = null, $default = null)
{ {
if ($type === null) { if ($type === null) {
return $this->requestData; return $this->requestData;
@@ -146,31 +299,71 @@ class Api
return $data[$key] ?? $default; return $data[$key] ?? $default;
} }
/**
* Returns the request body if available
*
* @param string $key
* @param mixed $default
* @return mixed
*/
public function requestBody(string $key = null, $default = null) public function requestBody(string $key = null, $default = null)
{ {
return $this->requestData('body', $key, $default); return $this->requestData('body', $key, $default);
} }
/**
* Returns the files from the request if available
*
* @param string $key
* @param mixed $default
* @return mixed
*/
public function requestFiles(string $key = null, $default = null) public function requestFiles(string $key = null, $default = null)
{ {
return $this->requestData('files', $key, $default); return $this->requestData('files', $key, $default);
} }
/**
* Returns all headers from the request if available
*
* @param string $key
* @param mixed $default
* @return mixed
*/
public function requestHeaders(string $key = null, $default = null) public function requestHeaders(string $key = null, $default = null)
{ {
return $this->requestData('headers', $key, $default); return $this->requestData('headers', $key, $default);
} }
/**
* Returns the request method
*
* @return string
*/
public function requestMethod(): string public function requestMethod(): string
{ {
return $this->requestMethod; return $this->requestMethod;
} }
/**
* Returns the request query if available
*
* @param string $key
* @param mixed $default
* @return mixed
*/
public function requestQuery(string $key = null, $default = null) public function requestQuery(string $key = null, $default = null)
{ {
return $this->requestData('query', $key, $default); return $this->requestData('query', $key, $default);
} }
/**
* Turns a Kirby object into an
* API model or collection representation
*
* @param mixed $object
* @return Model|Collection
*/
public function resolve($object) public function resolve($object)
{ {
if (is_a($object, 'Kirby\Api\Model') === true || is_a($object, 'Kirby\Api\Collection') === true) { if (is_a($object, 'Kirby\Api\Model') === true || is_a($object, 'Kirby\Api\Collection') === true) {
@@ -202,17 +395,34 @@ class Api
throw new NotFoundException(sprintf('The object "%s" cannot be resolved', $className)); throw new NotFoundException(sprintf('The object "%s" cannot be resolved', $className));
} }
/**
* Returns all defined routes
*
* @return array
*/
public function routes(): array public function routes(): array
{ {
return $this->routes; return $this->routes;
} }
/**
* Setter for the authentication callback
*
* @param Closure $authentication
* @return self
*/
protected function setAuthentication(Closure $authentication = null) protected function setAuthentication(Closure $authentication = null)
{ {
$this->authentication = $authentication; $this->authentication = $authentication;
return $this; return $this;
} }
/**
* Setter for the collections definition
*
* @param array $collections
* @return self
*/
protected function setCollections(array $collections = null) protected function setCollections(array $collections = null)
{ {
if ($collections !== null) { if ($collections !== null) {
@@ -221,18 +431,36 @@ class Api
return $this; return $this;
} }
/**
* Setter for the injected data
*
* @param array $data
* @return self
*/
protected function setData(array $data = null) protected function setData(array $data = null)
{ {
$this->data = $data ?? []; $this->data = $data ?? [];
return $this; return $this;
} }
/**
* Setter for the debug flag
*
* @param boolean $debug
* @return self
*/
protected function setDebug(bool $debug = false) protected function setDebug(bool $debug = false)
{ {
$this->debug = $debug; $this->debug = $debug;
return $this; return $this;
} }
/**
* Setter for the model definitions
*
* @param array $models
* @return self
*/
protected function setModels(array $models = null) protected function setModels(array $models = null)
{ {
if ($models !== null) { if ($models !== null) {
@@ -242,6 +470,12 @@ class Api
return $this; return $this;
} }
/**
* Setter for the request data
*
* @param array $requestData
* @return self
*/
protected function setRequestData(array $requestData = null) protected function setRequestData(array $requestData = null)
{ {
$defaults = [ $defaults = [
@@ -254,25 +488,48 @@ class Api
return $this; return $this;
} }
/**
* Setter for the request method
*
* @param string $requestMethod
* @return self
*/
protected function setRequestMethod(string $requestMethod = null) protected function setRequestMethod(string $requestMethod = null)
{ {
$this->requestMethod = $requestMethod; $this->requestMethod = $requestMethod ?? 'GET';
return $this; return $this;
} }
/**
* Setter for the route definitions
*
* @param array $routes
* @return self
*/
protected function setRoutes(array $routes = null) protected function setRoutes(array $routes = null)
{ {
$this->routes = $routes ?? []; $this->routes = $routes ?? [];
return $this; return $this;
} }
/**
* Renders the API call
*
* @param string $path
* @param string $method
* @param array $requestData
* @return mixed
*/
public function render(string $path, $method = 'GET', array $requestData = []) public function render(string $path, $method = 'GET', array $requestData = [])
{ {
try { try {
$result = $this->call($path, $method, $requestData); $result = $this->call($path, $method, $requestData);
} catch (Throwable $e) { } catch (Throwable $e) {
if (is_a($e, 'Kirby\Exception\Exception') === true) { if (is_a($e, 'Kirby\Exception\Exception') === true) {
$result = ['status' => 'error'] + $e->toArray(); $result = [
'status' => 'error',
'route' => $this->route->pattern()
] + $e->toArray();
} else { } else {
$result = [ $result = [
'status' => 'error', 'status' => 'error',
@@ -280,7 +537,8 @@ class Api
'message' => $e->getMessage(), 'message' => $e->getMessage(),
'file' => ltrim($e->getFile(), $_SERVER['DOCUMENT_ROOT'] ?? null), 'file' => ltrim($e->getFile(), $_SERVER['DOCUMENT_ROOT'] ?? null),
'line' => $e->getLine(), 'line' => $e->getLine(),
'code' => empty($e->getCode()) === false ? $e->getCode() : 500 'code' => empty($e->getCode()) === false ? $e->getCode() : 500,
'route' => $this->route->pattern()
]; ];
} }
} }
@@ -338,6 +596,13 @@ class Api
return Response::json($result, 200, $pretty); return Response::json($result, 200, $pretty);
} }
/**
* Upload helper method
*
* @param Closure $callback
* @param boolean $single
* @return array
*/
public function upload(Closure $callback, $single = false): array public function upload(Closure $callback, $single = false): array
{ {
$trials = 0; $trials = 0;

View File

@@ -29,9 +29,16 @@ use Kirby\Toolkit\Str;
use Kirby\Toolkit\Url; use Kirby\Toolkit\Url;
/** /**
* The App object is a big-ass monolith that's * The `$kirby` object is the app instance of
* in the center between all the other CMS classes. * your Kirby installation. It's the central
* It's the $kirby object in templates and handles * starting point to get all the different
* aspects of your site, like the options, urls,
* roots, languages, roles, etc.
*
* @package Kirby Cms
* @author Bastian Allgeier <bastian@getkirby.com>
* @link http://getkirby.com
* @copyright Bastian Allgeier
*/ */
class App class App
{ {
@@ -148,6 +155,7 @@ class App
/** /**
* Returns the Api instance * Returns the Api instance
* *
* @internal
* @return Api * @return Api
*/ */
public function api(): Api public function api(): Api
@@ -170,8 +178,9 @@ class App
} }
/** /**
* Apply a hook to the given value * Apply a hook to the given value
* *
* @internal
* @param string $name * @param string $name
* @param mixed $value * @param mixed $value
* @return mixed * @return mixed
@@ -264,12 +273,13 @@ class App
*/ */
public function collections(): Collections public function collections(): Collections
{ {
return $this->collections = $this->collections ?? Collections::load($this); return $this->collections = $this->collections ?? new Collections;
} }
/** /**
* Returns a core component * Returns a core component
* *
* @internal
* @param string $name * @param string $name
* @return mixed * @return mixed
*/ */
@@ -281,6 +291,7 @@ class App
/** /**
* Returns the content extension * Returns the content extension
* *
* @internal
* @return string * @return string
*/ */
public function contentExtension(): string public function contentExtension(): string
@@ -291,6 +302,7 @@ class App
/** /**
* Returns files that should be ignored when scanning folders * Returns files that should be ignored when scanning folders
* *
* @internal
* @return array * @return array
*/ */
public function contentIgnore(): array public function contentIgnore(): array
@@ -302,6 +314,7 @@ class App
* Calls a page controller by name * Calls a page controller by name
* and with the given arguments * and with the given arguments
* *
* @internal
* @param string $name * @param string $name
* @param array $arguments * @param array $arguments
* @return array * @return array
@@ -369,6 +382,8 @@ class App
/** /**
* Destroy the instance singleton and * Destroy the instance singleton and
* purge other static props * purge other static props
*
* @internal
*/ */
public static function destroy() public static function destroy()
{ {
@@ -424,6 +439,10 @@ class App
$id = dirname($path); $id = dirname($path);
$filename = basename($path); $filename = basename($path);
if (is_a($parent, User::class) === true) {
return $parent->file($filename);
}
if (is_a($parent, File::class) === true) { if (is_a($parent, File::class) === true) {
$parent = $parent->parent(); $parent = $parent->parent();
} }
@@ -468,6 +487,7 @@ class App
* Takes almost any kind of input and * Takes almost any kind of input and
* tries to convert it into a valid response * tries to convert it into a valid response
* *
* @internal
* @param mixed $input * @param mixed $input
* @return Response * @return Response
*/ */
@@ -553,6 +573,7 @@ class App
/** /**
* Renders a single KirbyTag with the given attributes * Renders a single KirbyTag with the given attributes
* *
* @internal
* @param string $type * @param string $type
* @param string $value * @param string $value
* @param array $attr * @param array $attr
@@ -571,6 +592,7 @@ class App
/** /**
* KirbyTags Parser * KirbyTags Parser
* *
* @internal
* @param string $text * @param string $text
* @param array $data * @param array $data
* @return string * @return string
@@ -587,15 +609,16 @@ class App
/** /**
* Parses KirbyTags first and Markdown afterwards * Parses KirbyTags first and Markdown afterwards
* *
* @internal
* @param string $text * @param string $text
* @param array $data * @param array $data
* @return string * @return string
*/ */
public function kirbytext(string $text = null, array $data = []): string public function kirbytext(string $text = null, array $data = [], bool $inline = false): string
{ {
$text = $this->apply('kirbytext:before', $text); $text = $this->apply('kirbytext:before', $text);
$text = $this->kirbytags($text, $data); $text = $this->kirbytags($text, $data);
$text = $this->markdown($text); $text = $this->markdown($text, $inline);
$text = $this->apply('kirbytext:after', $text); $text = $this->apply('kirbytext:after', $text);
return $text; return $text;
@@ -627,6 +650,7 @@ class App
/** /**
* Returns the current language code * Returns the current language code
* *
* @internal
* @return string|null * @return string|null
*/ */
public function languageCode(string $languageCode = null): ?string public function languageCode(string $languageCode = null): ?string
@@ -651,12 +675,14 @@ class App
/** /**
* Parses Markdown * Parses Markdown
* *
* @internal
* @param string $text * @param string $text
* @param bool $inline
* @return string * @return string
*/ */
public function markdown(string $text = null): string public function markdown(string $text = null, bool $inline = false): string
{ {
return $this->extensions['components']['markdown']($this, $text, $this->options['markdown'] ?? []); return $this->extensions['components']['markdown']($this, $text, $this->options['markdown'] ?? [], $inline);
} }
/** /**
@@ -794,6 +820,7 @@ class App
/** /**
* Path resolver for the router * Path resolver for the router
* *
* @internal
* @param string $path * @param string $path
* @param string|null $language * @param string|null $language
* @return mixed * @return mixed
@@ -811,7 +838,11 @@ class App
// use the home page // use the home page
if ($path === null) { if ($path === null) {
return $site->homePage(); if ($homePage = $site->homePage()) {
return $homePage;
}
throw new NotFoundException('The home page does not exist');
} }
// search for the page by path // search for the page by path
@@ -911,6 +942,7 @@ class App
/** /**
* Returns the Router singleton * Returns the Router singleton
* *
* @internal
* @return Router * @return Router
*/ */
public function router(): Router public function router(): Router
@@ -921,6 +953,7 @@ class App
/** /**
* Returns all defined routes * Returns all defined routes
* *
* @internal
* @return array * @return array
*/ */
public function routes(): array public function routes(): array
@@ -1052,6 +1085,7 @@ class App
/** /**
* Applies the smartypants rule on the text * Applies the smartypants rule on the text
* *
* @internal
* @param string $text * @param string $text
* @return string * @return string
*/ */
@@ -1064,6 +1098,7 @@ class App
* Uses the snippet component to create * Uses the snippet component to create
* and return a template snippet * and return a template snippet
* *
* @internal
* @return Snippet * @return Snippet
*/ */
public function snippet(string $name, array $data = []): ?string public function snippet(string $name, array $data = []): ?string
@@ -1085,6 +1120,7 @@ class App
* Uses the template component to initialize * Uses the template component to initialize
* and return the Template object * and return the Template object
* *
* @internal
* @return Template * @return Template
*/ */
public function template(string $name, string $type = 'html', string $defaultType = 'html'): Template public function template(string $name, string $type = 'html', string $defaultType = 'html'): Template
@@ -1106,8 +1142,9 @@ class App
} }
/** /**
* Trigger a hook by name * Trigger a hook by name
* *
* @internal
* @param string $name * @param string $name
* @param mixed ...$arguments * @param mixed ...$arguments
* @return void * @return void

View File

@@ -67,6 +67,7 @@ trait AppPlugins
/** /**
* Register all given extensions * Register all given extensions
* *
* @internal
* @param array $extensions * @param array $extensions
* @param Plugin $plugin The plugin which defined those extensions * @param Plugin $plugin The plugin which defined those extensions
* @return array * @return array
@@ -133,7 +134,7 @@ trait AppPlugins
protected function extendFieldMethods(array $methods): array protected function extendFieldMethods(array $methods): array
{ {
return $this->extensions['fieldMethods'] = Field::$methods = array_merge(Field::$methods, $methods); return $this->extensions['fieldMethods'] = Field::$methods = array_merge(Field::$methods, array_change_key_case($methods));
} }
protected function extendFields(array $fields): array protected function extendFields(array $fields): array
@@ -258,6 +259,7 @@ trait AppPlugins
/** /**
* Returns a given extension by type and name * Returns a given extension by type and name
* *
* @internal
* @param string $type i.e. `'hooks'` * @param string $type i.e. `'hooks'`
* @param string $name i.e. `'page.delete:before'` * @param string $name i.e. `'page.delete:before'`
* @param mixed $fallback * @param mixed $fallback
@@ -270,7 +272,9 @@ trait AppPlugins
/** /**
* Returns the extensions registry * Returns the extensions registry
*
* @internal
* @param string|null $type
* @return array * @return array
*/ */
public function extensions(string $type = null) public function extensions(string $type = null)
@@ -376,6 +380,7 @@ trait AppPlugins
'h' => 'html', 'h' => 'html',
'int' => 'toInt', 'int' => 'toInt',
'kt' => 'kirbytext', 'kt' => 'kirbytext',
'kti' => 'kirbytextinline',
'link' => 'toLink', 'link' => 'toLink',
'md' => 'markdown', 'md' => 'markdown',
'sp' => 'smartypants', 'sp' => 'smartypants',
@@ -404,6 +409,7 @@ trait AppPlugins
// section mixins // section mixins
Section::$mixins['empty'] = include static::$root . '/config/sections/mixins/empty.php'; Section::$mixins['empty'] = include static::$root . '/config/sections/mixins/empty.php';
Section::$mixins['headline'] = include static::$root . '/config/sections/mixins/headline.php'; Section::$mixins['headline'] = include static::$root . '/config/sections/mixins/headline.php';
Section::$mixins['help'] = include static::$root . '/config/sections/mixins/help.php';
Section::$mixins['layout'] = include static::$root . '/config/sections/mixins/layout.php'; Section::$mixins['layout'] = include static::$root . '/config/sections/mixins/layout.php';
Section::$mixins['max'] = include static::$root . '/config/sections/mixins/max.php'; Section::$mixins['max'] = include static::$root . '/config/sections/mixins/max.php';
Section::$mixins['min'] = include static::$root . '/config/sections/mixins/min.php'; Section::$mixins['min'] = include static::$root . '/config/sections/mixins/min.php';
@@ -447,6 +453,7 @@ trait AppPlugins
* Loads and returns all plugins in the site/plugins directory * Loads and returns all plugins in the site/plugins directory
* Loading only happens on the first call. * Loading only happens on the first call.
* *
* @internal
* @param array $plugins Can be used to overwrite the plugins registry * @param array $plugins Can be used to overwrite the plugins registry
* @return array * @return array
*/ */

View File

@@ -53,6 +53,7 @@ trait AppTranslations
* Load and set the current language if it exists * Load and set the current language if it exists
* Otherwise fall back to the default language * Otherwise fall back to the default language
* *
* @internal
* @param string $languageCode * @param string $languageCode
* @return Language|null * @return Language|null
*/ */
@@ -79,6 +80,7 @@ trait AppTranslations
/** /**
* Set the current translation * Set the current translation
* *
* @internal
* @param string $translationCode * @param string $translationCode
* @return void * @return void
*/ */
@@ -90,6 +92,7 @@ trait AppTranslations
/** /**
* Set locale settings * Set locale settings
* *
* @internal
* @param string|array $locale * @param string|array $locale
*/ */
public function setLocale($locale) public function setLocale($locale)

View File

@@ -15,6 +15,7 @@ trait AppUsers
/** /**
* Returns the Authentication layer class * Returns the Authentication layer class
* *
* @internal
* @return Auth * @return Auth
*/ */
public function auth() public function auth()

View File

@@ -230,6 +230,38 @@ class Collection extends BaseCollection
return $this->parent; return $this->parent;
} }
/**
* Runs a combination of filterBy, sortBy, not
* offset, limit, search and paginate on the collection.
* Any part of the query is optional.
*
* @param array $query
* @return self
*/
public function query(array $query = [])
{
$paginate = $query['paginate'] ?? null;
$search = $query['search'] ?? null;
unset($query['paginate']);
$result = parent::query($query);
if (empty($search) === false) {
if (is_array($search) === true) {
$result = $result->search($search['query'] ?? null, $search['options'] ?? []);
} else {
$result = $result->search($search);
}
}
if (empty($paginate) === false) {
$result = $result->paginate($paginate);
}
return $result;
}
/** /**
* Removes an object * Removes an object
* *

View File

@@ -52,16 +52,6 @@ class Collections
return $this->get($name, ...$arguments); return $this->get($name, ...$arguments);
} }
/**
* Creates a new Collections set
*
* @param array $collections
*/
public function __construct(array $collections = [])
{
$this->collections = $collections;
}
/** /**
* Loads a collection by name if registered * Loads a collection by name if registered
* *
@@ -71,17 +61,23 @@ class Collections
*/ */
public function get(string $name, array $data = []) public function get(string $name, array $data = [])
{ {
if (isset($this->cache[$name]) === true) { // if not yet loaded
return $this->cache[$name];
}
if (isset($this->collections[$name]) === false) { if (isset($this->collections[$name]) === false) {
return null; $this->collections[$name] = $this->load($name);
} }
$controller = new Controller($this->collections[$name]); // if not yet cached
if (isset($this->cache[$name]) === false) {
$controller = new Controller($this->collections[$name]);
$this->cache[$name] = $controller->call(null, $data);
}
return $this->cache[$name] = $controller->call(null, $data); // return cloned object
if (is_object($this->cache[$name]) === true) {
return clone $this->cache[$name];
}
return $this->cache[$name];
} }
/** /**
@@ -92,30 +88,47 @@ class Collections
*/ */
public function has(string $name): bool public function has(string $name): bool
{ {
return isset($this->collections[$name]) === true; if (isset($this->collections[$name]) === true) {
return true;
}
try {
$this->load($name);
return true;
} catch (NotFoundException $e) {
return false;
}
} }
/** /**
* Loads collections from php files in a * Loads collection from php file in a
* given directory. * given directory or from plugin extension.
* *
* @param string $root * @param string $name
* @return self * @return mixed
*/ */
public static function load(App $app): self public function load(string $name)
{ {
$collections = $app->extensions('collections'); $kirby = App::instance();
$root = $app->root('collections');
foreach (glob($root . '/*.php') as $file) { // first check for collection file
$file = $kirby->root('collections') . '/' . $name . '.php';
if (file_exists($file)) {
$collection = require $file; $collection = require $file;
if (is_a($collection, 'Closure')) { if (is_a($collection, 'Closure')) {
$name = pathinfo($file, PATHINFO_FILENAME); return $collection;
$collections[$name] = $collection;
} }
} }
return new static($collections); // fallback to collections from plugins
$collections = $kirby->extensions('collections');
if (isset($collections[$name]) === true) {
return $collections[$name];
}
throw new NotFoundException('The collection cannot be found');
} }
} }

View File

@@ -87,7 +87,12 @@ class ContentTranslation
// merge with the default content // merge with the default content
if ($this->isDefault() === false && $defaultLanguage = $parent->kirby()->defaultLanguage()) { if ($this->isDefault() === false && $defaultLanguage = $parent->kirby()->defaultLanguage()) {
$default = $parent->translation($defaultLanguage->code())->content(); $default = [];
if ($defaultTranslation = $parent->translation($defaultLanguage->code())) {
$default = $defaultTranslation->content();
}
$content = array_merge($default, $content); $content = array_merge($default, $content);
} }

View File

@@ -73,12 +73,14 @@ class Field
*/ */
public function __call(string $method, array $arguments = []) public function __call(string $method, array $arguments = [])
{ {
$method = strtolower($method);
if (isset(static::$methods[$method]) === true) { if (isset(static::$methods[$method]) === true) {
return static::$methods[$method](clone $this, ...$arguments); return static::$methods[$method](clone $this, ...$arguments);
} }
if (isset(static::$aliases[$method]) === true) { if (isset(static::$aliases[$method]) === true) {
$method = static::$aliases[$method]; $method = strtolower(static::$aliases[$method]);
if (isset(static::$methods[$method]) === true) { if (isset(static::$methods[$method]) === true) {
return static::$methods[$method](clone $this, ...$arguments); return static::$methods[$method](clone $this, ...$arguments);
@@ -142,7 +144,7 @@ class Field
*/ */
public function isEmpty(): bool public function isEmpty(): bool
{ {
return empty($this->value) === true; return empty($this->value) === true && in_array($this->value, [0, '0', false], true) === false;
} }
/** /**
@@ -152,7 +154,7 @@ class Field
*/ */
public function isNotEmpty(): bool public function isNotEmpty(): bool
{ {
return empty($this->value) === false; return $this->isEmpty() === false;
} }
/** /**

View File

@@ -12,6 +12,13 @@ use Kirby\Toolkit\Str;
use Throwable; use Throwable;
/** /**
* The `$file` object provides a set
* of methods that can be used when
* dealing with a single image or
* other media file, like getting the
* URL or resizing an image. It also
* handles file meta data.
*
* The File class is a wrapper around * The File class is a wrapper around
* the Kirby\Image\Image class, which * the Kirby\Image\Image class, which
* is used to handle all file methods. * is used to handle all file methods.
@@ -148,6 +155,7 @@ class File extends ModelWithContent
/** /**
* Returns the url to api endpoint * Returns the url to api endpoint
* *
* @internal
* @param bool $relative * @param bool $relative
* @return string * @return string
*/ */
@@ -157,8 +165,9 @@ class File extends ModelWithContent
} }
/** /**
* Returns the Asset object * Returns the Image object
* *
* @internal
* @return Image * @return Image
*/ */
public function asset(): Image public function asset(): Image
@@ -183,7 +192,8 @@ class File extends ModelWithContent
/** /**
* Store the template in addition to the * Store the template in addition to the
* other content. * other content.
*
* @internal
* @param array $data * @param array $data
* @param string|null $languageCode * @param string|null $languageCode
* @return array * @return array
@@ -199,6 +209,7 @@ class File extends ModelWithContent
* Returns the directory in which * Returns the directory in which
* the content file is located * the content file is located
* *
* @internal
* @return string * @return string
*/ */
public function contentFileDirectory(): string public function contentFileDirectory(): string
@@ -209,6 +220,7 @@ class File extends ModelWithContent
/** /**
* Filename for the content file * Filename for the content file
* *
* @internal
* @return string * @return string
*/ */
public function contentFileName(): string public function contentFileName(): string
@@ -222,6 +234,7 @@ class File extends ModelWithContent
* used in the panel, when the file * used in the panel, when the file
* gets dragged onto a textarea * gets dragged onto a textarea
* *
* @internal
* @param string $type * @param string $type
* @param bool $absolute * @param bool $absolute
* @return string * @return string
@@ -301,6 +314,7 @@ class File extends ModelWithContent
/** /**
* Create a unique media hash * Create a unique media hash
* *
* @internal
* @return string * @return string
*/ */
public function mediaHash(): string public function mediaHash(): string
@@ -311,6 +325,7 @@ class File extends ModelWithContent
/** /**
* Returns the absolute path to the file in the public media folder * Returns the absolute path to the file in the public media folder
* *
* @internal
* @return string * @return string
*/ */
public function mediaRoot(): string public function mediaRoot(): string
@@ -321,6 +336,7 @@ class File extends ModelWithContent
/** /**
* Returns the absolute Url to the file in the public media folder * Returns the absolute Url to the file in the public media folder
* *
* @internal
* @return string * @return string
*/ */
public function mediaUrl(): string public function mediaUrl(): string
@@ -329,9 +345,7 @@ class File extends ModelWithContent
} }
/** /**
* Alias for the old way of fetching File * @deprecated 3.0.0 Use `File::content()` instead
* content. Nowadays `File::content()` should
* be used instead.
* *
* @return Content * @return Content
*/ */
@@ -345,6 +359,7 @@ class File extends ModelWithContent
* This is normally the parent page * This is normally the parent page
* or the site object. * or the site object.
* *
* @internal
* @return Site|Page * @return Site|Page
*/ */
public function model() public function model()
@@ -365,6 +380,7 @@ class File extends ModelWithContent
/** /**
* Panel icon definition * Panel icon definition
* *
* @internal
* @param array $params * @param array $params
* @return array * @return array
*/ */
@@ -415,6 +431,7 @@ class File extends ModelWithContent
/** /**
* Panel image definition * Panel image definition
* *
* @internal
* @param string|array|false $settings * @param string|array|false $settings
* @param array $thumbSettings * @param array $thumbSettings
* @return array * @return array
@@ -455,6 +472,7 @@ class File extends ModelWithContent
/** /**
* Returns the full path without leading slash * Returns the full path without leading slash
* *
* @internal
* @return string * @return string
*/ */
public function panelPath(): string public function panelPath(): string
@@ -466,6 +484,7 @@ class File extends ModelWithContent
* Returns the url to the editing view * Returns the url to the editing view
* in the panel * in the panel
* *
* @internal
* @param bool $relative * @param bool $relative
* @return string * @return string
*/ */
@@ -487,6 +506,7 @@ class File extends ModelWithContent
/** /**
* Returns the parent id if a parent exists * Returns the parent id if a parent exists
* *
* @internal
* @return string|null * @return string|null
*/ */
public function parentId(): ?string public function parentId(): ?string
@@ -525,6 +545,7 @@ class File extends ModelWithContent
/** /**
* Creates a string query, starting from the model * Creates a string query, starting from the model
* *
* @internal
* @param string|null $query * @param string|null $query
* @param string|null $expect * @param string|null $expect
* @return mixed * @return mixed
@@ -646,6 +667,7 @@ class File extends ModelWithContent
/** /**
* Returns the parent Files collection * Returns the parent Files collection
* @internal
* *
* @return Files * @return Files
*/ */

View File

@@ -206,6 +206,7 @@ trait FileActions
/** /**
* Alias for changeName * Alias for changeName
* @deprecated
* *
* @param string $name * @param string $name
* @param bool $sanitize * @param bool $sanitize

View File

@@ -65,7 +65,7 @@ trait FileFoundation
} }
/** /**
* Returns the Asset object * Returns the Image object
*^ *^
* @return Image * @return Image
*/ */
@@ -148,7 +148,7 @@ trait FileFoundation
} }
/** /**
* Returns the paren app instance * Returns the app instance
* *
* @return App * @return App
*/ */

View File

@@ -90,6 +90,46 @@ trait FileModifications
]); ]);
} }
/**
* Create a srcset definition for the given sizes
* Sizes can be defined as a simple array. They can
* also be set up in the config with the thumbs.srcsets option.
* @since 3.1.0
*
* @param array|string $sizes
* @return string
*/
public function srcset($sizes = null): ?string
{
if (empty($sizes) === true) {
$sizes = $this->kirby()->option('thumbs.srcsets.default', []);
}
if (is_string($sizes) === true) {
$sizes = $this->kirby()->option('thumbs.srcsets.' . $sizes, []);
}
if (is_array($sizes) === false || empty($sizes) === true) {
return null;
}
$set = [];
foreach ($sizes as $key => $value) {
if (is_string($value) === true) {
$size = $key;
$attr = $value;
} else {
$size = $value;
$attr = $value . 'w';
}
$set[] = $this->resize($size)->url() . ' ' . $attr;
}
return implode(', ', $set);
}
/** /**
* Creates a modified version of images * Creates a modified version of images
* The media manager takes care of generating * The media manager takes care of generating

View File

@@ -64,7 +64,7 @@ class FileRules
public static function delete(File $file): bool public static function delete(File $file): bool
{ {
if ($file->permissions()->delete() !== true) { if ($file->permissions()->delete() !== true) {
throw new LogicException('The file cannot be deleted'); throw new PermissionException('The file cannot be deleted');
} }
return true; return true;
@@ -73,7 +73,7 @@ class FileRules
public static function replace(File $file, Image $upload): bool public static function replace(File $file, Image $upload): bool
{ {
if ($file->permissions()->replace() !== true) { if ($file->permissions()->replace() !== true) {
throw new LogicException('The file cannot be replaced'); throw new PermissionException('The file cannot be replaced');
} }
static::validMime($file, $upload->mime()); static::validMime($file, $upload->mime());
@@ -94,7 +94,7 @@ class FileRules
public static function update(File $file, array $content = []): bool public static function update(File $file, array $content = []): bool
{ {
if ($file->permissions()->update() !== true) { if ($file->permissions()->update() !== true) {
throw new LogicException('The file cannot be updated'); throw new PermissionException('The file cannot be updated');
} }
return true; return true;

View File

@@ -3,10 +3,17 @@
namespace Kirby\Cms; namespace Kirby\Cms;
/** /**
* An extended version of the Collection * The `$files` object extends the general
* class, that has custom find methods and * `Collection` class and refers to a
* a Files::factory method to convert an array * collection of files, i.e. images, documents
* into a Files collection. * etc. Files can be filtered, searched,
* converted, modified or evaluated with the
* following methods:
*
* @package Kirby Cms
* @author Bastian Allgeier <bastian@getkirby.com>
* @link http://getkirby.com
* @copyright Bastian Allgeier
*/ */
class Files extends Collection class Files extends Collection
{ {

View File

@@ -166,8 +166,7 @@ trait HasChildren
} }
/** /**
* Deprecated! Use Page::hasUnlistedChildren * @deprecated 3.0.0 Use `Page::hasUnlistedChildren` instead
*
* @return boolean * @return boolean
*/ */
public function hasInvisibleChildren(): bool public function hasInvisibleChildren(): bool
@@ -196,8 +195,7 @@ trait HasChildren
} }
/** /**
* Deprecated! Use Page::hasListedChildren * @deprecated 3.0.0 Use `Page::hasListedChildren` instead
*
* @return boolean * @return boolean
*/ */
public function hasVisibleChildren(): bool public function hasVisibleChildren(): bool

View File

@@ -16,6 +16,7 @@ trait HasMethods
* Calls a registered method class with the * Calls a registered method class with the
* passed arguments * passed arguments
* *
* @internal
* @param string $method * @param string $method
* @param array $args * @param array $args
* @return mixed * @return mixed
@@ -28,6 +29,7 @@ trait HasMethods
/** /**
* Checks if the object has a registered method * Checks if the object has a registered method
* *
* @internal
* @param string $method * @param string $method
* @return boolean * @return boolean
*/ */

View File

@@ -3,9 +3,14 @@
namespace Kirby\Cms; namespace Kirby\Cms;
/** /**
* Custom extension of the Toolkit Html builder class * The `Html` class provides methods for building
* that overwrites the Html::a method to include Cms * common HTML tags and also contains some helper
* Url handling. * methods.
*
* @package Kirby Cms
* @author Bastian Allgeier <bastian@getkirby.com>
* @link http://getkirby.com
* @copyright Bastian Allgeier
*/ */
class Html extends \Kirby\Toolkit\Html class Html extends \Kirby\Toolkit\Html
{ {

View File

@@ -65,6 +65,7 @@ class Ingredients
* Resolves all ingredient callbacks * Resolves all ingredient callbacks
* and creates a plain array * and creates a plain array
* *
* @internal
* @param array $ingredients * @param array $ingredients
* @return self * @return self
*/ */

View File

@@ -11,8 +11,19 @@ use Kirby\Toolkit\F;
use Kirby\Toolkit\Str; use Kirby\Toolkit\Str;
/** /**
* Represents a content language * The `$language` object represents
* in a multi-language setup * a single language in a multi-language
* Kirby setup. You can, for example,
* use the methods of this class to get
* the name or locale of a language,
* check for the default language,
* get translation strings and many
* more things.
*
* @package Kirby Cms
* @author Bastian Allgeier <bastian@getkirby.com>
* @link http://getkirby.com
* @copyright Bastian Allgeier
*/ */
class Language extends Model class Language extends Model
{ {
@@ -145,6 +156,7 @@ class Language extends Model
/** /**
* Creates a new language object * Creates a new language object
* *
* @internal
* @param array $props * @param array $props
* @return self * @return self
*/ */
@@ -179,6 +191,7 @@ class Language extends Model
* Delete the current language and * Delete the current language and
* all its translation files * all its translation files
* *
* @internal
* @return boolean * @return boolean
*/ */
public function delete(): bool public function delete(): bool
@@ -321,6 +334,7 @@ class Language extends Model
/** /**
* Saves the language settings in the languages folder * Saves the language settings in the languages folder
* *
* @internal
* @return self * @return self
*/ */
public function save(): self public function save(): self
@@ -447,6 +461,7 @@ class Language extends Model
/** /**
* Update language properties and save them * Update language properties and save them
* *
* @internal
* @param array $props * @param array $props
* @return self * @return self
*/ */

View File

@@ -23,6 +23,7 @@ class Languages extends Collection
/** /**
* Creates a new language with the given props * Creates a new language with the given props
* *
* @internal
* @param array $props * @param array $props
* @return Language * @return Language
*/ */
@@ -46,8 +47,7 @@ class Languages extends Collection
} }
/** /**
* Deprecated version of static::default(); * @deprecated 3.0.0 Use `Languages::default()`instead
*
* @return Language|null * @return Language|null
*/ */
public function findDefault(): ?Language public function findDefault(): ?Language
@@ -58,6 +58,7 @@ class Languages extends Collection
/** /**
* Convert all defined languages to a collection * Convert all defined languages to a collection
* *
* @internal
* @return self * @return self
*/ */
public static function load(): self public static function load(): self

View File

@@ -84,6 +84,7 @@ abstract class Model
/** /**
* Setter for the parent Site object * Setter for the parent Site object
* *
* @internal
* @param Site|null $site * @param Site|null $site
* @return self * @return self
*/ */

View File

@@ -88,6 +88,7 @@ abstract class ModelWithContent extends Model
/** /**
* Returns the absolute path to the content file * Returns the absolute path to the content file
* *
* @internal
* @param string|null $languageCode * @param string|null $languageCode
* @param bool $force * @param bool $force
* @return string * @return string
@@ -123,6 +124,7 @@ abstract class ModelWithContent extends Model
* Prepares the content that should be written * Prepares the content that should be written
* to the text file * to the text file
* *
* @internal
* @param array $data * @param array $data
* @param string $languageCode * @param string $languageCode
* @return array * @return array
@@ -137,6 +139,7 @@ abstract class ModelWithContent extends Model
* folder in which the content file is * folder in which the content file is
* located * located
* *
* @internal
* @return string|null * @return string|null
*/ */
public function contentFileDirectory(): ?string public function contentFileDirectory(): ?string
@@ -147,6 +150,7 @@ abstract class ModelWithContent extends Model
/** /**
* Returns the extension of the content file * Returns the extension of the content file
* *
* @internal
* @return string * @return string
*/ */
public function contentFileExtension(): string public function contentFileExtension(): string
@@ -157,6 +161,7 @@ abstract class ModelWithContent extends Model
/** /**
* Needs to be declared by the final model * Needs to be declared by the final model
* *
* @internal
* @return string * @return string
*/ */
abstract public function contentFileName(): string; abstract public function contentFileName(): string;
@@ -218,7 +223,7 @@ abstract class ModelWithContent extends Model
} }
/** /**
* Checks if the model data has any errors * Checks if the data has any errors
* *
* @return boolean * @return boolean
*/ */
@@ -230,6 +235,7 @@ abstract class ModelWithContent extends Model
/** /**
* Read the content from the content file * Read the content from the content file
* *
* @internal
* @param string|null $languageCode * @param string|null $languageCode
* @return array * @return array
*/ */
@@ -252,6 +258,7 @@ abstract class ModelWithContent extends Model
/** /**
* Stores the content on disk * Stores the content on disk
* *
* @internal
* @param string $languageCode * @param string $languageCode
* @param array $data * @param array $data
* @param bool $overwrite * @param bool $overwrite
@@ -428,6 +435,7 @@ abstract class ModelWithContent extends Model
* Low level data writer method * Low level data writer method
* to store the given data on disk or anywhere else * to store the given data on disk or anywhere else
* *
* @internal
* @param array $data * @param array $data
* @param string $languageCode * @param string $languageCode
* @return boolean * @return boolean

View File

@@ -12,10 +12,10 @@ use Kirby\Toolkit\Str;
use Throwable; use Throwable;
/** /**
* The Page class is the heart and soul of * The `$page` object is the heart and
* Kirby. It is used to construct pages and * soul of Kirby. It is used to construct
* all their dependencies like children, * pages and all their dependencies like
* files, content, etc. * children, files, content, etc.
* *
* @package Kirby Cms * @package Kirby Cms
* @author Bastian Allgeier <bastian@getkirby.com> * @author Bastian Allgeier <bastian@getkirby.com>
@@ -207,6 +207,7 @@ class Page extends ModelWithContent
/** /**
* Returns the url to the api endpoint * Returns the url to the api endpoint
* *
* @internal
* @param bool $relative * @param bool $relative
* @return string * @return string
*/ */
@@ -295,6 +296,7 @@ class Page extends ModelWithContent
/** /**
* Prepares the content for the write method * Prepares the content for the write method
* *
* @internal
* @return array * @return array
*/ */
public function contentFileData(array $data, string $languageCode = null): array public function contentFileData(array $data, string $languageCode = null): array
@@ -309,6 +311,7 @@ class Page extends ModelWithContent
* Returns the content text file * Returns the content text file
* which is found by the inventory method * which is found by the inventory method
* *
* @internal
* @param string $languageCode * @param string $languageCode
* @return string * @return string
*/ */
@@ -320,6 +323,7 @@ class Page extends ModelWithContent
/** /**
* Call the page controller * Call the page controller
* *
* @internal
* @param array $data * @param array $data
* @param string $contentType * @param string $contentType
* @return array * @return array
@@ -397,6 +401,7 @@ class Page extends ModelWithContent
* used in the panel, when the page * used in the panel, when the page
* gets dragged onto a textarea * gets dragged onto a textarea
* *
* @internal
* @return string * @return string
*/ */
public function dragText($type = 'kirbytext'): string public function dragText($type = 'kirbytext'): string
@@ -423,6 +428,7 @@ class Page extends ModelWithContent
* Constructs a Page object and also * Constructs a Page object and also
* takes page models into account. * takes page models into account.
* *
* @internal
* @return self * @return self
*/ */
public static function factory($props): self public static function factory($props): self
@@ -483,6 +489,7 @@ class Page extends ModelWithContent
* Returns the inventory of files * Returns the inventory of files
* children and content files * children and content files
* *
* @internal
* @return array * @return array
*/ */
public function inventory(): array public function inventory(): array
@@ -703,8 +710,7 @@ class Page extends ModelWithContent
} }
/** /**
* Checks if the page is invisible * @deprecated 3.0.0 Use `Page::isUnlisted()` intead
*
* @return bool * @return bool
*/ */
public function isInvisible(): bool public function isInvisible(): bool
@@ -768,6 +774,7 @@ class Page extends ModelWithContent
* Checks if the page access is verified. * Checks if the page access is verified.
* This is only used for drafts so far. * This is only used for drafts so far.
* *
* @internal
* @param string $token * @param string $token
* @return boolean * @return boolean
*/ */
@@ -785,8 +792,7 @@ class Page extends ModelWithContent
} }
/** /**
* Checks if the page is visible * @deprecated 3.0.0 Use `Page::isListed()` intead
*
* @return bool * @return bool
*/ */
public function isVisible(): bool public function isVisible(): bool
@@ -797,6 +803,7 @@ class Page extends ModelWithContent
/** /**
* Returns the root to the media folder for the page * Returns the root to the media folder for the page
* *
* @internal
* @return string * @return string
*/ */
public function mediaRoot(): string public function mediaRoot(): string
@@ -805,8 +812,9 @@ class Page extends ModelWithContent
} }
/** /**
* The page's base url for any files * The page's base URL for any files
* *
* @internal
* @return string * @return string
*/ */
public function mediaUrl(): string public function mediaUrl(): string
@@ -815,8 +823,9 @@ class Page extends ModelWithContent
} }
/** /**
* Creates a Page model if it has been registered * Creates a page model if it has been registered
* *
* @internal
* @param string $name * @param string $name
* @param array $props * @param array $props
* @return Page * @return Page
@@ -860,7 +869,8 @@ class Page extends ModelWithContent
* Returns the panel icon definition * Returns the panel icon definition
* according to the blueprint settings * according to the blueprint settings
* *
* @params array $params * @internal
* @param array $params
* @return array * @return array
*/ */
public function panelIcon(array $params = null): array public function panelIcon(array $params = null): array
@@ -896,6 +906,7 @@ class Page extends ModelWithContent
* Returns the escaped Id, which is * Returns the escaped Id, which is
* used in the panel to make routing work properly * used in the panel to make routing work properly
* *
* @internal
* @return string * @return string
*/ */
public function panelId(): string public function panelId(): string
@@ -904,6 +915,7 @@ class Page extends ModelWithContent
} }
/** /**
* @internal
* @param string|array|false $settings * @param string|array|false $settings
* @param array|null $thumbSettings * @param array|null $thumbSettings
* @return array|null * @return array|null
@@ -939,6 +951,7 @@ class Page extends ModelWithContent
/** /**
* Returns the full path without leading slash * Returns the full path without leading slash
* *
* @internal
* @return string * @return string
*/ */
public function panelPath(): string public function panelPath(): string
@@ -950,6 +963,7 @@ class Page extends ModelWithContent
* Returns the url to the editing view * Returns the url to the editing view
* in the panel * in the panel
* *
* @internal
* @return string * @return string
*/ */
public function panelUrl(bool $relative = false): string public function panelUrl(bool $relative = false): string
@@ -974,6 +988,7 @@ class Page extends ModelWithContent
/** /**
* Returns the parent id, if a parent exists * Returns the parent id, if a parent exists
* *
* @internal
* @return string|null * @return string|null
*/ */
public function parentId(): ?string public function parentId(): ?string
@@ -990,6 +1005,7 @@ class Page extends ModelWithContent
* which can either be another Page * which can either be another Page
* or the Site * or the Site
* *
* @internal
* @return Page|Site * @return Page|Site
*/ */
public function parentModel() public function parentModel()
@@ -1028,6 +1044,7 @@ class Page extends ModelWithContent
/** /**
* Draft preview Url * Draft preview Url
* *
* @internal
* @return string|null * @return string|null
*/ */
public function previewUrl(): ?string public function previewUrl(): ?string
@@ -1054,6 +1071,7 @@ class Page extends ModelWithContent
/** /**
* Creates a string query, starting from the model * Creates a string query, starting from the model
* *
* @internal
* @param string|null $query * @param string|null $query
* @param string|null $expect * @param string|null $expect
* @return mixed * @return mixed
@@ -1143,6 +1161,7 @@ class Page extends ModelWithContent
} }
/** /**
* @internal
* @return Template * @return Template
*/ */
public function representation($type) public function representation($type)
@@ -1514,6 +1533,7 @@ class Page extends ModelWithContent
/** /**
* Builds the Url for a specific language * Builds the Url for a specific language
* *
* @internal
* @param string $language * @param string $language
* @param array $options * @param array $options
* @return string * @return string

View File

@@ -28,7 +28,9 @@ class PageRules
if ($page->permissions()->changeSlug() !== true) { if ($page->permissions()->changeSlug() !== true) {
throw new PermissionException([ throw new PermissionException([
'key' => 'page.changeSlug.permission', 'key' => 'page.changeSlug.permission',
'data' => ['slug' => $page->slug()] 'data' => [
'slug' => $page->slug()
]
]); ]);
} }
@@ -39,7 +41,9 @@ class PageRules
if ($duplicate->is($page) === false) { if ($duplicate->is($page) === false) {
throw new DuplicateException([ throw new DuplicateException([
'key' => 'page.duplicate', 'key' => 'page.duplicate',
'data' => ['slug' => $slug] 'data' => [
'slug' => $slug
]
]); ]);
} }
} }
@@ -48,7 +52,9 @@ class PageRules
if ($duplicate->is($page) === false) { if ($duplicate->is($page) === false) {
throw new DuplicateException([ throw new DuplicateException([
'key' => 'page.draft.duplicate', 'key' => 'page.draft.duplicate',
'data' => ['slug' => $slug] 'data' => [
'slug' => $slug
]
]); ]);
} }
} }
@@ -79,14 +85,18 @@ class PageRules
if ($page->permissions()->changeStatus() !== true) { if ($page->permissions()->changeStatus() !== true) {
throw new PermissionException([ throw new PermissionException([
'key' => 'page.changeStatus.permission', 'key' => 'page.changeStatus.permission',
'data' => ['slug' => $page->slug()] 'data' => [
'slug' => $page->slug()
]
]); ]);
} }
if ($page->isHomeOrErrorPage() === true) { if ($page->isHomeOrErrorPage() === true) {
throw new PermissionException([ throw new PermissionException([
'key' => 'page.changeStatus.toDraft.invalid', 'key' => 'page.changeStatus.toDraft.invalid',
'data' => ['slug' => $page->slug()] 'data' => [
'slug' => $page->slug()
]
]); ]);
} }
@@ -101,7 +111,9 @@ class PageRules
if ($page->isSortable() !== true) { if ($page->isSortable() !== true) {
throw new PermissionException([ throw new PermissionException([
'key' => 'page.sort.permission', 'key' => 'page.sort.permission',
'data' => ['slug' => $page->slug()] 'data' => [
'slug' => $page->slug()
]
]); ]);
} }
@@ -111,7 +123,9 @@ class PageRules
if ($page->permissions()->changeStatus() !== true) { if ($page->permissions()->changeStatus() !== true) {
throw new PermissionException([ throw new PermissionException([
'key' => 'page.changeStatus.permission', 'key' => 'page.changeStatus.permission',
'data' => ['slug' => $page->slug()] 'data' => [
'slug' => $page->slug()
]
]); ]);
} }
@@ -134,7 +148,9 @@ class PageRules
if ($page->permissions()->changeStatus() !== true) { if ($page->permissions()->changeStatus() !== true) {
throw new PermissionException([ throw new PermissionException([
'key' => 'page.changeStatus.permission', 'key' => 'page.changeStatus.permission',
'data' => ['slug' => $page->slug()] 'data' => [
'slug' => $page->slug()
]
]); ]);
} }
@@ -146,7 +162,9 @@ class PageRules
if ($page->permissions()->changeTemplate() !== true) { if ($page->permissions()->changeTemplate() !== true) {
throw new PermissionException([ throw new PermissionException([
'key' => 'page.changeTemplate.permission', 'key' => 'page.changeTemplate.permission',
'data' => ['slug' => $page->slug()] 'data' => [
'slug' => $page->slug()
]
]); ]);
} }
@@ -171,7 +189,9 @@ class PageRules
if ($page->permissions()->changeTitle() !== true) { if ($page->permissions()->changeTitle() !== true) {
throw new PermissionException([ throw new PermissionException([
'key' => 'page.changeTitle.permission', 'key' => 'page.changeTitle.permission',
'data' => ['slug' => $page->slug()] 'data' => [
'slug' => $page->slug()
]
]); ]);
} }
@@ -183,12 +203,19 @@ class PageRules
if ($page->exists() === true) { if ($page->exists() === true) {
throw new DuplicateException([ throw new DuplicateException([
'key' => 'page.draft.duplicate', 'key' => 'page.draft.duplicate',
'data' => ['slug' => $page->slug()] 'data' => [
'slug' => $page->slug()
]
]); ]);
} }
if ($page->permissions()->create() !== true) { if ($page->permissions()->create() !== true) {
throw new PermissionException(['key' => 'page.create.permission']); throw new PermissionException([
'key' => 'page.create.permission',
'data' => [
'slug' => $page->slug()
]
]);
} }
$siblings = $page->parentModel()->children(); $siblings = $page->parentModel()->children();
@@ -215,7 +242,12 @@ class PageRules
public static function delete(Page $page, bool $force = false): bool public static function delete(Page $page, bool $force = false): bool
{ {
if ($page->permissions()->delete() !== true) { if ($page->permissions()->delete() !== true) {
throw new PermissionException(['key' => 'page.delete.permission']); throw new PermissionException([
'key' => 'page.delete.permission',
'data' => [
'slug' => $page->slug()
]
]);
} }
if (($page->hasChildren() === true || $page->hasDrafts() === true) && $force === false) { if (($page->hasChildren() === true || $page->hasDrafts() === true) && $force === false) {

View File

@@ -6,7 +6,7 @@ trait PageSiblings
{ {
/** /**
* @deprecated Use Page::hasNextUnlisted instead * @deprecated 3.0.0 Use `Page::hasNextUnlisted` instead
* @return boolean * @return boolean
*/ */
public function hasNextInvisible(): bool public function hasNextInvisible(): bool
@@ -26,7 +26,7 @@ trait PageSiblings
} }
/** /**
* @deprecated Use Page::hasNextListed instead * @deprecated Use `Page::hasNextListed` instead
* @return boolean * @return boolean
*/ */
public function hasNextVisible(): bool public function hasNextVisible(): bool
@@ -46,7 +46,7 @@ trait PageSiblings
} }
/** /**
* @deprecated Use Page::hasPrevUnlisted instead * @deprecated Use `Page::hasPrevUnlisted` instead
* @return boolean * @return boolean
*/ */
public function hasPrevInvisible(): bool public function hasPrevInvisible(): bool
@@ -77,7 +77,7 @@ trait PageSiblings
} }
/** /**
* @deprecated Use Page::hasPrevListed instead * @deprecated Use `Page::hasPrevListed instead`
* @return boolean * @return boolean
*/ */
public function hasPrevVisible(): bool public function hasPrevVisible(): bool
@@ -86,7 +86,7 @@ trait PageSiblings
} }
/** /**
* @deprecated Use Page::nextUnlisted() instead * @deprecated Use `Page::nextUnlisted()` instead
* @return self|null * @return self|null
*/ */
public function nextInvisible() public function nextInvisible()
@@ -115,7 +115,7 @@ trait PageSiblings
} }
/** /**
* @deprecated Use Page::prevListed() instead * @deprecated Use `Page::prevListed()` instead
* @return self|null * @return self|null
*/ */
public function nextVisible() public function nextVisible()
@@ -124,7 +124,7 @@ trait PageSiblings
} }
/** /**
* @deprecated Use Page::prevUnlisted() instead * @deprecated Use `Page::prevUnlisted()` instead
* @return self|null * @return self|null
*/ */
public function prevInvisible() public function prevInvisible()
@@ -153,7 +153,7 @@ trait PageSiblings
} }
/** /**
* @deprecated Use Page::prevListed() instead * @deprecated Use `Page::prevListed()` instead
* @return self|null * @return self|null
*/ */
public function prevVisible() public function prevVisible()

View File

@@ -5,22 +5,14 @@ namespace Kirby\Cms;
use Kirby\Toolkit\F; use Kirby\Toolkit\F;
/** /**
* The Pages collection contains * The `$pages` object refers to a
* any number and mixture of page objects * collection of pages. The pages in this
* They don't necessarily have to belong * collection can have the same or different
* to the same parent unless it is passed * parents, they can actually exist as
* as second argument in the constructor. * subfolders in the content folder or be
* * virtual pages created from a database,
* Pages collection can be constructed very * an Excel sheet, any API or any other
* easily: * source.
*
* ```php
* $collection = new Pages([
* new Page(['id' => 'project-a']),
* new Page(['id' => 'project-b']),
* new Page(['id' => 'project-c']),
* ]);
* ```
* *
* @package Kirby Cms * @package Kirby Cms
* @author Bastian Allgeier <bastian@getkirby.com> * @author Bastian Allgeier <bastian@getkirby.com>

View File

@@ -6,9 +6,13 @@ use Kirby\Http\Uri;
use Kirby\Toolkit\Pagination as BasePagination; use Kirby\Toolkit\Pagination as BasePagination;
/** /**
* The extended Pagination class handles * The `$pagination` object divides
* URLs in addition to the pagination features * a collection of pages, files etc.
* from Kirby\Toolkit\Pagination * into discrete pages consisting of
* the number of defined items. The
* pagination object can then be used
* to navigate between these pages,
* create a navigation etc.
* *
* @package Kirby Cms * @package Kirby Cms
* @author Bastian Allgeier <bastian@getkirby.com> * @author Bastian Allgeier <bastian@getkirby.com>

View File

@@ -2,6 +2,7 @@
namespace Kirby\Cms; namespace Kirby\Cms;
use Kirby\Http\Response;
use Kirby\Toolkit\Dir; use Kirby\Toolkit\Dir;
use Kirby\Toolkit\F; use Kirby\Toolkit\F;
@@ -104,9 +105,11 @@ class PluginAssets
$target = $plugin->mediaRoot() . '/' . $filename; $target = $plugin->mediaRoot() . '/' . $filename;
$url = $plugin->mediaUrl() . '/' . $filename; $url = $plugin->mediaUrl() . '/' . $filename;
F::link($source, $target, 'symlink'); if (F::link($source, $target, 'symlink') === true) {
return Response::redirect($url);
}
return $url; return Response::file($source);
} }
} }

View File

@@ -57,6 +57,17 @@ class Search
$keys = array_keys($data); $keys = array_keys($data);
$keys[] = 'id'; $keys[] = 'id';
if (is_a($item, User::class) === true) {
$keys[] = 'email';
$keys[] = 'role';
} elseif (is_a($item, Page::class) === true) {
// apply the default score for pages
$options['score'] = array_merge([
'id' => 64,
'title' => 64,
], $options['score']);
}
if (empty($options['fields']) === false) { if (empty($options['fields']) === false) {
$keys = array_intersect($keys, $options['fields']); $keys = array_intersect($keys, $options['fields']);
} }
@@ -66,7 +77,7 @@ class Search
foreach ($keys as $key) { foreach ($keys as $key) {
$score = $options['score'][$key] ?? 1; $score = $options['score'][$key] ?? 1;
$value = $key === 'id' ? $item->id() : $data[$key]; $value = $data[$key] ?? (string)$item->$key();
$lowerValue = strtolower($value); $lowerValue = strtolower($value);

View File

@@ -9,9 +9,10 @@ use Kirby\Toolkit\A;
use Kirby\Toolkit\Str; use Kirby\Toolkit\Str;
/** /**
* The Site class is the root element * The `$site` object is the root element
* for any site with pages. It represents * for any site with pages. It represents
* the main content folder with its site.txt * the main content folder with its
* `site.txt`.
* *
* @package Kirby Cms * @package Kirby Cms
* @author Bastian Allgeier <bastian@getkirby.com> * @author Bastian Allgeier <bastian@getkirby.com>
@@ -143,6 +144,7 @@ class Site extends ModelWithContent
/** /**
* Returns the url to the api endpoint * Returns the url to the api endpoint
* *
* @internal
* @param bool $relative * @param bool $relative
* @return string * @return string
*/ */
@@ -217,6 +219,7 @@ class Site extends ModelWithContent
/** /**
* Prepares the content for the write method * Prepares the content for the write method
* *
* @internal
* @return array * @return array
*/ */
public function contentFileData(array $data, string $languageCode = null): array public function contentFileData(array $data, string $languageCode = null): array
@@ -229,6 +232,7 @@ class Site extends ModelWithContent
/** /**
* Filename for the content file * Filename for the content file
* *
* @internal
* @return string * @return string
*/ */
public function contentFileName(): string public function contentFileName(): string
@@ -257,6 +261,7 @@ class Site extends ModelWithContent
/** /**
* Returns the global error page id * Returns the global error page id
* *
* @internal
* @return string * @return string
*/ */
public function errorPageId(): string public function errorPageId(): string
@@ -295,6 +300,7 @@ class Site extends ModelWithContent
/** /**
* Returns the global home page id * Returns the global home page id
* *
* @internal
* @return string * @return string
*/ */
public function homePageId(): string public function homePageId(): string
@@ -306,6 +312,7 @@ class Site extends ModelWithContent
* Creates an inventory of all files * Creates an inventory of all files
* and children in the site directory * and children in the site directory
* *
* @internal
* @return array * @return array
*/ */
public function inventory(): array public function inventory(): array
@@ -330,14 +337,19 @@ class Site extends ModelWithContent
* @param Site $site * @param Site $site
* @return bool * @return bool
*/ */
public function is(Site $site): bool public function is($site): bool
{ {
if (is_a($site, Site::class) === false) {
return false;
}
return $this === $site; return $this === $site;
} }
/** /**
* Returns the root to the media folder for the site * Returns the root to the media folder for the site
* *
* @internal
* @return string * @return string
*/ */
public function mediaRoot(): string public function mediaRoot(): string
@@ -348,6 +360,7 @@ class Site extends ModelWithContent
/** /**
* The site's base url for any files * The site's base url for any files
* *
* @internal
* @return string * @return string
*/ */
public function mediaUrl(): string public function mediaUrl(): string
@@ -410,6 +423,7 @@ class Site extends ModelWithContent
/** /**
* Returns the full path without leading slash * Returns the full path without leading slash
* *
* @internal
* @return string * @return string
*/ */
public function panelPath(): string public function panelPath(): string
@@ -421,6 +435,7 @@ class Site extends ModelWithContent
* Returns the url to the editing view * Returns the url to the editing view
* in the panel * in the panel
* *
* @internal
* @param bool $relative * @param bool $relative
* @return string * @return string
*/ */
@@ -446,6 +461,7 @@ class Site extends ModelWithContent
/** /**
* Creates a string query, starting from the model * Creates a string query, starting from the model
* *
* @internal
* @param string|null $query * @param string|null $query
* @param string|null $expect * @param string|null $expect
* @return mixed * @return mixed
@@ -551,6 +567,7 @@ class Site extends ModelWithContent
/** /**
* Sets the current page object * Sets the current page object
* *
* @internal
* @param Page|null $page * @param Page|null $page
* @return self * @return self
*/ */
@@ -628,8 +645,9 @@ class Site extends ModelWithContent
/** /**
* Returns the translated url * Returns the translated url
* *
* @params string $languageCode * @internal
* @params array $options * @param string $languageCode
* @param array $options
* @return string * @return string
*/ */
public function urlForLanguage(string $languageCode = null, array $options = null): string public function urlForLanguage(string $languageCode = null, array $options = null): string
@@ -646,6 +664,7 @@ class Site extends ModelWithContent
* id or page object and * id or page object and
* returns the current page * returns the current page
* *
* @internal
* @param string|Page $page * @param string|Page $page
* @param string|null $languageCode * @param string|null $languageCode
* @return Page * @return Page

View File

@@ -91,18 +91,6 @@ class StructureObject extends Model
return $this->content = new Content($this->content, $this->parent()); return $this->content = new Content($this->content, $this->parent());
} }
/**
* Returns a formatted date field from the content
*
* @param string $format
* @param string $field
* @return Field
*/
public function date(string $format = null, $field = 'date')
{
return $this->content()->get($field)->toDate($format);
}
/** /**
* Returns the required id * Returns the required id
* *

View File

@@ -6,10 +6,18 @@ use Kirby\Http\Url as BaseUrl;
use Kirby\Toolkit\Str; use Kirby\Toolkit\Str;
/** /**
* Extension of the Kirby\Http\Url class * The `Url` class extends the
* with a specific Url::home method that always * `Kirby\Http\Url` class. In addition
* creates the correct base Url and a template asset * to the methods of that class for dealing
* Url builder. * with URLs, it provides a specific
* `Url::home` method that always creates
* the correct base URL and a template asset
* URL builder.
*
* @package Kirby Cms
* @author Bastian Allgeier <bastian@getkirby.com>
* @link http://getkirby.com
* @copyright Bastian Allgeier
*/ */
class Url extends BaseUrl class Url extends BaseUrl
{ {
@@ -68,7 +76,7 @@ class Url extends BaseUrl
} }
// get a language url for the linked page, if the page can be found // get a language url for the linked page, if the page can be found
if ($language !== null && $kirby->multilang() === true && $page = page($path)) { if ($kirby->multilang() === true && $page = page($path)) {
$path = $page->url($language); $path = $page->url($language);
} }

View File

@@ -14,8 +14,8 @@ use Kirby\Toolkit\V;
use Throwable; use Throwable;
/** /**
* The User class represents * The `$user` object represents a
* panel users as well as frontend users. * single Panel or frontend user.
* *
* @package Kirby Cms * @package Kirby Cms
* @author Bastian Allgeier <bastian@getkirby.com> * @author Bastian Allgeier <bastian@getkirby.com>
@@ -134,6 +134,7 @@ class User extends ModelWithContent
/** /**
* Returns the url to the api endpoint * Returns the url to the api endpoint
* *
* @internal
* @param bool $relative * @param bool $relative
* @return string * @return string
*/ */
@@ -181,6 +182,7 @@ class User extends ModelWithContent
/** /**
* Prepares the content for the write method * Prepares the content for the write method
* *
* @internal
* @param array $data * @param array $data
* @param string $languageCode Not used so far * @param string $languageCode Not used so far
* @return array * @return array
@@ -202,6 +204,7 @@ class User extends ModelWithContent
/** /**
* Filename for the content file * Filename for the content file
* *
* @internal
* @return string * @return string
*/ */
public function contentFileName(): string public function contentFileName(): string
@@ -237,6 +240,7 @@ class User extends ModelWithContent
/** /**
* Hashes user password * Hashes user password
* *
* @internal
* @param string|null $password * @param string|null $password
* @return string|null * @return string|null
*/ */
@@ -416,6 +420,7 @@ class User extends ModelWithContent
/** /**
* Returns the root to the media folder for the user * Returns the root to the media folder for the user
* *
* @internal
* @return string * @return string
*/ */
public function mediaRoot(): string public function mediaRoot(): string
@@ -426,6 +431,7 @@ class User extends ModelWithContent
/** /**
* Returns the media url for the user object * Returns the media url for the user object
* *
* @internal
* @return string * @return string
*/ */
public function mediaUrl(): string public function mediaUrl(): string
@@ -471,6 +477,7 @@ class User extends ModelWithContent
/** /**
* Create a dummy nobody * Create a dummy nobody
* *
* @internal
* @return self * @return self
*/ */
public static function nobody(): self public static function nobody(): self
@@ -484,6 +491,7 @@ class User extends ModelWithContent
/** /**
* Returns the full path without leading slash * Returns the full path without leading slash
* *
* @internal
* @return string * @return string
*/ */
public function panelPath(): string public function panelPath(): string
@@ -495,6 +503,7 @@ class User extends ModelWithContent
* Returns the url to the editing view * Returns the url to the editing view
* in the panel * in the panel
* *
* @internal
* @param bool $relative * @param bool $relative
* @return string * @return string
*/ */
@@ -532,6 +541,7 @@ class User extends ModelWithContent
/** /**
* Creates a string query, starting from the model * Creates a string query, starting from the model
* *
* @internal
* @param string|null $query * @param string|null $query
* @param string|null $expect * @param string|null $expect
* @return mixed * @return mixed
@@ -776,7 +786,7 @@ class User extends ModelWithContent
throw new NotFoundException(['key' => 'user.password.undefined']); throw new NotFoundException(['key' => 'user.password.undefined']);
} }
if ($password === null) { if (Str::length($password) < 8) {
throw new InvalidArgumentException(['key' => 'user.password.invalid']); throw new InvalidArgumentException(['key' => 'user.password.invalid']);
} }

View File

@@ -6,11 +6,15 @@ use Kirby\Toolkit\Dir;
use Kirby\Toolkit\Str; use Kirby\Toolkit\Str;
/** /**
* Extension of the Collection class that * The `$users` object refers to a collection
* provides a Users::factory method to convert * of users with or without Panel access. Like
* an array into a Users collection with User * all collections, you can filter, modify,
* objects and a Users::load method to load * convert or check the users collection.
* user accounts from disk. *
* @package Kirby Cms
* @author Bastian Allgeier <bastian@getkirby.com>
* @link http://getkirby.com
* @copyright Bastian Allgeier
*/ */
class Users extends Collection class Users extends Collection
{ {

View File

@@ -6,20 +6,20 @@ use Exception;
use Kirby\Toolkit\F; use Kirby\Toolkit\F;
/** /**
* Universal Data writer and reader class. * The `Data` class provides readers and
* writers for data. The class comes with
* three handlers for `json`, `yaml` and
* `txt` encoded data, but can be extended
* and customized.
* *
* The read and write methods automatically * The read and write methods automatically
* detect, which data handler to use in order * detect, which data handler to use in order
* to correctly encode and decode passed data. * to correctly encode and decode passed data.
* *
* Data Handlers for the class can be
* extended and customized.
*
* @package Kirby * @package Kirby
* @author Bastian Allgeier <bastian@getkirby.com> * @author Bastian Allgeier <bastian@getkirby.com>
* @link http://getkirby.com * @link http://getkirby.com
* @copyright 2012 Bastian Allgeier * @copyright Bastian Allgeier
* @license MIT
*/ */
class Data class Data
{ {

View File

@@ -102,6 +102,12 @@ class Field extends Component
'before' => function ($before = null) { 'before' => function ($before = null) {
return I18n::translate($before, $before); return I18n::translate($before, $before);
}, },
/**
* Conditions when the field will be shown
*/
'when' => function ($when = null) {
return $when;
},
/** /**
* Default value for the field, which will be used when a Page/File/User is created * Default value for the field, which will be used when a Page/File/User is created
*/ */

View File

@@ -5,13 +5,13 @@ namespace Kirby\Http;
use Kirby\Toolkit\Str; use Kirby\Toolkit\Str;
/** /**
* This class makes cookie handling easy * The `Cookie` class helps you to
* handle cookies in your projects.
* *
* @package Kirby Http * @package Kirby Http
* @author Bastian Allgeier <bastian@getkirby.com> * @author Bastian Allgeier <bastian@getkirby.com>
* @link http://getkirby.com * @link http://getkirby.com
* @copyright Bastian Allgeier * @copyright Bastian Allgeier
* @license MIT
*/ */
class Cookie class Cookie
{ {

View File

@@ -5,13 +5,13 @@ namespace Kirby\Http;
use Kirby\Toolkit\F; use Kirby\Toolkit\F;
/** /**
* Makes sending HTTP headers a breeze * The Header class provides methods
* for sending HTTP headers.
* *
* @package Kirby Toolkit * @package Kirby Http
* @author Bastian Allgeier <bastian@getkirby.com> * @author Bastian Allgeier <bastian@getkirby.com>
* @link http://getkirby.com * @link http://getkirby.com
* @copyright Bastian Allgeier * @copyright Bastian Allgeier
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/ */
class Header class Header
{ {

View File

@@ -12,7 +12,7 @@ use Kirby\Toolkit\A;
use Kirby\Toolkit\Str; use Kirby\Toolkit\Str;
/** /**
* The Request class provides * The `Request` class provides
* a simple API to inspect incoming * a simple API to inspect incoming
* requests. * requests.
* *
@@ -154,7 +154,7 @@ class Request
/** /**
* Detects ajax requests * Detects ajax requests
* * @deprecated 3.1.0 No longer reliable, especially with the fetch api.
* @return boolean * @return boolean
*/ */
public function ajax(): bool public function ajax(): bool

View File

@@ -187,7 +187,7 @@ class Response
*/ */
public static function file(string $file) public static function file(string $file)
{ {
return new static(F::read($file), F::mime($file)); return new static(F::read($file), F::extensionToMime(F::extension($file)));
} }
/** /**

View File

@@ -155,6 +155,7 @@ class Route
/** /**
* Throws a specific exception to tell * Throws a specific exception to tell
* the router to jump to the next route * the router to jump to the next route
* @since 3.0.3
* *
* @return void * @return void
*/ */

View File

@@ -75,7 +75,13 @@ class ImageMagick extends Darkroom
// remove all null values and join the parts // remove all null values and join the parts
$command = implode(' ', array_filter($command)); $command = implode(' ', array_filter($command));
exec($command); // try to execute the command
exec($command, $output, $return);
// log broken commands
if ($return !== 0) {
error_log('The imagemagick convert command could not be executed: ' . $command);
}
return $options; return $options;
} }

View File

@@ -6,6 +6,10 @@ use Kirby\Exception\InvalidArgumentException;
use Kirby\Exception\LogicException; use Kirby\Exception\LogicException;
/** /**
* The session object can be used to
* store visitor preferences for your
* site throughout various requests.
*
* @package Kirby Session * @package Kirby Session
* @author Lukas Bestle <lukas@getkirby.com> * @author Lukas Bestle <lukas@getkirby.com>
* @link http://getkirby.com * @link http://getkirby.com

View File

@@ -58,9 +58,10 @@ class Markdown
* Parses the given text and returns the HTML * Parses the given text and returns the HTML
* *
* @param string $text * @param string $text
* @param bool $inline
* @return string * @return string
*/ */
public function parse(string $text): string public function parse(string $text, bool $inline = false): string
{ {
if ($this->options['extra'] === true) { if ($this->options['extra'] === true) {
$parser = new ParsedownExtra; $parser = new ParsedownExtra;
@@ -70,7 +71,10 @@ class Markdown
$parser->setBreaksEnabled($this->options['breaks']); $parser->setBreaksEnabled($this->options['breaks']);
// we need the @ here, because parsedown has some notice issues :( if ($inline === true) {
return @$parser->text($text); return @$parser->line($text);
} else {
return @$parser->text($text);
}
} }
} }

View File

@@ -5,14 +5,16 @@ namespace Kirby\Toolkit;
use Exception; use Exception;
/** /**
* A set of handy methods to simplify array handling * The `A` class provides a set of handy methods
* and make it more consistent. * to simplify array handling and make it more
* consistent. The class contains methods for
* fetching elements from arrays, merging and
* sorting or shuffling arrays.
* *
* @package Kirby Toolkit * @package Kirby Toolkit
* @author Bastian Allgeier <bastian@getkirby.com> * @author Bastian Allgeier <bastian@getkirby.com>
* @link http://getkirby.com * @link http://getkirby.com
* @copyright Bastian Allgeier * @copyright Bastian Allgeier
* @license MIT
*/ */
class A class A
{ {

View File

@@ -3,6 +3,7 @@
namespace Kirby\Toolkit; namespace Kirby\Toolkit;
use Closure; use Closure;
use Countable;
use Exception; use Exception;
/** /**
@@ -10,7 +11,7 @@ use Exception;
* interface around arrays of arrays or objects, * interface around arrays of arrays or objects,
* with advanced filters, sorting, navigation and more. * with advanced filters, sorting, navigation and more.
*/ */
class Collection extends Iterator class Collection extends Iterator implements Countable
{ {
/** /**
@@ -59,7 +60,7 @@ class Collection extends Iterator
} }
/** /**
* Low-level getter for items * Low-level getter for elements
* *
* @param mixed $key * @param mixed $key
* @return mixed * @return mixed
@@ -74,7 +75,7 @@ class Collection extends Iterator
} }
/** /**
* Low-level setter for collection items * Low-level setter for elements
* *
* @param string $key string or array * @param string $key string or array
* @param mixed $value * @param mixed $value
@@ -96,7 +97,7 @@ class Collection extends Iterator
} }
/** /**
* Low-level item remover * Low-level element remover
* *
* @param mixed $key the name of the key * @param mixed $key the name of the key
*/ */
@@ -106,7 +107,7 @@ class Collection extends Iterator
} }
/** /**
* Appends an element to the data array * Appends an element
* *
* @param mixed $key * @param mixed $key
* @param mixed $item * @param mixed $item
@@ -124,17 +125,17 @@ class Collection extends Iterator
} }
/** /**
* Creates chunks of the same size * Creates chunks of the same size.
* The last chunk may be smaller * The last chunk may be smaller
* *
* @param int $size Number of items per chunk * @param int $size Number of elements per chunk
* @return Collection A new collection with an item for each chunk and * @return Collection A new collection with an element for each chunk and
* a sub collection in each chunk * a sub collection in each chunk
*/ */
public function chunk(int $size): self public function chunk(int $size): self
{ {
// create a multidimensional array that is chunked with the given // create a multidimensional array that is chunked with the given
// chunk size keep keys of the items // chunk size keep keys of the elements
$chunks = array_chunk($this->data, $size, true); $chunks = array_chunk($this->data, $size, true);
// convert each chunk to a subcollection // convert each chunk to a subcollection
@@ -167,7 +168,7 @@ class Collection extends Iterator
} }
/** /**
* Getter and setter for the collection data * Getter and setter for the data
* *
* @param array $data * @param array $data
* @return array|Collection * @return array|Collection
@@ -188,7 +189,7 @@ class Collection extends Iterator
} }
/** /**
* Clone and remove all items from the collection * Clone and remove all elements from the collection
* *
* @return Collection * @return Collection
*/ */
@@ -201,7 +202,7 @@ class Collection extends Iterator
} }
/** /**
* Adds all items to the collection * Adds all elements to the collection
* *
* @return Collection * @return Collection
*/ */
@@ -212,7 +213,7 @@ class Collection extends Iterator
} }
/** /**
* Filters the collection by a custom * Filters elements by a custom
* filter function or an array of filters * filter function or an array of filters
* *
* @param Closure $filter * @param Closure $filter
@@ -239,8 +240,8 @@ class Collection extends Iterator
} }
/** /**
* Filters the collection by one of the predefined * Filters elements by one of the
* filter methods. * predefined filter methods.
* *
* @param string $field * @param string $field
* @return self * @return self
@@ -329,7 +330,7 @@ class Collection extends Iterator
} }
/** /**
* Find one or multiple collection items by id * Find one or multiple elements by id
* *
* @param string ...$keys * @param string ...$keys
* @return mixed * @return mixed
@@ -358,7 +359,7 @@ class Collection extends Iterator
} }
/** /**
* Find a single item by an attribute and its value * Find a single element by an attribute and its value
* *
* @param string $attribute * @param string $attribute
* @param mixed $value * @param mixed $value
@@ -375,7 +376,7 @@ class Collection extends Iterator
} }
/** /**
* Find a single item by key (id) * Find a single element by key (id)
* *
* @param string $key * @param string $key
* @return mixed * @return mixed
@@ -386,7 +387,7 @@ class Collection extends Iterator
} }
/** /**
* Returns the first element from the array * Returns the first element
* *
* @return mixed * @return mixed
*/ */
@@ -397,7 +398,7 @@ class Collection extends Iterator
} }
/** /**
* Returns the array in reverse order * Returns the elements in reverse order
* *
* @return Collection * @return Collection
*/ */
@@ -421,8 +422,8 @@ class Collection extends Iterator
} }
/** /**
* Extracts an attribute value from the given item * Extracts an attribute value from the given element
* in the collection. This is useful if items in the collection * in the collection. This is useful if elements in the collection
* might be objects, arrays or anything else and you need to * might be objects, arrays or anything else and you need to
* get the value independently from that. We use it for filterBy. * get the value independently from that. We use it for filterBy.
* *
@@ -463,10 +464,10 @@ class Collection extends Iterator
} }
/** /**
* Groups the collection by a given callback * Groups the elements by a given callback
* *
* @param Closure $callback * @param Closure $callback
* @return Collection A new collection with an item for each group and a subcollection in each group * @return Collection A new collection with an element for each group and a subcollection in each group
*/ */
public function group(Closure $callback): Collection public function group(Closure $callback): Collection
{ {
@@ -497,7 +498,7 @@ class Collection extends Iterator
// create a new entry for the group if it does not exist yet // create a new entry for the group if it does not exist yet
$groups[$value] = new static([$key => $item]); $groups[$value] = new static([$key => $item]);
} else { } else {
// add the item to an existing group // add the element to an existing group
$groups[$value]->set($key, $item); $groups[$value]->set($key, $item);
} }
} }
@@ -506,11 +507,11 @@ class Collection extends Iterator
} }
/** /**
* Groups the collection by a given field * Groups the elements by a given field
* *
* @param string $field * @param string $field
* @param bool $i * @param bool $i
* @return Collection A new collection with an item for each group and a subcollection in each group * @return Collection A new collection with an element for each group and a subcollection in each group
*/ */
public function groupBy(string $field, bool $i = true) public function groupBy(string $field, bool $i = true)
{ {
@@ -527,7 +528,7 @@ class Collection extends Iterator
} }
/** /**
* Checks if the collection has no items * Checks if the number of elements is zero
* *
* @return boolean * @return boolean
*/ */
@@ -537,7 +538,7 @@ class Collection extends Iterator
} }
/** /**
* Checks if the number of items in the collection is even * Checks if the number of elements is even
* *
* @return boolean * @return boolean
*/ */
@@ -547,7 +548,7 @@ class Collection extends Iterator
} }
/** /**
* Checks if the collection has no items * Checks if the number of elements is more than zero
* *
* @return boolean * @return boolean
*/ */
@@ -557,7 +558,7 @@ class Collection extends Iterator
} }
/** /**
* Checks if the number of items in the collection is odd * Checks if the number of elements is odd
* *
* @return boolean * @return boolean
*/ */
@@ -567,7 +568,7 @@ class Collection extends Iterator
} }
/** /**
* Returns the last element from the collection * Returns the last element
* *
* @return mixed * @return mixed
*/ */
@@ -589,7 +590,7 @@ class Collection extends Iterator
} }
/** /**
* Map a function to each item in the collection * Map a function to each element
* *
* @param callable $callback * @param callable $callback
* @return Collection * @return Collection
@@ -771,7 +772,7 @@ class Collection extends Iterator
} }
/** /**
* Adds a new item to the collection * Adds a new element to the collection
* *
* @param mixed $key string or array * @param mixed $key string or array
* @param mixed $value * @param mixed $value
@@ -790,7 +791,7 @@ class Collection extends Iterator
} }
/** /**
* Shuffle all elements in the array * Shuffle all elements
* *
* @return Collection * @return Collection
*/ */
@@ -829,7 +830,7 @@ class Collection extends Iterator
} }
/** /**
* Sorts the object by any number of fields * Sorts the elements by any number of fields
* *
* @param $field string|callable Field name or value callback to sort by * @param $field string|callable Field name or value callback to sort by
* @param $direction string asc or desc * @param $direction string asc or desc
@@ -918,7 +919,7 @@ class Collection extends Iterator
} }
/** /**
* Converts the current object into an array * Converts the object into an array
* *
* @return array * @return array
*/ */
@@ -932,7 +933,7 @@ class Collection extends Iterator
} }
/** /**
* Converts the current object into a json string * Converts the object into a JSON string
* *
* @return string * @return string
*/ */
@@ -942,7 +943,7 @@ class Collection extends Iterator
} }
/** /**
* Convertes the collection to a string * Convertes the object to a string
* *
* @return string * @return string
*/ */

View File

@@ -3,9 +3,19 @@
namespace Kirby\Toolkit; namespace Kirby\Toolkit;
use Exception; use Exception;
use Throwable;
/** /**
* Low level directory handling utilities * The `Dir` class provides methods
* for dealing with directories on the
* file system level, like creating,
* listing, moving, copying or
* evaluating directories etc.
*
* @package Kirby Toolkit
* @author Bastian Allgeier <bastian@getkirby.com>
* @link http://getkirby.com
* @copyright Bastian Allgeier
*/ */
class Dir class Dir
{ {
@@ -174,7 +184,11 @@ class Dir
throw new Exception(sprintf('The directory "%s" does not exist and cannot be linked', $source)); throw new Exception(sprintf('The directory "%s" does not exist and cannot be linked', $source));
} }
return symlink($source, $link); try {
return symlink($source, $link) === true;
} catch (Throwable $e) {
return false;
}
} }
/** /**

View File

@@ -5,6 +5,13 @@ namespace Kirby\Toolkit;
use Zend\Escaper\Escaper; use Zend\Escaper\Escaper;
/** /**
* The `Escape` class provides methods
* for escaping common HTML attributes
* data. This can be used to put
* untrusted data into typical
* attribute values like width, name,
* value, etc.
*
* Wrapper for the Zend Escaper * Wrapper for the Zend Escaper
* *
* @link https://github.com/zendframework/zend-escaper * @link https://github.com/zendframework/zend-escaper

View File

@@ -3,12 +3,20 @@
namespace Kirby\Toolkit; namespace Kirby\Toolkit;
use Exception; use Exception;
use Throwable;
use Kirby\Http\Header; use Kirby\Http\Header;
use Throwable;
use ZipArchive; use ZipArchive;
/** /**
* Low level file handling utilities * The `F` class provides methods for
* dealing with files on the file system
* level, like creating, reading,
* deleting, copying or validatings files.
*
* @package Kirby Toolkit
* @author Bastian Allgeier <bastian@getkirby.com>
* @link http://getkirby.com
* @copyright Bastian Allgeier
*/ */
class F class F
{ {
@@ -324,7 +332,11 @@ class F
throw new Exception(sprintf('The file "%s" does not exist and cannot be linked', $source)); throw new Exception(sprintf('The file "%s" does not exist and cannot be linked', $source));
} }
return $method($source, $link); try {
return $method($source, $link) === true;
} catch (Throwable $e) {
return false;
}
} }
/** /**
@@ -534,7 +546,7 @@ class F
$parent = realpath($in); $parent = realpath($in);
if ($parent === false || is_dir($parent) === false) { if ($parent === false || is_dir($parent) === false) {
throw new Exception(sprintf('The parent directory does not exist: "%s"', $parent)); throw new Exception(sprintf('The parent directory does not exist: "%s"', $in));
} }
if (substr($realpath, 0, strlen($parent)) !== $parent) { if (substr($realpath, 0, strlen($parent)) !== $parent) {

View File

@@ -28,7 +28,7 @@ class Iterator implements \Iterator
} }
/** /**
* Returns the current key from the array * Returns the current key
* *
* @return string * @return string
*/ */
@@ -38,7 +38,7 @@ class Iterator implements \Iterator
} }
/** /**
* Returns an array of all keys in the Iterator * Returns an array of all keys
* *
* @return array * @return array
*/ */
@@ -48,7 +48,7 @@ class Iterator implements \Iterator
} }
/** /**
* Returns the current element of the array * Returns the current element
* *
* @return mixed * @return mixed
*/ */
@@ -58,7 +58,7 @@ class Iterator implements \Iterator
} }
/** /**
* Moves the cursor to the previous element in the array * Moves the cursor to the previous element
* and returns it * and returns it
* *
* @return mixed * @return mixed
@@ -69,7 +69,7 @@ class Iterator implements \Iterator
} }
/** /**
* Moves the cursor to the next element in the array * Moves the cursor to the next element
* and returns it * and returns it
* *
* @return mixed * @return mixed
@@ -80,7 +80,7 @@ class Iterator implements \Iterator
} }
/** /**
* Moves the cusor to the first element of the array * Moves the cusor to the first element
*/ */
public function rewind() public function rewind()
{ {
@@ -98,7 +98,7 @@ class Iterator implements \Iterator
} }
/** /**
* Counts all elements in the array * Counts all elements
* *
* @return int * @return int
*/ */
@@ -130,7 +130,7 @@ class Iterator implements \Iterator
} }
/** /**
* Checks if an element is in the collection by key. * Checks by key if an element is included
* *
* @param mixed $key * @param mixed $key
* @return boolean * @return boolean

View File

@@ -5,7 +5,15 @@ namespace Kirby\Toolkit;
use SimpleXMLElement; use SimpleXMLElement;
/** /**
* Mime type detection/guessing * The `Mime` class provides method
* for mime type detection or guessing
* from different criteria like
* extensions etc.
*
* @package Kirby Toolkit
* @author Bastian Allgeier <bastian@getkirby.com>
* @link http://getkirby.com
* @copyright Bastian Allgeier
*/ */
class Mime class Mime
{ {

View File

@@ -5,7 +5,9 @@ namespace Kirby\Toolkit;
use Exception; use Exception;
/** /**
* A set of handy string methods * The String class provides a set
* of handy methods for string
* handling and manipulation.
* *
* @package Kirby Toolkit * @package Kirby Toolkit
* @author Bastian Allgeier <bastian@getkirby.com> * @author Bastian Allgeier <bastian@getkirby.com>

View File

@@ -365,6 +365,9 @@
"toolbar.button.heading.2": "Заглавие 2", "toolbar.button.heading.2": "Заглавие 2",
"toolbar.button.heading.3": "Заглавие 3", "toolbar.button.heading.3": "Заглавие 3",
"toolbar.button.italic": "\u041d\u0430\u043a\u043b\u043e\u043d\u0435\u043d \u0448\u0440\u0438\u0444\u0442", "toolbar.button.italic": "\u041d\u0430\u043a\u043b\u043e\u043d\u0435\u043d \u0448\u0440\u0438\u0444\u0442",
"toolbar.button.file": "Файл",
"toolbar.button.file.select": "Select a file",
"toolbar.button.file.upload": "Upload a file",
"toolbar.button.link": "\u0412\u0440\u044a\u0437\u043a\u0430", "toolbar.button.link": "\u0412\u0440\u044a\u0437\u043a\u0430",
"toolbar.button.ol": "Подреден списък", "toolbar.button.ol": "Подреден списък",
"toolbar.button.ul": "Списък", "toolbar.button.ul": "Списък",
@@ -396,6 +399,8 @@
"user.delete.confirm": "user.delete.confirm":
"Сигурни ли сте, че искате да изтриете <br><strong>{email}</strong>?", "Сигурни ли сте, че искате да изтриете <br><strong>{email}</strong>?",
"users": "Потребители",
"version": "\u0412\u0435\u0440\u0441\u0438\u044f \u043d\u0430 Kirby", "version": "\u0412\u0435\u0440\u0441\u0438\u044f \u043d\u0430 Kirby",
"view.account": "\u0412\u0430\u0448\u0438\u044f \u0430\u043a\u0430\u0443\u043d\u0442", "view.account": "\u0412\u0430\u0448\u0438\u044f \u0430\u043a\u0430\u0443\u043d\u0442",

View File

@@ -365,6 +365,9 @@
"toolbar.button.heading.2": "Encapçalament 2", "toolbar.button.heading.2": "Encapçalament 2",
"toolbar.button.heading.3": "Encapçalament 3", "toolbar.button.heading.3": "Encapçalament 3",
"toolbar.button.italic": "Cursiva", "toolbar.button.italic": "Cursiva",
"toolbar.button.file": "Arxiu",
"toolbar.button.file.select": "Select a file",
"toolbar.button.file.upload": "Upload a file",
"toolbar.button.link": "Enlla\u00e7", "toolbar.button.link": "Enlla\u00e7",
"toolbar.button.ol": "Llista ordenada", "toolbar.button.ol": "Llista ordenada",
"toolbar.button.ul": "Llista de vinyetes", "toolbar.button.ul": "Llista de vinyetes",
@@ -396,6 +399,8 @@
"user.delete.confirm": "user.delete.confirm":
"Segur que voleu eliminar <br> <strong>{email}</strong>?", "Segur que voleu eliminar <br> <strong>{email}</strong>?",
"users": "Usuaris",
"version": "Versi\u00f3 de Kirby", "version": "Versi\u00f3 de Kirby",
"view.account": "La teva compta", "view.account": "La teva compta",

View File

@@ -365,6 +365,9 @@
"toolbar.button.heading.2": "Nadpis 2", "toolbar.button.heading.2": "Nadpis 2",
"toolbar.button.heading.3": "Nadpis 3", "toolbar.button.heading.3": "Nadpis 3",
"toolbar.button.italic": "Kurz\u00edva", "toolbar.button.italic": "Kurz\u00edva",
"toolbar.button.file": "Soubor",
"toolbar.button.file.select": "Select a file",
"toolbar.button.file.upload": "Upload a file",
"toolbar.button.link": "Odkaz", "toolbar.button.link": "Odkaz",
"toolbar.button.ol": "Řazený seznam", "toolbar.button.ol": "Řazený seznam",
"toolbar.button.ul": "Odrážkový seznam", "toolbar.button.ul": "Odrážkový seznam",
@@ -396,6 +399,8 @@
"user.delete.confirm": "user.delete.confirm":
"Opravdu chcete smazat tohoto u\u017eivatele?", "Opravdu chcete smazat tohoto u\u017eivatele?",
"users": "Uživatelé",
"version": "Verze Kirby", "version": "Verze Kirby",
"view.account": "V\u00e1\u0161 \u00fa\u010det", "view.account": "V\u00e1\u0161 \u00fa\u010det",

View File

@@ -365,6 +365,9 @@
"toolbar.button.heading.2": "Overskrift 2", "toolbar.button.heading.2": "Overskrift 2",
"toolbar.button.heading.3": "Overskrift 3", "toolbar.button.heading.3": "Overskrift 3",
"toolbar.button.italic": "Kursiv tekst", "toolbar.button.italic": "Kursiv tekst",
"toolbar.button.file": "Fil",
"toolbar.button.file.select": "Select a file",
"toolbar.button.file.upload": "Upload a file",
"toolbar.button.link": "Link", "toolbar.button.link": "Link",
"toolbar.button.ol": "Ordnet liste", "toolbar.button.ol": "Ordnet liste",
"toolbar.button.ul": "Punktliste", "toolbar.button.ul": "Punktliste",
@@ -396,6 +399,8 @@
"user.delete.confirm": "user.delete.confirm":
"\u00d8nsker du virkelig at slette denne bruger?", "\u00d8nsker du virkelig at slette denne bruger?",
"users": "Brugere",
"version": "Kirby version", "version": "Kirby version",
"view.account": "Din konto", "view.account": "Din konto",

View File

@@ -365,6 +365,9 @@
"toolbar.button.heading.2": "Überschrift 2", "toolbar.button.heading.2": "Überschrift 2",
"toolbar.button.heading.3": "Überschrift 3", "toolbar.button.heading.3": "Überschrift 3",
"toolbar.button.italic": "Kursiver Text", "toolbar.button.italic": "Kursiver Text",
"toolbar.button.file": "Datei",
"toolbar.button.file.select": "Datei auswählen",
"toolbar.button.file.upload": "Datei hochladen",
"toolbar.button.link": "Link", "toolbar.button.link": "Link",
"toolbar.button.ol": "Geordnete Liste", "toolbar.button.ol": "Geordnete Liste",
"toolbar.button.ul": "Ungeordnete Liste", "toolbar.button.ul": "Ungeordnete Liste",
@@ -396,6 +399,8 @@
"user.delete.confirm": "user.delete.confirm":
"Willst du den Benutzer <br><strong>{email}</strong> wirklich löschen?", "Willst du den Benutzer <br><strong>{email}</strong> wirklich löschen?",
"users": "Benutzer",
"version": "Version", "version": "Version",
"view.account": "Dein Account", "view.account": "Dein Account",

View File

@@ -365,6 +365,9 @@
"toolbar.button.heading.2": "Επικεφαλίδα 2", "toolbar.button.heading.2": "Επικεφαλίδα 2",
"toolbar.button.heading.3": "Επικεφαλίδα 3", "toolbar.button.heading.3": "Επικεφαλίδα 3",
"toolbar.button.italic": "\u03a0\u03bb\u03ac\u03b3\u03b9\u03b1 \u03b3\u03c1\u03b1\u03c6\u03ae", "toolbar.button.italic": "\u03a0\u03bb\u03ac\u03b3\u03b9\u03b1 \u03b3\u03c1\u03b1\u03c6\u03ae",
"toolbar.button.file": "Αρχείο",
"toolbar.button.file.select": "Select a file",
"toolbar.button.file.upload": "Upload a file",
"toolbar.button.link": "\u03a3\u03cd\u03bd\u03b4\u03b5\u03c3\u03bc\u03bf\u03c2", "toolbar.button.link": "\u03a3\u03cd\u03bd\u03b4\u03b5\u03c3\u03bc\u03bf\u03c2",
"toolbar.button.ol": "Ταξινομημένη λίστα", "toolbar.button.ol": "Ταξινομημένη λίστα",
"toolbar.button.ul": "Λίστα κουκκίδων", "toolbar.button.ul": "Λίστα κουκκίδων",
@@ -396,6 +399,8 @@
"user.delete.confirm": "user.delete.confirm":
"\u0398\u03ad\u03bb\u03b5\u03c4\u03b5 \u03c3\u03af\u03b3\u03bf\u03c5\u03c1\u03b1 \u03bd\u03b1 \u03b4\u03b9\u03b1\u03b3\u03c1\u03ac\u03c8\u03b5\u03c4\u03b5 \u03b1\u03c5\u03c4\u03cc\u03bd \u03c4\u03bf\u03bd \u03c7\u03c1\u03ae\u03c3\u03c4\u03b7;", "\u0398\u03ad\u03bb\u03b5\u03c4\u03b5 \u03c3\u03af\u03b3\u03bf\u03c5\u03c1\u03b1 \u03bd\u03b1 \u03b4\u03b9\u03b1\u03b3\u03c1\u03ac\u03c8\u03b5\u03c4\u03b5 \u03b1\u03c5\u03c4\u03cc\u03bd \u03c4\u03bf\u03bd \u03c7\u03c1\u03ae\u03c3\u03c4\u03b7;",
"users": "Χρήστες",
"version": "\u0388\u03ba\u03b4\u03bf\u03c3\u03b7 Kirby", "version": "\u0388\u03ba\u03b4\u03bf\u03c3\u03b7 Kirby",
"view.account": "\u039f \u03bb\u03bf\u03b3\u03b1\u03c1\u03b9\u03b1\u03c3\u03bc\u03cc\u03c2 \u03c3\u03b1\u03c2", "view.account": "\u039f \u03bb\u03bf\u03b3\u03b1\u03c1\u03b9\u03b1\u03c3\u03bc\u03cc\u03c2 \u03c3\u03b1\u03c2",

View File

@@ -365,6 +365,9 @@
"toolbar.button.heading.2": "Heading 2", "toolbar.button.heading.2": "Heading 2",
"toolbar.button.heading.3": "Heading 3", "toolbar.button.heading.3": "Heading 3",
"toolbar.button.italic": "Italic", "toolbar.button.italic": "Italic",
"toolbar.button.file": "File",
"toolbar.button.file.select": "Select a file",
"toolbar.button.file.upload": "Upload a file",
"toolbar.button.link": "Link", "toolbar.button.link": "Link",
"toolbar.button.ol": "Ordered list", "toolbar.button.ol": "Ordered list",
"toolbar.button.ul": "Bullet list", "toolbar.button.ul": "Bullet list",
@@ -396,6 +399,8 @@
"user.delete.confirm": "user.delete.confirm":
"Do you really want to delete <br><strong>{email}</strong>?", "Do you really want to delete <br><strong>{email}</strong>?",
"users": "Users",
"version": "Version", "version": "Version",
"view.account": "Your account", "view.account": "Your account",

View File

@@ -365,6 +365,9 @@
"toolbar.button.heading.2": "Encabezado 2", "toolbar.button.heading.2": "Encabezado 2",
"toolbar.button.heading.3": "Encabezado 3", "toolbar.button.heading.3": "Encabezado 3",
"toolbar.button.italic": "Texto en It\u00e1licas", "toolbar.button.italic": "Texto en It\u00e1licas",
"toolbar.button.file": "Archivo",
"toolbar.button.file.select": "Select a file",
"toolbar.button.file.upload": "Upload a file",
"toolbar.button.link": "Enlace", "toolbar.button.link": "Enlace",
"toolbar.button.ol": "Lista en orden", "toolbar.button.ol": "Lista en orden",
"toolbar.button.ul": "Lista de viñetas", "toolbar.button.ul": "Lista de viñetas",
@@ -396,6 +399,8 @@
"user.delete.confirm": "user.delete.confirm":
"¿Estás seguro que deseas eliminar <br><strong>{email}</strong>?", "¿Estás seguro que deseas eliminar <br><strong>{email}</strong>?",
"users": "Usuarios",
"version": "Versión", "version": "Versión",
"view.account": "Tu cuenta", "view.account": "Tu cuenta",

View File

@@ -365,6 +365,9 @@
"toolbar.button.heading.2": "Encabezado 2", "toolbar.button.heading.2": "Encabezado 2",
"toolbar.button.heading.3": "Encabezado 3", "toolbar.button.heading.3": "Encabezado 3",
"toolbar.button.italic": "Italica", "toolbar.button.italic": "Italica",
"toolbar.button.file": "Archivo",
"toolbar.button.file.select": "Select a file",
"toolbar.button.file.upload": "Upload a file",
"toolbar.button.link": "Enlace", "toolbar.button.link": "Enlace",
"toolbar.button.ol": "Lista ordenada", "toolbar.button.ol": "Lista ordenada",
"toolbar.button.ul": "Lista de viñetas", "toolbar.button.ul": "Lista de viñetas",
@@ -396,6 +399,8 @@
"user.delete.confirm": "user.delete.confirm":
"¿Realmente quieres eliminar <br><strong>{email}</strong>?", "¿Realmente quieres eliminar <br><strong>{email}</strong>?",
"users": "Usuarios",
"version": "Versión", "version": "Versión",
"view.account": "Su cuenta", "view.account": "Su cuenta",

View File

@@ -365,6 +365,9 @@
"toolbar.button.heading.2": "عنوان 2", "toolbar.button.heading.2": "عنوان 2",
"toolbar.button.heading.3": "عنوان 3", "toolbar.button.heading.3": "عنوان 3",
"toolbar.button.italic": "\u0645\u062a\u0646 \u0627\u0631\u06cc\u0628", "toolbar.button.italic": "\u0645\u062a\u0646 \u0627\u0631\u06cc\u0628",
"toolbar.button.file": "فایل",
"toolbar.button.file.select": "Select a file",
"toolbar.button.file.upload": "Upload a file",
"toolbar.button.link": "\u067e\u06cc\u0648\u0646\u062f", "toolbar.button.link": "\u067e\u06cc\u0648\u0646\u062f",
"toolbar.button.ol": "لیست مرتب", "toolbar.button.ol": "لیست مرتب",
"toolbar.button.ul": "لیست معمولی", "toolbar.button.ul": "لیست معمولی",
@@ -396,6 +399,8 @@
"user.delete.confirm": "user.delete.confirm":
"آیا واقعا میخواهید<strong> {email}</strong> را حذف کنید؟", "آیا واقعا میخواهید<strong> {email}</strong> را حذف کنید؟",
"users": "کاربران",
"version": "\u0646\u0633\u062e\u0647 \u0646\u0631\u0645 \u0627\u0641\u0632\u0627\u0631", "version": "\u0646\u0633\u062e\u0647 \u0646\u0631\u0645 \u0627\u0641\u0632\u0627\u0631",
"view.account": "حساب کاربری شما", "view.account": "حساب کاربری شما",

View File

@@ -365,6 +365,9 @@
"toolbar.button.heading.2": "Otsikko 2", "toolbar.button.heading.2": "Otsikko 2",
"toolbar.button.heading.3": "Otsikko 3", "toolbar.button.heading.3": "Otsikko 3",
"toolbar.button.italic": "Kursivointi", "toolbar.button.italic": "Kursivointi",
"toolbar.button.file": "Tiedosto",
"toolbar.button.file.select": "Select a file",
"toolbar.button.file.upload": "Upload a file",
"toolbar.button.link": "Linkki", "toolbar.button.link": "Linkki",
"toolbar.button.ol": "Järjestetty lista", "toolbar.button.ol": "Järjestetty lista",
"toolbar.button.ul": "Järjestämätön lista", "toolbar.button.ul": "Järjestämätön lista",
@@ -396,6 +399,8 @@
"user.delete.confirm": "user.delete.confirm":
"Haluatko varmsti poistaa käyttäjän <br><strong>{email}</strong>?", "Haluatko varmsti poistaa käyttäjän <br><strong>{email}</strong>?",
"users": "Käyttäjät",
"version": "Versio", "version": "Versio",
"view.account": "Oma käyttäjätili", "view.account": "Oma käyttäjätili",

View File

@@ -365,6 +365,9 @@
"toolbar.button.heading.2": "Titre 2", "toolbar.button.heading.2": "Titre 2",
"toolbar.button.heading.3": "Titre 3", "toolbar.button.heading.3": "Titre 3",
"toolbar.button.italic": "Italique", "toolbar.button.italic": "Italique",
"toolbar.button.file": "Fichier",
"toolbar.button.file.select": "Sélectionner un fichier",
"toolbar.button.file.upload": "Transférer un fichier",
"toolbar.button.link": "Lien", "toolbar.button.link": "Lien",
"toolbar.button.ol": "Liste ordonnée", "toolbar.button.ol": "Liste ordonnée",
"toolbar.button.ul": "Liste non-ordonnée", "toolbar.button.ul": "Liste non-ordonnée",
@@ -396,6 +399,8 @@
"user.delete.confirm": "user.delete.confirm":
"Voulez-vous vraiment supprimer <br><strong>{email}</strong>?", "Voulez-vous vraiment supprimer <br><strong>{email}</strong>?",
"users": "Utilisateurs",
"version": "Version", "version": "Version",
"view.account": "Votre compte", "view.account": "Votre compte",

View File

@@ -365,6 +365,9 @@
"toolbar.button.heading.2": "Cím 2", "toolbar.button.heading.2": "Cím 2",
"toolbar.button.heading.3": "Cím 3", "toolbar.button.heading.3": "Cím 3",
"toolbar.button.italic": "Dőlt szöveg", "toolbar.button.italic": "Dőlt szöveg",
"toolbar.button.file": "Fájl",
"toolbar.button.file.select": "Select a file",
"toolbar.button.file.upload": "Upload a file",
"toolbar.button.link": "Link", "toolbar.button.link": "Link",
"toolbar.button.ol": "Rendezett lista", "toolbar.button.ol": "Rendezett lista",
"toolbar.button.ul": "Rendezetlen lista", "toolbar.button.ul": "Rendezetlen lista",
@@ -396,6 +399,8 @@
"user.delete.confirm": "user.delete.confirm":
"Biztos törlöd ezt a felhasználót: <br><strong>{email}</strong>?", "Biztos törlöd ezt a felhasználót: <br><strong>{email}</strong>?",
"users": "Felhasználók",
"version": "Kirby verzi\u00f3", "version": "Kirby verzi\u00f3",
"view.account": "Fi\u00f3kod", "view.account": "Fi\u00f3kod",

View File

@@ -365,6 +365,9 @@
"toolbar.button.heading.2": "Penajukan 2", "toolbar.button.heading.2": "Penajukan 2",
"toolbar.button.heading.3": "Penajukan 3", "toolbar.button.heading.3": "Penajukan 3",
"toolbar.button.italic": "Miring", "toolbar.button.italic": "Miring",
"toolbar.button.file": "Berkas",
"toolbar.button.file.select": "Select a file",
"toolbar.button.file.upload": "Upload a file",
"toolbar.button.link": "Tautan", "toolbar.button.link": "Tautan",
"toolbar.button.ol": "Daftar berurut", "toolbar.button.ol": "Daftar berurut",
"toolbar.button.ul": "Daftar tidak berurut", "toolbar.button.ul": "Daftar tidak berurut",
@@ -396,6 +399,8 @@
"user.delete.confirm": "user.delete.confirm":
"Anda yakin menghapus <br><strong>{email}</strong>?", "Anda yakin menghapus <br><strong>{email}</strong>?",
"users": "Pengguna",
"version": "Versi", "version": "Versi",
"view.account": "Akun Anda", "view.account": "Akun Anda",

View File

@@ -365,6 +365,9 @@
"toolbar.button.heading.2": "Titolo 2", "toolbar.button.heading.2": "Titolo 2",
"toolbar.button.heading.3": "Titolo 3", "toolbar.button.heading.3": "Titolo 3",
"toolbar.button.italic": "Corsivo", "toolbar.button.italic": "Corsivo",
"toolbar.button.file": "File",
"toolbar.button.file.select": "Select a file",
"toolbar.button.file.upload": "Upload a file",
"toolbar.button.link": "Link", "toolbar.button.link": "Link",
"toolbar.button.ol": "Elenco numerato", "toolbar.button.ol": "Elenco numerato",
"toolbar.button.ul": "Elenco puntato", "toolbar.button.ul": "Elenco puntato",
@@ -396,6 +399,8 @@
"user.delete.confirm": "user.delete.confirm":
"Sei sicuro di voler eliminare questo utente?", "Sei sicuro di voler eliminare questo utente?",
"users": "Utenti",
"version": "Versione di Kirby", "version": "Versione di Kirby",
"view.account": "Il tuo account", "view.account": "Il tuo account",

View File

@@ -365,6 +365,9 @@
"toolbar.button.heading.2": "제목 2", "toolbar.button.heading.2": "제목 2",
"toolbar.button.heading.3": "제목 3", "toolbar.button.heading.3": "제목 3",
"toolbar.button.italic": "강조 2", "toolbar.button.italic": "강조 2",
"toolbar.button.file": "파일",
"toolbar.button.file.select": "Select a file",
"toolbar.button.file.upload": "Upload a file",
"toolbar.button.link": "링크", "toolbar.button.link": "링크",
"toolbar.button.ol": "숫자 목록", "toolbar.button.ol": "숫자 목록",
"toolbar.button.ul": "기호 목록", "toolbar.button.ul": "기호 목록",
@@ -396,6 +399,8 @@
"user.delete.confirm": "user.delete.confirm":
"<strong>이메일({email})</strong>을 삭제할까요?", "<strong>이메일({email})</strong>을 삭제할까요?",
"users": "사용자",
"version": "버전", "version": "버전",
"view.account": "계정", "view.account": "계정",

View File

@@ -365,6 +365,9 @@
"toolbar.button.heading.2": "Overskrift 2", "toolbar.button.heading.2": "Overskrift 2",
"toolbar.button.heading.3": "Overskrift 3", "toolbar.button.heading.3": "Overskrift 3",
"toolbar.button.italic": "Kursiv tekst", "toolbar.button.italic": "Kursiv tekst",
"toolbar.button.file": "Fil",
"toolbar.button.file.select": "Select a file",
"toolbar.button.file.upload": "Upload a file",
"toolbar.button.link": "Adresse", "toolbar.button.link": "Adresse",
"toolbar.button.ol": "Ordnet liste", "toolbar.button.ol": "Ordnet liste",
"toolbar.button.ul": "Punktliste", "toolbar.button.ul": "Punktliste",
@@ -396,6 +399,8 @@
"user.delete.confirm": "user.delete.confirm":
"Vil du virkelig slette denne konten?", "Vil du virkelig slette denne konten?",
"users": "Brukere",
"version": "Kirby versjon", "version": "Kirby versjon",
"view.account": "Din konto", "view.account": "Din konto",

View File

@@ -365,6 +365,9 @@
"toolbar.button.heading.2": "Titel 2", "toolbar.button.heading.2": "Titel 2",
"toolbar.button.heading.3": "Titel 3", "toolbar.button.heading.3": "Titel 3",
"toolbar.button.italic": "Cursieve tekst", "toolbar.button.italic": "Cursieve tekst",
"toolbar.button.file": "Bestand",
"toolbar.button.file.select": "Select a file",
"toolbar.button.file.upload": "Upload a file",
"toolbar.button.link": "Link", "toolbar.button.link": "Link",
"toolbar.button.ol": "Genummerde lijst", "toolbar.button.ol": "Genummerde lijst",
"toolbar.button.ul": "Opsomming", "toolbar.button.ul": "Opsomming",
@@ -396,6 +399,8 @@
"user.delete.confirm": "user.delete.confirm":
"Weet je zeker dat je <br><strong>{email}</strong>wil verwijderen?", "Weet je zeker dat je <br><strong>{email}</strong>wil verwijderen?",
"users": "Gebruikers",
"version": "Kirby-versie", "version": "Kirby-versie",
"view.account": "Jouw account", "view.account": "Jouw account",

View File

@@ -365,6 +365,9 @@
"toolbar.button.heading.2": "Nagłówek 2", "toolbar.button.heading.2": "Nagłówek 2",
"toolbar.button.heading.3": "Nagłówek 3", "toolbar.button.heading.3": "Nagłówek 3",
"toolbar.button.italic": "Kursywa", "toolbar.button.italic": "Kursywa",
"toolbar.button.file": "Plik",
"toolbar.button.file.select": "Select a file",
"toolbar.button.file.upload": "Upload a file",
"toolbar.button.link": "Link", "toolbar.button.link": "Link",
"toolbar.button.ol": "Lista numerowana", "toolbar.button.ol": "Lista numerowana",
"toolbar.button.ul": "Lista wypunktowana", "toolbar.button.ul": "Lista wypunktowana",
@@ -396,6 +399,8 @@
"user.delete.confirm": "user.delete.confirm":
"Czy na pewno chcesz usunąć <br><strong>{email}</strong>?", "Czy na pewno chcesz usunąć <br><strong>{email}</strong>?",
"users": "Użytkownicy",
"version": "Wersja", "version": "Wersja",
"view.account": "Twoje konto", "view.account": "Twoje konto",

View File

@@ -365,6 +365,9 @@
"toolbar.button.heading.2": "Título 2", "toolbar.button.heading.2": "Título 2",
"toolbar.button.heading.3": "Título 3", "toolbar.button.heading.3": "Título 3",
"toolbar.button.italic": "Itálico", "toolbar.button.italic": "Itálico",
"toolbar.button.file": "Arquivo",
"toolbar.button.file.select": "Select a file",
"toolbar.button.file.upload": "Upload a file",
"toolbar.button.link": "Link", "toolbar.button.link": "Link",
"toolbar.button.ol": "Lista ordenada", "toolbar.button.ol": "Lista ordenada",
"toolbar.button.ul": "Lista não-ordenada", "toolbar.button.ul": "Lista não-ordenada",
@@ -396,6 +399,8 @@
"user.delete.confirm": "user.delete.confirm":
"Deseja realmente excluir <br><strong>{email}</strong>?", "Deseja realmente excluir <br><strong>{email}</strong>?",
"users": "Usuários",
"version": "Vers\u00e3o do Kirby", "version": "Vers\u00e3o do Kirby",
"view.account": "Sua conta", "view.account": "Sua conta",

View File

@@ -365,6 +365,9 @@
"toolbar.button.heading.2": "Título 2", "toolbar.button.heading.2": "Título 2",
"toolbar.button.heading.3": "Título 3", "toolbar.button.heading.3": "Título 3",
"toolbar.button.italic": "Itálico", "toolbar.button.italic": "Itálico",
"toolbar.button.file": "Ficheiro",
"toolbar.button.file.select": "Select a file",
"toolbar.button.file.upload": "Upload a file",
"toolbar.button.link": "Link", "toolbar.button.link": "Link",
"toolbar.button.ol": "Lista ordenada", "toolbar.button.ol": "Lista ordenada",
"toolbar.button.ul": "Lista não-ordenada", "toolbar.button.ul": "Lista não-ordenada",
@@ -396,6 +399,8 @@
"user.delete.confirm": "user.delete.confirm":
"Deseja realmente excluir <br><strong>{email}</strong>?", "Deseja realmente excluir <br><strong>{email}</strong>?",
"users": "Utilizadores",
"version": "Vers\u00e3o do Kirby", "version": "Vers\u00e3o do Kirby",
"view.account": "A sua conta", "view.account": "A sua conta",

View File

@@ -365,6 +365,9 @@
"toolbar.button.heading.2": "Nadpis 2", "toolbar.button.heading.2": "Nadpis 2",
"toolbar.button.heading.3": "Nadpis 3", "toolbar.button.heading.3": "Nadpis 3",
"toolbar.button.italic": "Kurzíva", "toolbar.button.italic": "Kurzíva",
"toolbar.button.file": "Súbor",
"toolbar.button.file.select": "Select a file",
"toolbar.button.file.upload": "Upload a file",
"toolbar.button.link": "Odkaz", "toolbar.button.link": "Odkaz",
"toolbar.button.ol": "Číslovaný zoznam", "toolbar.button.ol": "Číslovaný zoznam",
"toolbar.button.ul": "Odrážkový zoznam", "toolbar.button.ul": "Odrážkový zoznam",
@@ -396,6 +399,8 @@
"user.delete.confirm": "user.delete.confirm":
"Ste si istý, že chcete zmazať <br><strong>{email}</strong>?", "Ste si istý, že chcete zmazať <br><strong>{email}</strong>?",
"users": "Užívatelia",
"version": "Verzia", "version": "Verzia",
"view.account": "Váš účet", "view.account": "Váš účet",

View File

@@ -365,6 +365,9 @@
"toolbar.button.heading.2": "Rubrik 2", "toolbar.button.heading.2": "Rubrik 2",
"toolbar.button.heading.3": "Rubrik 3", "toolbar.button.heading.3": "Rubrik 3",
"toolbar.button.italic": "Kursiv", "toolbar.button.italic": "Kursiv",
"toolbar.button.file": "Fil",
"toolbar.button.file.select": "Select a file",
"toolbar.button.file.upload": "Upload a file",
"toolbar.button.link": "L\u00e4nk", "toolbar.button.link": "L\u00e4nk",
"toolbar.button.ol": "Sorterad lista", "toolbar.button.ol": "Sorterad lista",
"toolbar.button.ul": "Punktlista", "toolbar.button.ul": "Punktlista",
@@ -396,6 +399,8 @@
"user.delete.confirm": "user.delete.confirm":
"Vill du verkligen radera <br><strong>{email}</strong>?", "Vill du verkligen radera <br><strong>{email}</strong>?",
"users": "Användare",
"version": "Version", "version": "Version",
"view.account": "Ditt konto", "view.account": "Ditt konto",

View File

@@ -365,6 +365,9 @@
"toolbar.button.heading.2": "Başlık 2", "toolbar.button.heading.2": "Başlık 2",
"toolbar.button.heading.3": "Başlık 3", "toolbar.button.heading.3": "Başlık 3",
"toolbar.button.italic": "Eğik Yazı", "toolbar.button.italic": "Eğik Yazı",
"toolbar.button.file": "Dosya",
"toolbar.button.file.select": "Bir dosya seçin",
"toolbar.button.file.upload": "Bir dosya yükleyin",
"toolbar.button.link": "Ba\u011flant\u0131", "toolbar.button.link": "Ba\u011flant\u0131",
"toolbar.button.ol": "Sıralı liste", "toolbar.button.ol": "Sıralı liste",
"toolbar.button.ul": "Madde listesi", "toolbar.button.ul": "Madde listesi",
@@ -396,6 +399,8 @@
"user.delete.confirm": "user.delete.confirm":
"<strong>{email}</strong> kullanıcısını silmek istediğinizden emin misiniz?", "<strong>{email}</strong> kullanıcısını silmek istediğinizden emin misiniz?",
"users": "Kullanıcılar",
"version": "Versiyon", "version": "Versiyon",
"view.account": "Hesap Bilgilerin", "view.account": "Hesap Bilgilerin",