Upgrade to 3.7.0
This commit is contained in:
31
kirby/src/Api/Api.php
Normal file → Executable file
31
kirby/src/Api/Api.php
Normal file → Executable file
@@ -8,6 +8,7 @@ use Kirby\Exception\NotFoundException;
|
||||
use Kirby\Filesystem\F;
|
||||
use Kirby\Http\Response;
|
||||
use Kirby\Http\Router;
|
||||
use Kirby\Toolkit\I18n;
|
||||
use Kirby\Toolkit\Pagination;
|
||||
use Kirby\Toolkit\Properties;
|
||||
use Kirby\Toolkit\Str;
|
||||
@@ -679,6 +680,12 @@ class Api
|
||||
*/
|
||||
public function responseForException(Throwable $e): array
|
||||
{
|
||||
if (isset($this->kirby) === true) {
|
||||
$docRoot = $this->kirby->environment()->get('DOCUMENT_ROOT');
|
||||
} else {
|
||||
$docRoot = $_SERVER['DOCUMENT_ROOT'] ?? null;
|
||||
}
|
||||
|
||||
// prepare the result array for all exception types
|
||||
$result = [
|
||||
'status' => 'error',
|
||||
@@ -686,7 +693,7 @@ class Api
|
||||
'code' => empty($e->getCode()) === true ? 500 : $e->getCode(),
|
||||
'exception' => get_class($e),
|
||||
'key' => null,
|
||||
'file' => F::relativepath($e->getFile(), $_SERVER['DOCUMENT_ROOT'] ?? null),
|
||||
'file' => F::relativepath($e->getFile(), $docRoot),
|
||||
'line' => $e->getLine(),
|
||||
'details' => [],
|
||||
'route' => $this->route ? $this->route->pattern() : null
|
||||
@@ -735,13 +742,13 @@ class Api
|
||||
|
||||
// get error messages from translation
|
||||
$errorMessages = [
|
||||
UPLOAD_ERR_INI_SIZE => t('upload.error.iniSize'),
|
||||
UPLOAD_ERR_FORM_SIZE => t('upload.error.formSize'),
|
||||
UPLOAD_ERR_PARTIAL => t('upload.error.partial'),
|
||||
UPLOAD_ERR_NO_FILE => t('upload.error.noFile'),
|
||||
UPLOAD_ERR_NO_TMP_DIR => t('upload.error.tmpDir'),
|
||||
UPLOAD_ERR_CANT_WRITE => t('upload.error.cantWrite'),
|
||||
UPLOAD_ERR_EXTENSION => t('upload.error.extension')
|
||||
UPLOAD_ERR_INI_SIZE => I18n::translate('upload.error.iniSize'),
|
||||
UPLOAD_ERR_FORM_SIZE => I18n::translate('upload.error.formSize'),
|
||||
UPLOAD_ERR_PARTIAL => I18n::translate('upload.error.partial'),
|
||||
UPLOAD_ERR_NO_FILE => I18n::translate('upload.error.noFile'),
|
||||
UPLOAD_ERR_NO_TMP_DIR => I18n::translate('upload.error.tmpDir'),
|
||||
UPLOAD_ERR_CANT_WRITE => I18n::translate('upload.error.cantWrite'),
|
||||
UPLOAD_ERR_EXTENSION => I18n::translate('upload.error.extension')
|
||||
];
|
||||
|
||||
if (empty($files) === true) {
|
||||
@@ -749,9 +756,9 @@ class Api
|
||||
$uploadMaxFileSize = Str::toBytes(ini_get('upload_max_filesize'));
|
||||
|
||||
if ($postMaxSize < $uploadMaxFileSize) {
|
||||
throw new Exception(t('upload.error.iniPostSize'));
|
||||
throw new Exception(I18n::translate('upload.error.iniPostSize'));
|
||||
} else {
|
||||
throw new Exception(t('upload.error.noFiles'));
|
||||
throw new Exception(I18n::translate('upload.error.noFiles'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -764,7 +771,7 @@ class Api
|
||||
|
||||
try {
|
||||
if ($upload['error'] !== 0) {
|
||||
$errorMessage = $errorMessages[$upload['error']] ?? t('upload.error.default');
|
||||
$errorMessage = $errorMessages[$upload['error']] ?? I18n::translate('upload.error.default');
|
||||
throw new Exception($errorMessage);
|
||||
}
|
||||
|
||||
@@ -786,7 +793,7 @@ class Api
|
||||
// move the file to a location including the extension,
|
||||
// for better mime detection
|
||||
if ($debug === false && move_uploaded_file($upload['tmp_name'], $source) === false) {
|
||||
throw new Exception(t('upload.error.cantMove'));
|
||||
throw new Exception(I18n::translate('upload.error.cantMove'));
|
||||
}
|
||||
|
||||
$data = $callback($source, $filename);
|
||||
|
0
kirby/src/Api/Collection.php
Normal file → Executable file
0
kirby/src/Api/Collection.php
Normal file → Executable file
0
kirby/src/Api/Model.php
Normal file → Executable file
0
kirby/src/Api/Model.php
Normal file → Executable file
0
kirby/src/Cache/ApcuCache.php
Normal file → Executable file
0
kirby/src/Cache/ApcuCache.php
Normal file → Executable file
0
kirby/src/Cache/Cache.php
Normal file → Executable file
0
kirby/src/Cache/Cache.php
Normal file → Executable file
0
kirby/src/Cache/FileCache.php
Normal file → Executable file
0
kirby/src/Cache/FileCache.php
Normal file → Executable file
0
kirby/src/Cache/MemCached.php
Normal file → Executable file
0
kirby/src/Cache/MemCached.php
Normal file → Executable file
0
kirby/src/Cache/MemoryCache.php
Normal file → Executable file
0
kirby/src/Cache/MemoryCache.php
Normal file → Executable file
0
kirby/src/Cache/NullCache.php
Normal file → Executable file
0
kirby/src/Cache/NullCache.php
Normal file → Executable file
0
kirby/src/Cache/Value.php
Normal file → Executable file
0
kirby/src/Cache/Value.php
Normal file → Executable file
2
kirby/src/Cms/Api.php
Normal file → Executable file
2
kirby/src/Cms/Api.php
Normal file → Executable file
@@ -114,7 +114,7 @@ class Api extends BaseApi
|
||||
*/
|
||||
public function language(): ?string
|
||||
{
|
||||
return get('language') ?? $this->requestHeaders('x-language');
|
||||
return $this->requestQuery('language') ?? $this->requestHeaders('x-language');
|
||||
}
|
||||
|
||||
/**
|
||||
|
278
kirby/src/Cms/App.php
Normal file → Executable file
278
kirby/src/Cms/App.php
Normal file → Executable file
@@ -9,10 +9,10 @@ use Kirby\Exception\LogicException;
|
||||
use Kirby\Exception\NotFoundException;
|
||||
use Kirby\Filesystem\Dir;
|
||||
use Kirby\Filesystem\F;
|
||||
use Kirby\Http\Environment;
|
||||
use Kirby\Http\Request;
|
||||
use Kirby\Http\Response;
|
||||
use Kirby\Http\Router;
|
||||
use Kirby\Http\Server;
|
||||
use Kirby\Http\Uri;
|
||||
use Kirby\Http\Visitor;
|
||||
use Kirby\Session\AutoSession;
|
||||
@@ -22,6 +22,7 @@ use Kirby\Toolkit\A;
|
||||
use Kirby\Toolkit\Config;
|
||||
use Kirby\Toolkit\Controller;
|
||||
use Kirby\Toolkit\Properties;
|
||||
use Kirby\Toolkit\Str;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
@@ -71,7 +72,6 @@ class App
|
||||
protected $roots;
|
||||
protected $routes;
|
||||
protected $router;
|
||||
protected $server;
|
||||
protected $sessionHandler;
|
||||
protected $site;
|
||||
protected $system;
|
||||
@@ -97,7 +97,7 @@ class App
|
||||
// stuff from config and additional options
|
||||
$this->optionsFromConfig();
|
||||
$this->optionsFromProps($props['options'] ?? []);
|
||||
$this->optionsFromEnvironment();
|
||||
$this->optionsFromEnvironment($props);
|
||||
} finally {
|
||||
// register the Whoops error handler inside of a
|
||||
// try-finally block to ensure it's still registered
|
||||
@@ -105,6 +105,9 @@ class App
|
||||
$this->handleErrors();
|
||||
}
|
||||
|
||||
// a custom request setup must come before defining the path
|
||||
$this->setRequest($props['request'] ?? null);
|
||||
|
||||
// set the path to make it available for the url bakery
|
||||
$this->setPath($props['path'] ?? null);
|
||||
|
||||
@@ -115,7 +118,6 @@ class App
|
||||
// configurable properties
|
||||
$this->setOptionalProperties($props, [
|
||||
'languages',
|
||||
'request',
|
||||
'roles',
|
||||
'site',
|
||||
'user',
|
||||
@@ -330,26 +332,9 @@ class App
|
||||
*/
|
||||
public function call(string $path = null, string $method = null)
|
||||
{
|
||||
$router = $this->router();
|
||||
|
||||
/**
|
||||
* @todo Closures should not defined statically but
|
||||
* for each instance to avoid this constant setting and unsetting
|
||||
*/
|
||||
$router::$beforeEach = function ($route, $path, $method) {
|
||||
$this->trigger('route:before', compact('route', 'path', 'method'));
|
||||
};
|
||||
|
||||
$router::$afterEach = function ($route, $path, $method, $result, $final) {
|
||||
return $this->apply('route:after', compact('route', 'path', 'method', 'result', 'final'), 'result');
|
||||
};
|
||||
|
||||
$result = $router->call($path ?? $this->path(), $method ?? $this->request()->method());
|
||||
|
||||
$router::$beforeEach = null;
|
||||
$router::$afterEach = null;
|
||||
|
||||
return $result;
|
||||
$path ??= $this->path();
|
||||
$method ??= $this->request()->method();
|
||||
return $this->router()->call($path, $method);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -529,6 +514,43 @@ class App
|
||||
return $this->core;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks/returns a CSRF token
|
||||
* @since 3.7.0
|
||||
*
|
||||
* @param string|null $check Pass a token here to compare it to the one in the session
|
||||
* @return string|bool Either the token or a boolean check result
|
||||
*/
|
||||
public function csrf(?string $check = null)
|
||||
{
|
||||
$session = $this->session();
|
||||
|
||||
// no arguments, generate/return a token
|
||||
// (check explicitly if there have been no arguments at all;
|
||||
// checking for null introduces a security issue because null could come
|
||||
// from user input or bugs in the calling code!)
|
||||
if (func_num_args() === 0) {
|
||||
$token = $session->get('kirby.csrf');
|
||||
|
||||
if (is_string($token) !== true) {
|
||||
$token = bin2hex(random_bytes(32));
|
||||
$session->set('kirby.csrf', $token);
|
||||
}
|
||||
|
||||
return $token;
|
||||
}
|
||||
|
||||
// argument has been passed, check the token
|
||||
if (
|
||||
is_string($check) === true &&
|
||||
is_string($session->get('kirby.csrf')) === true
|
||||
) {
|
||||
return hash_equals($session->get('kirby.csrf'), $check) === true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default language object
|
||||
*
|
||||
@@ -595,11 +617,11 @@ class App
|
||||
* Returns the environment object with access
|
||||
* to the detected host, base url and dedicated options
|
||||
*
|
||||
* @return \Kirby\Cms\Environment
|
||||
* @return \Kirby\Http\Environment
|
||||
*/
|
||||
public function environment()
|
||||
{
|
||||
return $this->environment;
|
||||
return $this->environment ?? new Environment();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -627,11 +649,13 @@ class App
|
||||
if ($id === '.') {
|
||||
if ($file = $parent->file($filename)) {
|
||||
return $file;
|
||||
} elseif ($file = $this->site()->file($filename)) {
|
||||
return $file;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($file = $this->site()->file($filename)) {
|
||||
return $file;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($page = $this->page($id, $parent, $drafts)) {
|
||||
@@ -645,6 +669,50 @@ class App
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an image from any page
|
||||
* specified by the path
|
||||
*
|
||||
* Example:
|
||||
* <?= App::image('some/page/myimage.jpg') ?>
|
||||
*
|
||||
* @param string|null $path
|
||||
* @return \Kirby\Cms\File|null
|
||||
*
|
||||
* @todo merge with App::file()
|
||||
*/
|
||||
public function image(?string $path = null)
|
||||
{
|
||||
if ($path === null) {
|
||||
return $this->site()->page()->image();
|
||||
}
|
||||
|
||||
$uri = dirname($path);
|
||||
$filename = basename($path);
|
||||
|
||||
if ($uri === '.') {
|
||||
$uri = null;
|
||||
}
|
||||
|
||||
switch ($uri) {
|
||||
case '/':
|
||||
$parent = $this->site();
|
||||
break;
|
||||
case null:
|
||||
$parent = $this->site()->page();
|
||||
break;
|
||||
default:
|
||||
$parent = $this->site()->page($uri);
|
||||
break;
|
||||
}
|
||||
|
||||
if ($parent) {
|
||||
return $parent->image($filename);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current App instance
|
||||
*
|
||||
@@ -770,14 +838,28 @@ class App
|
||||
* Renders a single KirbyTag with the given attributes
|
||||
*
|
||||
* @internal
|
||||
* @param string $type
|
||||
* @param string|array $type Tag type or array with all tag arguments
|
||||
* (the key of the first element becomes the type)
|
||||
* @param string|null $value
|
||||
* @param array $attr
|
||||
* @param array $data
|
||||
* @return string
|
||||
*/
|
||||
public function kirbytag(string $type, string $value = null, array $attr = [], array $data = []): string
|
||||
public function kirbytag($type, ?string $value = null, array $attr = [], array $data = []): string
|
||||
{
|
||||
if (is_array($type) === true) {
|
||||
$kirbytag = $type;
|
||||
$type = key($kirbytag);
|
||||
$value = current($kirbytag);
|
||||
$attr = $kirbytag;
|
||||
|
||||
// check data attribute and separate from attr data if exists
|
||||
if (isset($attr['data']) === true) {
|
||||
$data = $attr['data'];
|
||||
unset($attr['data']);
|
||||
}
|
||||
}
|
||||
|
||||
$data['kirby'] = $data['kirby'] ?? $this;
|
||||
$data['site'] = $data['site'] ?? $data['kirby']->site();
|
||||
$data['parent'] = $data['parent'] ?? $data['site']->page();
|
||||
@@ -813,20 +895,21 @@ class App
|
||||
*
|
||||
* @internal
|
||||
* @param string|null $text
|
||||
* @param array $data
|
||||
* @param bool $inline (deprecated: use $data['markdown']['inline'] instead)
|
||||
* @param array $options
|
||||
* @param bool $inline (deprecated: use $options['markdown']['inline'] instead)
|
||||
* @return string
|
||||
* @todo add deprecation warning for $inline parameter in 3.7.0
|
||||
* @todo rename $data parameter to $options in 3.7.0
|
||||
* @todo remove $inline parameter in in 3.8.0
|
||||
*/
|
||||
public function kirbytext(string $text = null, array $data = [], bool $inline = false): string
|
||||
public function kirbytext(string $text = null, array $options = [], bool $inline = false): string
|
||||
{
|
||||
$options = A::merge([
|
||||
'markdown' => [
|
||||
'inline' => $inline
|
||||
]
|
||||
], $data);
|
||||
// warning for deprecated fourth parameter
|
||||
// @codeCoverageIgnoreStart
|
||||
if (func_num_args() === 3) {
|
||||
Helpers::deprecated('Cms\App::kirbytext(): the $inline parameter is deprecated and will be removed in Kirby 3.8.0. Use $options[\'markdown\'][\'inline\'] instead.');
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
$options['markdown']['inline'] ??= $inline;
|
||||
|
||||
$text = $this->apply('kirbytext:before', compact('text'), 'text');
|
||||
$text = $this->kirbytags($text, $options);
|
||||
@@ -924,23 +1007,22 @@ class App
|
||||
*
|
||||
* @internal
|
||||
* @param string|null $text
|
||||
* @param bool|array $options
|
||||
* @param bool|array $options Boolean inline value is deprecated, use `['inline' => true]` instead
|
||||
* @return string
|
||||
* @todo rename $inline parameter to $options in 3.7.0
|
||||
* @todo add deprecation warning for boolean $options in 3.7.0
|
||||
* @todo remove boolean $options in in 3.8.0
|
||||
*/
|
||||
public function markdown(string $text = null, $inline = null): string
|
||||
public function markdown(string $text = null, $options = null): string
|
||||
{
|
||||
// TODO: remove after renaming parameter
|
||||
$options = $inline;
|
||||
|
||||
// support for the old syntax to enable inline mode as second argument
|
||||
// @codeCoverageIgnoreStart
|
||||
if (is_bool($options) === true) {
|
||||
Helpers::deprecated('Cms\App::markdown(): Passing a boolean as second parameter has been deprecated and won\'t be supported anymore in Kirby 3.8.0. Instead pass array with the key "inline" set to true or false.');
|
||||
|
||||
$options = [
|
||||
'inline' => $options
|
||||
];
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
// merge global options with local options
|
||||
$options = array_merge(
|
||||
@@ -948,9 +1030,10 @@ class App
|
||||
(array)$options
|
||||
);
|
||||
|
||||
// TODO: deprecate passing the $inline parameter in 3.7.0
|
||||
// TODO: remove passing the $inline parameter in 3.8.0
|
||||
$inline = $options['inline'] ?? false;
|
||||
// $options['inline'] is set to `false` to avoid the deprecation
|
||||
// warning in the component; this can also be removed in 3.8.0
|
||||
$inline = $options['inline'] ??= false;
|
||||
return ($this->component('markdown'))($this, $text, $options, $inline);
|
||||
}
|
||||
|
||||
@@ -1024,15 +1107,20 @@ class App
|
||||
* Load all options for the current
|
||||
* server environment
|
||||
*
|
||||
* @param array $props
|
||||
* @return array
|
||||
*/
|
||||
protected function optionsFromEnvironment(): array
|
||||
protected function optionsFromEnvironment(array $props = []): array
|
||||
{
|
||||
// create the environment based on the URL setup
|
||||
$this->environment = new Environment($this->root('config'), $this->options['url'] ?? null);
|
||||
$this->environment = new Environment([
|
||||
'allowed' => $this->options['url'] ?? null,
|
||||
'cli' => $props['cli'] ?? null,
|
||||
], $props['server'] ?? null);
|
||||
|
||||
// merge into one clean options array
|
||||
return $this->options = array_replace_recursive($this->options, $this->environment->options());
|
||||
$options = $this->environment()->options($this->root('config'));
|
||||
return $this->options = array_replace_recursive($this->options, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1134,14 +1222,11 @@ class App
|
||||
return $this->path;
|
||||
}
|
||||
|
||||
$requestUri = '/' . $this->request()->url()->path();
|
||||
$scriptName = $_SERVER['SCRIPT_NAME'];
|
||||
$scriptFile = basename($scriptName);
|
||||
$scriptDir = dirname($scriptName);
|
||||
$scriptPath = $scriptFile === 'index.php' ? $scriptDir : $scriptName;
|
||||
$requestPath = preg_replace('!^' . preg_quote($scriptPath) . '!', '', $requestUri);
|
||||
$current = $this->request()->path()->toString();
|
||||
$index = $this->environment()->baseUri()->path()->toString();
|
||||
$path = Str::afterStart($current, $index);
|
||||
|
||||
return $this->setPath($requestPath)->path;
|
||||
return $this->setPath($path)->path;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1164,7 +1249,16 @@ class App
|
||||
*/
|
||||
public function request()
|
||||
{
|
||||
return $this->request = $this->request ?? new Request();
|
||||
if ($this->request !== null) {
|
||||
return $this->request;
|
||||
}
|
||||
|
||||
$env = $this->environment();
|
||||
|
||||
return $this->request = new Request([
|
||||
'cli' => $env->cli(),
|
||||
'url' => $env->requestUri()
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1201,7 +1295,7 @@ class App
|
||||
|
||||
// search for a draft if the page cannot be found
|
||||
if (!$page && $draft = $site->draft($path)) {
|
||||
if ($this->user() || $draft->isVerified(get('token'))) {
|
||||
if ($this->user() || $draft->isVerified($this->request()->get('token'))) {
|
||||
$page = $draft;
|
||||
}
|
||||
}
|
||||
@@ -1269,9 +1363,9 @@ class App
|
||||
* Returns a system root
|
||||
*
|
||||
* @param string $type
|
||||
* @return string
|
||||
* @return string|null
|
||||
*/
|
||||
public function root(string $type = 'index'): string
|
||||
public function root(string $type = 'index'): ?string
|
||||
{
|
||||
return $this->roots->__get($type);
|
||||
}
|
||||
@@ -1314,7 +1408,16 @@ class App
|
||||
}
|
||||
}
|
||||
|
||||
return $this->router = $this->router ?? new Router($routes);
|
||||
$hooks = [
|
||||
'beforeEach' => function ($route, $path, $method) {
|
||||
$this->trigger('route:before', compact('route', 'path', 'method'));
|
||||
},
|
||||
'afterEach' => function ($route, $path, $method, $result, $final) {
|
||||
return $this->apply('route:after', compact('route', 'path', 'method', 'result', 'final'), 'result');
|
||||
}
|
||||
];
|
||||
|
||||
return $this->router ??= new Router($routes, $hooks);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1344,11 +1447,16 @@ class App
|
||||
*/
|
||||
public function session(array $options = [])
|
||||
{
|
||||
// never cache responses that depend on the session
|
||||
$this->response()->cache(false);
|
||||
$this->response()->header('Cache-Control', 'no-store', true);
|
||||
$session = $this->sessionHandler()->get($options);
|
||||
|
||||
return $this->sessionHandler()->get($options);
|
||||
// disable caching for sessions that use the `Authorization` header;
|
||||
// cookie sessions are already covered by the `Cookie` class
|
||||
if ($session->mode() === 'manual') {
|
||||
$this->response()->cache(false);
|
||||
$this->response()->header('Cache-Control', 'no-store, private', true);
|
||||
}
|
||||
|
||||
return $session;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1447,13 +1555,17 @@ class App
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Server object
|
||||
* Returns the Environment object
|
||||
* @deprecated 3.7.0 Use `$kirby->environment()` instead
|
||||
*
|
||||
* @return \Kirby\Http\Server
|
||||
* @return \Kirby\Http\Environment
|
||||
* @todo Start throwing deprecation warnings in 3.8.0
|
||||
* @todo Remove in 3.9.0
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function server()
|
||||
{
|
||||
return $this->server ??= new Server();
|
||||
return $this->environment();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1505,12 +1617,24 @@ class App
|
||||
*
|
||||
* @internal
|
||||
* @param mixed $name
|
||||
* @param array $data
|
||||
* @param array|object $data Variables or an object that becomes `$item`
|
||||
* @param bool $return On `false`, directly echo the snippet
|
||||
* @return string|null
|
||||
*/
|
||||
public function snippet($name, array $data = []): ?string
|
||||
public function snippet($name, $data = [], bool $return = true): ?string
|
||||
{
|
||||
return ($this->component('snippet'))($this, $name, array_merge($this->data, $data));
|
||||
if (is_object($data) === true) {
|
||||
$data = ['item' => $data];
|
||||
}
|
||||
|
||||
$snippet = ($this->component('snippet'))($this, $name, array_merge($this->data, $data));
|
||||
|
||||
if ($return === true) {
|
||||
return $snippet;
|
||||
}
|
||||
|
||||
echo $snippet;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1602,7 +1726,7 @@ class App
|
||||
*
|
||||
* @param string $type
|
||||
* @param bool $object If set to `true`, the URL is converted to an object
|
||||
* @return string|\Kirby\Http\Uri
|
||||
* @return string|\Kirby\Http\Uri|null
|
||||
*/
|
||||
public function url(string $type = 'index', bool $object = false)
|
||||
{
|
||||
|
0
kirby/src/Cms/AppCaches.php
Normal file → Executable file
0
kirby/src/Cms/AppCaches.php
Normal file → Executable file
5
kirby/src/Cms/AppErrors.php
Normal file → Executable file
5
kirby/src/Cms/AppErrors.php
Normal file → Executable file
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Kirby\Cms;
|
||||
|
||||
use Kirby\Filesystem\F;
|
||||
use Kirby\Http\Response;
|
||||
use Kirby\Toolkit\I18n;
|
||||
use Whoops\Handler\CallbackHandler;
|
||||
@@ -46,7 +47,7 @@ trait AppErrors
|
||||
*/
|
||||
protected function handleErrors(): void
|
||||
{
|
||||
if ($this->request()->cli() === true) {
|
||||
if ($this->environment()->cli() === true) {
|
||||
$this->handleCliErrors();
|
||||
return;
|
||||
}
|
||||
@@ -129,7 +130,7 @@ trait AppErrors
|
||||
'code' => $code,
|
||||
'message' => $exception->getMessage(),
|
||||
'details' => $details,
|
||||
'file' => ltrim($exception->getFile(), $_SERVER['DOCUMENT_ROOT'] ?? ''),
|
||||
'file' => F::relativepath($exception->getFile(), $this->environment()->get('DOCUMENT_ROOT', '')),
|
||||
'line' => $exception->getLine(),
|
||||
], $httpCode);
|
||||
} else {
|
||||
|
12
kirby/src/Cms/AppPlugins.php
Normal file → Executable file
12
kirby/src/Cms/AppPlugins.php
Normal file → Executable file
@@ -790,6 +790,18 @@ trait AppPlugins
|
||||
$this->extendTemplates($this->core->templates());
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a native component was extended
|
||||
* @since 3.7.0
|
||||
*
|
||||
* @param string $component
|
||||
* @return bool
|
||||
*/
|
||||
public function isNativeComponent(string $component): bool
|
||||
{
|
||||
return $this->component($component) === $this->nativeComponent($component);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the native implementation
|
||||
* of a core component
|
||||
|
16
kirby/src/Cms/AppTranslations.php
Normal file → Executable file
16
kirby/src/Cms/AppTranslations.php
Normal file → Executable file
@@ -155,22 +155,6 @@ trait AppTranslations
|
||||
I18n::$locale = $translationCode ?? 'en';
|
||||
}
|
||||
|
||||
/**
|
||||
* Set locale settings
|
||||
*
|
||||
* @deprecated 3.5.0 Use `\Kirby\Toolkit\Locale::set()` instead
|
||||
* @todo Remove in 3.7.0
|
||||
*
|
||||
* @param string|array $locale
|
||||
*/
|
||||
public function setLocale($locale): void
|
||||
{
|
||||
// @codeCoverageIgnoreStart
|
||||
deprecated('`Kirby\Cms\App::setLocale()` has been deprecated and will be removed in 3.7.0. Use `Kirby\Toolkit\Locale::set()` instead');
|
||||
Locale::set($locale);
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a specific translation by locale
|
||||
*
|
||||
|
0
kirby/src/Cms/AppUsers.php
Normal file → Executable file
0
kirby/src/Cms/AppUsers.php
Normal file → Executable file
5
kirby/src/Cms/Auth.php
Normal file → Executable file
5
kirby/src/Cms/Auth.php
Normal file → Executable file
@@ -194,8 +194,9 @@ class Auth
|
||||
*/
|
||||
public function csrfFromSession(): string
|
||||
{
|
||||
$isDev = $this->kirby->option('panel.dev', false) !== false;
|
||||
return $this->kirby->option('api.csrf', $isDev ? 'dev' : csrf());
|
||||
$isDev = $this->kirby->option('panel.dev', false) !== false;
|
||||
$fallback = $isDev ? 'dev' : $this->kirby->csrf();
|
||||
return $this->kirby->option('api.csrf', $fallback);
|
||||
}
|
||||
|
||||
/**
|
||||
|
0
kirby/src/Cms/Auth/Challenge.php
Normal file → Executable file
0
kirby/src/Cms/Auth/Challenge.php
Normal file → Executable file
0
kirby/src/Cms/Auth/EmailChallenge.php
Normal file → Executable file
0
kirby/src/Cms/Auth/EmailChallenge.php
Normal file → Executable file
0
kirby/src/Cms/Auth/Status.php
Normal file → Executable file
0
kirby/src/Cms/Auth/Status.php
Normal file → Executable file
43
kirby/src/Cms/Block.php
Normal file → Executable file
43
kirby/src/Cms/Block.php
Normal file → Executable file
@@ -73,15 +73,17 @@ class Block extends Item
|
||||
{
|
||||
parent::__construct($params);
|
||||
|
||||
// import old builder format
|
||||
$params = BlockConverter::builderBlock($params);
|
||||
$params = BlockConverter::editorBlock($params);
|
||||
|
||||
if (isset($params['type']) === false) {
|
||||
throw new InvalidArgumentException('The block type is missing');
|
||||
}
|
||||
|
||||
$this->content = $params['content'] ?? [];
|
||||
// make sure the content is always defined as array to keep
|
||||
// at least a bit of backward compatibility with older fields
|
||||
if (is_array($params['content'] ?? null) === false) {
|
||||
$params['content'] = [];
|
||||
}
|
||||
|
||||
$this->content = $params['content'];
|
||||
$this->isHidden = $params['isHidden'] ?? false;
|
||||
$this->type = $params['type'];
|
||||
|
||||
@@ -99,34 +101,6 @@ class Block extends Item
|
||||
return $this->toHtml();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated method to return the block type
|
||||
*
|
||||
* @deprecated 3.5.0 Use `\Kirby\Cms\Block::type()` instead
|
||||
* @todo Remove in 3.7.0
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function _key(): string
|
||||
{
|
||||
deprecated('Block::_key() has been deprecated. Use Block::type() instead.');
|
||||
return $this->type();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated method to return the block id
|
||||
*
|
||||
* @deprecated 3.5.0 Use `\Kirby\Cms\Block::id()` instead
|
||||
* @todo Remove in 3.7.0
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function _uid(): string
|
||||
{
|
||||
deprecated('Block::_uid() has been deprecated. Use Block::id() instead.');
|
||||
return $this->id();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the content object
|
||||
*
|
||||
@@ -278,7 +252,8 @@ class Block extends Item
|
||||
public function toHtml(): string
|
||||
{
|
||||
try {
|
||||
return (string)snippet('blocks/' . $this->type(), $this->controller(), true);
|
||||
$kirby = $this->parent()->kirby();
|
||||
return (string)$kirby->snippet('blocks/' . $this->type(), $this->controller(), true);
|
||||
} catch (Throwable $e) {
|
||||
return '<p>Block error: "' . $e->getMessage() . '" in block type: "' . $this->type() . '"</p>';
|
||||
}
|
||||
|
@@ -1,280 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Kirby\Cms;
|
||||
|
||||
/**
|
||||
* Converts the data from the old builder and editor fields
|
||||
* to the format supported by the new block field.
|
||||
* @since 3.5.0
|
||||
*
|
||||
* @package Kirby Cms
|
||||
* @author Bastian Allgeier <bastian@getkirby.com>
|
||||
* @link https://getkirby.com
|
||||
* @copyright Bastian Allgeier
|
||||
* @license https://getkirby.com/license
|
||||
*/
|
||||
class BlockConverter
|
||||
{
|
||||
public static function builderBlock(array $params): array
|
||||
{
|
||||
if (isset($params['_key']) === false) {
|
||||
return $params;
|
||||
}
|
||||
|
||||
$params['type'] = $params['_key'];
|
||||
$params['content'] = $params;
|
||||
unset($params['_uid']);
|
||||
|
||||
return $params;
|
||||
}
|
||||
|
||||
public static function editorBlock(array $params): array
|
||||
{
|
||||
if (static::isEditorBlock($params) === false) {
|
||||
return $params;
|
||||
}
|
||||
|
||||
$method = 'editor' . $params['type'];
|
||||
|
||||
if (method_exists(static::class, $method) === true) {
|
||||
$params = static::$method($params);
|
||||
} else {
|
||||
$params = static::editorCustom($params);
|
||||
}
|
||||
|
||||
return $params;
|
||||
}
|
||||
|
||||
public static function editorBlocks(array $blocks = []): array
|
||||
{
|
||||
if (empty($blocks) === true) {
|
||||
return $blocks;
|
||||
}
|
||||
|
||||
if (static::isEditorBlock($blocks[0]) === false) {
|
||||
return $blocks;
|
||||
}
|
||||
|
||||
$list = [];
|
||||
$listStart = null;
|
||||
|
||||
foreach ($blocks as $index => $block) {
|
||||
if (in_array($block['type'], ['ul', 'ol']) === true) {
|
||||
$prev = $blocks[$index-1] ?? null;
|
||||
$next = $blocks[$index+1] ?? null;
|
||||
|
||||
// new list starts here
|
||||
if (!$prev || $prev['type'] !== $block['type']) {
|
||||
$listStart = $index;
|
||||
}
|
||||
|
||||
// add the block to the list
|
||||
$list[] = $block;
|
||||
|
||||
// list ends here
|
||||
if (!$next || $next['type'] !== $block['type']) {
|
||||
$blocks[$listStart] = [
|
||||
'content' => [
|
||||
'text' =>
|
||||
'<' . $block['type'] . '>' .
|
||||
implode(array_map(function ($item) {
|
||||
return '<li>' . $item['content'] . '</li>';
|
||||
}, $list)) .
|
||||
'</' . $block['type'] . '>',
|
||||
],
|
||||
'type' => 'list'
|
||||
];
|
||||
|
||||
$start = $listStart + 1;
|
||||
$end = $listStart + count($list);
|
||||
|
||||
for ($x = $start; $x <= $end; $x++) {
|
||||
$blocks[$x] = false;
|
||||
}
|
||||
|
||||
$listStart = null;
|
||||
$list = [];
|
||||
}
|
||||
} else {
|
||||
$blocks[$index] = static::editorBlock($block);
|
||||
}
|
||||
}
|
||||
|
||||
return array_filter($blocks);
|
||||
}
|
||||
|
||||
public static function editorBlockquote(array $params): array
|
||||
{
|
||||
return [
|
||||
'content' => [
|
||||
'text' => $params['content']
|
||||
],
|
||||
'type' => 'quote'
|
||||
];
|
||||
}
|
||||
|
||||
public static function editorCode(array $params): array
|
||||
{
|
||||
return [
|
||||
'content' => [
|
||||
'language' => $params['attrs']['language'] ?? null,
|
||||
'code' => $params['content']
|
||||
],
|
||||
'type' => 'code'
|
||||
];
|
||||
}
|
||||
|
||||
public static function editorCustom(array $params): array
|
||||
{
|
||||
return [
|
||||
'content' => array_merge(
|
||||
$params['attrs'] ?? [],
|
||||
[
|
||||
'body' => $params['content'] ?? null
|
||||
]
|
||||
),
|
||||
'type' => $params['type'] ?? 'unknown'
|
||||
];
|
||||
}
|
||||
|
||||
public static function editorH1(array $params): array
|
||||
{
|
||||
return static::editorHeading($params, 'h1');
|
||||
}
|
||||
|
||||
public static function editorH2(array $params): array
|
||||
{
|
||||
return static::editorHeading($params, 'h2');
|
||||
}
|
||||
|
||||
public static function editorH3(array $params): array
|
||||
{
|
||||
return static::editorHeading($params, 'h3');
|
||||
}
|
||||
|
||||
public static function editorH4(array $params): array
|
||||
{
|
||||
return static::editorHeading($params, 'h4');
|
||||
}
|
||||
|
||||
public static function editorH5(array $params): array
|
||||
{
|
||||
return static::editorHeading($params, 'h5');
|
||||
}
|
||||
|
||||
public static function editorH6(array $params): array
|
||||
{
|
||||
return static::editorHeading($params, 'h6');
|
||||
}
|
||||
|
||||
public static function editorHr(array $params): array
|
||||
{
|
||||
return [
|
||||
'content' => [],
|
||||
'type' => 'line'
|
||||
];
|
||||
}
|
||||
|
||||
public static function editorHeading(array $params, string $level): array
|
||||
{
|
||||
return [
|
||||
'content' => [
|
||||
'level' => $level,
|
||||
'text' => $params['content']
|
||||
],
|
||||
'type' => 'heading'
|
||||
];
|
||||
}
|
||||
|
||||
public static function editorImage(array $params): array
|
||||
{
|
||||
// internal image
|
||||
if (isset($params['attrs']['id']) === true) {
|
||||
return [
|
||||
'content' => [
|
||||
'alt' => $params['attrs']['alt'] ?? null,
|
||||
'caption' => $params['attrs']['caption'] ?? null,
|
||||
'image' => $params['attrs']['id'] ?? $params['attrs']['src'] ?? null,
|
||||
'location' => 'kirby',
|
||||
'ratio' => $params['attrs']['ratio'] ?? null,
|
||||
],
|
||||
'type' => 'image'
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'content' => [
|
||||
'alt' => $params['attrs']['alt'] ?? null,
|
||||
'caption' => $params['attrs']['caption'] ?? null,
|
||||
'src' => $params['attrs']['src'] ?? null,
|
||||
'location' => 'web',
|
||||
'ratio' => $params['attrs']['ratio'] ?? null,
|
||||
],
|
||||
'type' => 'image'
|
||||
];
|
||||
}
|
||||
|
||||
public static function editorKirbytext(array $params): array
|
||||
{
|
||||
return [
|
||||
'content' => [
|
||||
'text' => $params['content']
|
||||
],
|
||||
'type' => 'markdown'
|
||||
];
|
||||
}
|
||||
|
||||
public static function editorOl(array $params): array
|
||||
{
|
||||
return [
|
||||
'content' => [
|
||||
'text' => $params['content']
|
||||
],
|
||||
'type' => 'list'
|
||||
];
|
||||
}
|
||||
|
||||
public static function editorParagraph(array $params): array
|
||||
{
|
||||
return [
|
||||
'content' => [
|
||||
'text' => '<p>' . $params['content'] . '</p>'
|
||||
],
|
||||
'type' => 'text'
|
||||
];
|
||||
}
|
||||
|
||||
public static function editorUl(array $params): array
|
||||
{
|
||||
return [
|
||||
'content' => [
|
||||
'text' => $params['content']
|
||||
],
|
||||
'type' => 'list'
|
||||
];
|
||||
}
|
||||
|
||||
public static function editorVideo(array $params): array
|
||||
{
|
||||
return [
|
||||
'content' => [
|
||||
'caption' => $params['attrs']['caption'] ?? null,
|
||||
'url' => $params['attrs']['src'] ?? null
|
||||
],
|
||||
'type' => 'video'
|
||||
];
|
||||
}
|
||||
|
||||
public static function isEditorBlock(array $params): bool
|
||||
{
|
||||
if (isset($params['attrs']) === true) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (is_string($params['content'] ?? null) === true) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
29
kirby/src/Cms/Blocks.php
Normal file → Executable file
29
kirby/src/Cms/Blocks.php
Normal file → Executable file
@@ -2,12 +2,9 @@
|
||||
|
||||
namespace Kirby\Cms;
|
||||
|
||||
use Exception;
|
||||
use Kirby\Data\Json;
|
||||
use Kirby\Data\Yaml;
|
||||
use Kirby\Parsley\Parsley;
|
||||
use Kirby\Parsley\Schema\Blocks as BlockSchema;
|
||||
use Kirby\Toolkit\A;
|
||||
use Kirby\Toolkit\Str;
|
||||
use Throwable;
|
||||
|
||||
@@ -60,7 +57,6 @@ class Blocks extends Items
|
||||
public static function factory(array $items = null, array $params = [])
|
||||
{
|
||||
$items = static::extractFromLayouts($items);
|
||||
$items = BlockConverter::editorBlocks($items);
|
||||
|
||||
return parent::factory($items, $params);
|
||||
}
|
||||
@@ -77,12 +73,8 @@ class Blocks extends Items
|
||||
return [];
|
||||
}
|
||||
|
||||
if (
|
||||
// no columns = no layout
|
||||
array_key_exists('columns', $input[0]) === false ||
|
||||
// checks if this is a block for the builder plugin
|
||||
array_key_exists('_key', $input[0]) === true
|
||||
) {
|
||||
// no columns = no layout
|
||||
if (array_key_exists('columns', $input[0]) === false) {
|
||||
return $input;
|
||||
}
|
||||
|
||||
@@ -123,21 +115,8 @@ class Blocks extends Items
|
||||
try {
|
||||
$input = Json::decode((string)$input);
|
||||
} catch (Throwable $e) {
|
||||
try {
|
||||
// try to import the old YAML format
|
||||
$yaml = Yaml::decode((string)$input);
|
||||
$first = A::first($yaml);
|
||||
|
||||
// check for valid yaml
|
||||
if (empty($yaml) === true || (isset($first['_key']) === false && isset($first['type']) === false)) {
|
||||
throw new Exception('Invalid YAML');
|
||||
} else {
|
||||
$input = $yaml;
|
||||
}
|
||||
} catch (Throwable $e) {
|
||||
$parser = new Parsley((string)$input, new BlockSchema());
|
||||
$input = $parser->blocks();
|
||||
}
|
||||
$parser = new Parsley((string)$input, new BlockSchema());
|
||||
$input = $parser->blocks();
|
||||
}
|
||||
}
|
||||
|
||||
|
0
kirby/src/Cms/Blueprint.php
Normal file → Executable file
0
kirby/src/Cms/Blueprint.php
Normal file → Executable file
0
kirby/src/Cms/Collection.php
Normal file → Executable file
0
kirby/src/Cms/Collection.php
Normal file → Executable file
0
kirby/src/Cms/Collections.php
Normal file → Executable file
0
kirby/src/Cms/Collections.php
Normal file → Executable file
21
kirby/src/Cms/Content.php
Normal file → Executable file
21
kirby/src/Cms/Content.php
Normal file → Executable file
@@ -60,9 +60,14 @@ class Content
|
||||
*
|
||||
* @param array|null $data
|
||||
* @param object|null $parent
|
||||
* @param bool $normalize Set to `false` if the input field keys are already lowercase
|
||||
*/
|
||||
public function __construct(array $data = [], $parent = null)
|
||||
public function __construct(array $data = [], $parent = null, bool $normalize = true)
|
||||
{
|
||||
if ($normalize === true) {
|
||||
$data = array_change_key_case($data, CASE_LOWER);
|
||||
}
|
||||
|
||||
$this->data = $data;
|
||||
$this->parent = $parent;
|
||||
}
|
||||
@@ -163,9 +168,7 @@ class Content
|
||||
return $this->fields[$key];
|
||||
}
|
||||
|
||||
// fetch the value no matter the case
|
||||
$data = $this->data();
|
||||
$value = $data[$key] ?? array_change_key_case($data)[$key] ?? null;
|
||||
$value = $this->data()[$key] ?? null;
|
||||
|
||||
return $this->fields[$key] = new Field($this->parent, $key, $value);
|
||||
}
|
||||
@@ -178,10 +181,7 @@ class Content
|
||||
*/
|
||||
public function has(string $key): bool
|
||||
{
|
||||
$key = strtolower($key);
|
||||
$data = array_change_key_case($this->data);
|
||||
|
||||
return isset($data[$key]) === true;
|
||||
return isset($this->data[strtolower($key)]) === true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -208,7 +208,7 @@ class Content
|
||||
$copy->fields = null;
|
||||
|
||||
foreach ($keys as $key) {
|
||||
unset($copy->data[$key]);
|
||||
unset($copy->data[strtolower($key)]);
|
||||
}
|
||||
|
||||
return $copy;
|
||||
@@ -258,7 +258,8 @@ class Content
|
||||
*/
|
||||
public function update(array $content = null, bool $overwrite = false)
|
||||
{
|
||||
$this->data = $overwrite === true ? (array)$content : array_merge($this->data, (array)$content);
|
||||
$content = array_change_key_case((array)$content, CASE_LOWER);
|
||||
$this->data = $overwrite === true ? $content : array_merge($this->data, $content);
|
||||
|
||||
// clear cache of Field objects
|
||||
$this->fields = [];
|
||||
|
0
kirby/src/Cms/ContentLock.php
Normal file → Executable file
0
kirby/src/Cms/ContentLock.php
Normal file → Executable file
0
kirby/src/Cms/ContentLocks.php
Normal file → Executable file
0
kirby/src/Cms/ContentLocks.php
Normal file → Executable file
10
kirby/src/Cms/ContentTranslation.php
Normal file → Executable file
10
kirby/src/Cms/ContentTranslation.php
Normal file → Executable file
@@ -177,7 +177,12 @@ class ContentTranslation
|
||||
*/
|
||||
protected function setContent(array $content = null)
|
||||
{
|
||||
$this->content = $content;
|
||||
if ($content !== null) {
|
||||
$this->content = array_change_key_case($content);
|
||||
} else {
|
||||
$this->content = null;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -220,7 +225,8 @@ class ContentTranslation
|
||||
*/
|
||||
public function update(array $data = null, bool $overwrite = false)
|
||||
{
|
||||
$this->content = $overwrite === true ? (array)$data : array_merge($this->content(), (array)$data);
|
||||
$data = array_change_key_case((array)$data);
|
||||
$this->content = $overwrite === true ? $data : array_merge($this->content(), $data);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
7
kirby/src/Cms/Core.php
Normal file → Executable file
7
kirby/src/Cms/Core.php
Normal file → Executable file
@@ -267,6 +267,7 @@ class Core
|
||||
'textarea' => $this->root . '/fields/textarea.php',
|
||||
'time' => $this->root . '/fields/time.php',
|
||||
'toggle' => $this->root . '/fields/toggle.php',
|
||||
'toggles' => $this->root . '/fields/toggles.php',
|
||||
'url' => $this->root . '/fields/url.php',
|
||||
'users' => $this->root . '/fields/users.php',
|
||||
'writer' => $this->root . '/fields/writer.php'
|
||||
@@ -399,6 +400,7 @@ class Core
|
||||
public function sectionMixins(): array
|
||||
{
|
||||
return [
|
||||
'details' => $this->root . '/sections/mixins/details.php',
|
||||
'empty' => $this->root . '/sections/mixins/empty.php',
|
||||
'headline' => $this->root . '/sections/mixins/headline.php',
|
||||
'help' => $this->root . '/sections/mixins/help.php',
|
||||
@@ -407,6 +409,8 @@ class Core
|
||||
'min' => $this->root . '/sections/mixins/min.php',
|
||||
'pagination' => $this->root . '/sections/mixins/pagination.php',
|
||||
'parent' => $this->root . '/sections/mixins/parent.php',
|
||||
'search' => $this->root . '/sections/mixins/search.php',
|
||||
'sort' => $this->root . '/sections/mixins/sort.php',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -424,6 +428,7 @@ class Core
|
||||
'files' => $this->root . '/sections/files.php',
|
||||
'info' => $this->root . '/sections/info.php',
|
||||
'pages' => $this->root . '/sections/pages.php',
|
||||
'stats' => $this->root . '/sections/stats.php',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -452,7 +457,7 @@ class Core
|
||||
public function urls(): array
|
||||
{
|
||||
return $this->cache['urls'] ??= [
|
||||
'index' => fn () => $this->kirby->environment()->url(),
|
||||
'index' => fn () => $this->kirby->environment()->baseUrl(),
|
||||
'base' => fn (array $urls) => rtrim($urls['index'], '/'),
|
||||
'current' => function (array $urls) {
|
||||
$path = trim($this->kirby->path(), '/');
|
||||
|
0
kirby/src/Cms/Email.php
Normal file → Executable file
0
kirby/src/Cms/Email.php
Normal file → Executable file
@@ -1,222 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Kirby\Cms;
|
||||
|
||||
use Kirby\Exception\InvalidArgumentException;
|
||||
use Kirby\Filesystem\F;
|
||||
use Kirby\Http\Server;
|
||||
use Kirby\Http\Uri;
|
||||
|
||||
/**
|
||||
* The environment object takes care of
|
||||
* secure host and base URL detection, as
|
||||
* well as loading the dedicated
|
||||
* environment options.
|
||||
*
|
||||
* @package Kirby Cms
|
||||
* @author Bastian Allgeier <bastian@getkirby.com>
|
||||
* @link https://getkirby.com
|
||||
* @copyright Bastian Allgeier
|
||||
* @license https://getkirby.com/license
|
||||
*/
|
||||
class Environment
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $root;
|
||||
|
||||
/**
|
||||
* @var \Kirby\Http\Uri
|
||||
*/
|
||||
protected $uri;
|
||||
|
||||
/**
|
||||
* @param string $root
|
||||
* @param bool|string|array|null $allowed
|
||||
*/
|
||||
public function __construct(string $root, $allowed = null)
|
||||
{
|
||||
$this->root = $root;
|
||||
|
||||
if (is_string($allowed) === true) {
|
||||
$this->setupFromString($allowed);
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_array($allowed) === true) {
|
||||
$this->setupFromArray($allowed);
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_int($allowed) === true) {
|
||||
$this->setupFromFlag($allowed);
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_null($allowed) === true) {
|
||||
$this->setupFromFlag(Server::HOST_FROM_SERVER | Server::HOST_ALLOW_EMPTY);
|
||||
return;
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException('Invalid allow list setup for base URLs');
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw an exception if the host in the URI
|
||||
* object is empty
|
||||
*
|
||||
* @throws \Kirby\Exception\InvalidArgumentException
|
||||
* @return void
|
||||
*/
|
||||
protected function blockEmptyHost(): void
|
||||
{
|
||||
if (empty($this->uri->host()) === true) {
|
||||
throw new InvalidArgumentException('Invalid host setup. The detected host is not allowed.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the detected host name
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function host(): ?string
|
||||
{
|
||||
return $this->uri->host();
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads and returns the environment options
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function options(): array
|
||||
{
|
||||
$configHost = [];
|
||||
$configAddr = [];
|
||||
|
||||
$host = $this->host();
|
||||
$addr = Server::address();
|
||||
|
||||
// load the config for the host
|
||||
if (empty($host) === false) {
|
||||
$configHost = F::load($this->root . '/config.' . $host . '.php', []);
|
||||
}
|
||||
|
||||
// load the config for the server IP
|
||||
if (empty($addr) === false) {
|
||||
$configAddr = F::load($this->root . '/config.' . $addr . '.php', []);
|
||||
}
|
||||
|
||||
return array_replace_recursive($configHost, $configAddr);
|
||||
}
|
||||
|
||||
/**
|
||||
* The current URL should be auto detected from a host allowlist
|
||||
*
|
||||
* @param array $allowed
|
||||
* @return \Kirby\Http\Uri
|
||||
*/
|
||||
public function setupFromArray(array $allowed)
|
||||
{
|
||||
$allowedStrings = [];
|
||||
$allowedUris = [];
|
||||
$hosts = [];
|
||||
|
||||
foreach ($allowed as $url) {
|
||||
$allowedUris[] = $uri = new Uri($url, ['slash' => false]);
|
||||
$allowedStrings[] = $uri->toString();
|
||||
$hosts[] = $uri->host();
|
||||
}
|
||||
|
||||
// register all allowed hosts
|
||||
Server::hosts($hosts);
|
||||
|
||||
// get the index URL, including the subfolder if it exists
|
||||
$this->uri = Uri::index();
|
||||
|
||||
// empty URLs don't make sense in an allow list
|
||||
$this->blockEmptyHost();
|
||||
|
||||
// validate against the list of allowed base URLs
|
||||
if (in_array($this->uri->toString(), $allowedStrings) === false) {
|
||||
throw new InvalidArgumentException('The subfolder is not in the allowed base URL list');
|
||||
}
|
||||
|
||||
return $this->uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* The URL option receives a set of Server constant flags
|
||||
*
|
||||
* Server::HOST_FROM_SERVER
|
||||
* Server::HOST_FROM_SERVER | Server::HOST_ALLOW_EMPTY
|
||||
* Server::HOST_FROM_HOST
|
||||
* Server::HOST_FROM_HOST | Server::HOST_ALLOW_EMPTY
|
||||
*
|
||||
* @param int $allowed
|
||||
* @return \Kirby\Http\Uri
|
||||
*/
|
||||
public function setupFromFlag(int $allowed)
|
||||
{
|
||||
// allow host detection from host headers
|
||||
if ($allowed & Server::HOST_FROM_HEADER) {
|
||||
Server::hosts(Server::HOST_FROM_HEADER);
|
||||
|
||||
// detect host only from server name
|
||||
} else {
|
||||
Server::hosts(Server::HOST_FROM_SERVER);
|
||||
}
|
||||
|
||||
// get the base URL
|
||||
$this->uri = Uri::index();
|
||||
|
||||
// accept empty hosts
|
||||
if ($allowed & Server::HOST_ALLOW_EMPTY) {
|
||||
return $this->uri;
|
||||
}
|
||||
|
||||
// block empty hosts
|
||||
$this->blockEmptyHost();
|
||||
|
||||
return $this->uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* The current URL is predefined with a single string
|
||||
* and not detected automatically.
|
||||
*
|
||||
* If the url option is relative (i.e. '/' or '/some/subfolder')
|
||||
* The host will be empty and that's totally fine.
|
||||
* No need to block an empty host here
|
||||
*
|
||||
* @param string $allowed
|
||||
* @return \Kirby\Http\Uri
|
||||
*/
|
||||
public function setupFromString(string $allowed)
|
||||
{
|
||||
// create the URI object directly from the given option
|
||||
// without any form of detection from the server
|
||||
$this->uri = new Uri($allowed);
|
||||
|
||||
// only create an allow list from absolute URLs
|
||||
// otherwise the default secure host detection
|
||||
// behavior will be used
|
||||
if (empty($host = $this->uri->host()) === false) {
|
||||
Server::hosts([$host]);
|
||||
}
|
||||
|
||||
return $this->uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the base URL for the environment
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function url(): string
|
||||
{
|
||||
return $this->uri;
|
||||
}
|
||||
}
|
0
kirby/src/Cms/Event.php
Normal file → Executable file
0
kirby/src/Cms/Event.php
Normal file → Executable file
0
kirby/src/Cms/Field.php
Normal file → Executable file
0
kirby/src/Cms/Field.php
Normal file → Executable file
0
kirby/src/Cms/Fieldset.php
Normal file → Executable file
0
kirby/src/Cms/Fieldset.php
Normal file → Executable file
2
kirby/src/Cms/Fieldsets.php
Normal file → Executable file
2
kirby/src/Cms/Fieldsets.php
Normal file → Executable file
@@ -70,7 +70,7 @@ class Fieldsets extends Items
|
||||
|
||||
public static function factory(array $items = null, array $params = [])
|
||||
{
|
||||
$items ??= option('blocks.fieldsets', [
|
||||
$items ??= App::instance()->option('blocks.fieldsets', [
|
||||
'code' => 'blocks/code',
|
||||
'gallery' => 'blocks/gallery',
|
||||
'heading' => 'blocks/heading',
|
||||
|
43
kirby/src/Cms/File.php
Normal file → Executable file
43
kirby/src/Cms/File.php
Normal file → Executable file
@@ -425,16 +425,11 @@ class File extends ModelWithContent
|
||||
* Returns the parent id if a parent exists
|
||||
*
|
||||
* @internal
|
||||
* @todo 3.7.0 When setParent() is changed, the if check is not needed anymore
|
||||
* @return string|null
|
||||
* @return string
|
||||
*/
|
||||
public function parentId(): ?string
|
||||
public function parentId(): string
|
||||
{
|
||||
if ($parent = $this->parent()) {
|
||||
return $parent->id();
|
||||
}
|
||||
|
||||
return null;
|
||||
return $this->parent()->id();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -511,22 +506,13 @@ class File extends ModelWithContent
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the parent model object;
|
||||
* this property is required for `File::create()` and
|
||||
* will be generally required starting with Kirby 3.7.0
|
||||
* Sets the parent model object
|
||||
*
|
||||
* @param \Kirby\Cms\Model|null $parent
|
||||
* @param \Kirby\Cms\Model $parent
|
||||
* @return $this
|
||||
* @todo make property required in 3.7.0
|
||||
*/
|
||||
protected function setParent(Model $parent = null)
|
||||
protected function setParent(Model $parent)
|
||||
{
|
||||
// @codeCoverageIgnoreStart
|
||||
if ($parent === null) {
|
||||
deprecated('You are creating a `Kirby\Cms\File` object without passing the `parent` property. While unsupported, this hasn\'t caused any direct errors so far. To fix inconsistencies, the `parent` property will be required when creating a `Kirby\Cms\File` object in Kirby 3.7.0 and higher. Not passing this property will start throwing a breaking error.');
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
$this->parent = $parent;
|
||||
return $this;
|
||||
}
|
||||
@@ -641,7 +627,6 @@ class File extends ModelWithContent
|
||||
* used in the panel, when the file
|
||||
* gets dragged onto a textarea
|
||||
*
|
||||
* @todo Add `deprecated()` helper warning in 3.7.0
|
||||
* @todo Remove in 3.8.0
|
||||
*
|
||||
* @internal
|
||||
@@ -652,6 +637,7 @@ class File extends ModelWithContent
|
||||
*/
|
||||
public function dragText(string $type = null, bool $absolute = false): string
|
||||
{
|
||||
Helpers::deprecated('Cms\File::dragText() has been deprecated and will be removed in Kirby 3.8.0. Use $file->panel()->dragText() instead.');
|
||||
return $this->panel()->dragText($type, $absolute);
|
||||
}
|
||||
|
||||
@@ -659,7 +645,6 @@ class File extends ModelWithContent
|
||||
* Returns an array of all actions
|
||||
* that can be performed in the Panel
|
||||
*
|
||||
* @todo Add `deprecated()` helper warning in 3.7.0
|
||||
* @todo Remove in 3.8.0
|
||||
*
|
||||
* @since 3.3.0 This also checks for the lock status
|
||||
@@ -671,13 +656,13 @@ class File extends ModelWithContent
|
||||
*/
|
||||
public function panelOptions(array $unlock = []): array
|
||||
{
|
||||
Helpers::deprecated('Cms\File::panelOptions() has been deprecated and will be removed in Kirby 3.8.0. Use $file->panel()->options() instead.');
|
||||
return $this->panel()->options($unlock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the full path without leading slash
|
||||
*
|
||||
* @todo Add `deprecated()` helper warning in 3.7.0
|
||||
* @todo Remove in 3.8.0
|
||||
*
|
||||
* @internal
|
||||
@@ -686,6 +671,7 @@ class File extends ModelWithContent
|
||||
*/
|
||||
public function panelPath(): string
|
||||
{
|
||||
Helpers::deprecated('Cms\File::panelPath() has been deprecated and will be removed in Kirby 3.8.0. Use $file->panel()->path() instead.');
|
||||
return $this->panel()->path();
|
||||
}
|
||||
|
||||
@@ -693,7 +679,6 @@ class File extends ModelWithContent
|
||||
* Prepares the response data for file pickers
|
||||
* and file fields
|
||||
*
|
||||
* @todo Add `deprecated()` helper warning in 3.7.0
|
||||
* @todo Remove in 3.8.0
|
||||
*
|
||||
* @param array|null $params
|
||||
@@ -702,6 +687,7 @@ class File extends ModelWithContent
|
||||
*/
|
||||
public function panelPickerData(array $params = []): array
|
||||
{
|
||||
Helpers::deprecated('Cms\File::panelPickerData() has been deprecated and will be removed in Kirby 3.8.0. Use $file->panel()->pickerData() instead.');
|
||||
return $this->panel()->pickerData($params);
|
||||
}
|
||||
|
||||
@@ -709,7 +695,6 @@ class File extends ModelWithContent
|
||||
* Returns the url to the editing view
|
||||
* in the panel
|
||||
*
|
||||
* @todo Add `deprecated()` helper warning in 3.7.0
|
||||
* @todo Remove in 3.8.0
|
||||
*
|
||||
* @internal
|
||||
@@ -719,6 +704,7 @@ class File extends ModelWithContent
|
||||
*/
|
||||
public function panelUrl(bool $relative = false): string
|
||||
{
|
||||
Helpers::deprecated('Cms\File::panelUrl() has been deprecated and will be removed in Kirby 3.8.0. Use $file->panel()->url() instead.');
|
||||
return $this->panel()->url($relative);
|
||||
}
|
||||
|
||||
@@ -732,7 +718,7 @@ class File extends ModelWithContent
|
||||
public function previewUrl(): string
|
||||
{
|
||||
$parent = $this->parent();
|
||||
$url = url($this->id());
|
||||
$url = Url::to($this->id());
|
||||
|
||||
switch ($parent::CLASS_ALIAS) {
|
||||
case 'page':
|
||||
@@ -752,6 +738,11 @@ class File extends ModelWithContent
|
||||
return $this->url();
|
||||
}
|
||||
|
||||
// checks `file::url` component is extended
|
||||
if ($this->kirby()->isNativeComponent('file::url') === false) {
|
||||
return $this->url();
|
||||
}
|
||||
|
||||
return $url;
|
||||
case 'user':
|
||||
return $this->url();
|
||||
|
0
kirby/src/Cms/FileActions.php
Normal file → Executable file
0
kirby/src/Cms/FileActions.php
Normal file → Executable file
0
kirby/src/Cms/FileBlueprint.php
Normal file → Executable file
0
kirby/src/Cms/FileBlueprint.php
Normal file → Executable file
0
kirby/src/Cms/FileModifications.php
Normal file → Executable file
0
kirby/src/Cms/FileModifications.php
Normal file → Executable file
0
kirby/src/Cms/FilePermissions.php
Normal file → Executable file
0
kirby/src/Cms/FilePermissions.php
Normal file → Executable file
0
kirby/src/Cms/FilePicker.php
Normal file → Executable file
0
kirby/src/Cms/FilePicker.php
Normal file → Executable file
0
kirby/src/Cms/FileRules.php
Normal file → Executable file
0
kirby/src/Cms/FileRules.php
Normal file → Executable file
0
kirby/src/Cms/FileVersion.php
Normal file → Executable file
0
kirby/src/Cms/FileVersion.php
Normal file → Executable file
14
kirby/src/Cms/Files.php
Normal file → Executable file
14
kirby/src/Cms/Files.php
Normal file → Executable file
@@ -107,26 +107,30 @@ class Files extends Collection
|
||||
|
||||
/**
|
||||
* Tries to find a file by id/filename
|
||||
* @deprecated 3.7.0 Use `$files->find()` instead
|
||||
* @todo 3.8.0 Remove method
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @param string $id
|
||||
* @return \Kirby\Cms\File|null
|
||||
*/
|
||||
public function findById(string $id)
|
||||
{
|
||||
return $this->get(ltrim($this->parent->id() . '/' . $id, '/'));
|
||||
Helpers::deprecated('Cms\Files::findById() has been deprecated and will be removed in Kirby 3.8.0. Use $files->find() instead.');
|
||||
|
||||
return $this->findByKey($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias for FilesFinder::findById() which is
|
||||
* used internally in the Files collection to
|
||||
* map the get method correctly.
|
||||
* Finds a file by its filename
|
||||
* @internal Use `$files->find()` instead
|
||||
*
|
||||
* @param string $key
|
||||
* @return \Kirby\Cms\File|null
|
||||
*/
|
||||
public function findByKey(string $key)
|
||||
{
|
||||
return $this->findById($key);
|
||||
return $this->get(ltrim($this->parent->id() . '/' . $key, '/'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
0
kirby/src/Cms/Find.php
Normal file → Executable file
0
kirby/src/Cms/Find.php
Normal file → Executable file
0
kirby/src/Cms/HasChildren.php
Normal file → Executable file
0
kirby/src/Cms/HasChildren.php
Normal file → Executable file
0
kirby/src/Cms/HasFiles.php
Normal file → Executable file
0
kirby/src/Cms/HasFiles.php
Normal file → Executable file
0
kirby/src/Cms/HasMethods.php
Normal file → Executable file
0
kirby/src/Cms/HasMethods.php
Normal file → Executable file
0
kirby/src/Cms/HasSiblings.php
Normal file → Executable file
0
kirby/src/Cms/HasSiblings.php
Normal file → Executable file
87
kirby/src/Cms/Helpers.php
Executable file
87
kirby/src/Cms/Helpers.php
Executable file
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
namespace Kirby\Cms;
|
||||
|
||||
use Kirby\Exception\InvalidArgumentException;
|
||||
use Kirby\Toolkit\Str;
|
||||
|
||||
/**
|
||||
* The `Helpers` class hosts a few handy helper methods
|
||||
* @since 3.7.0
|
||||
*
|
||||
* @package Kirby Cms
|
||||
* @author Nico Hoffmann <nico@getkirby.com>
|
||||
* @link https://getkirby.com
|
||||
* @copyright Bastian Allgeier
|
||||
* @license https://getkirby.com/license
|
||||
*/
|
||||
class Helpers
|
||||
{
|
||||
/**
|
||||
* Triggers a deprecation warning if debug mode is active
|
||||
*
|
||||
* @param string $message
|
||||
* @return bool Whether the warning was triggered
|
||||
*/
|
||||
public static function deprecated(string $message): bool
|
||||
{
|
||||
if (App::instance()->option('debug') === true) {
|
||||
return trigger_error($message, E_USER_DEPRECATED) === true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple object and variable dumper
|
||||
* to help with debugging.
|
||||
*
|
||||
* @param mixed $variable
|
||||
* @param bool $echo
|
||||
* @return string
|
||||
*/
|
||||
public static function dump($variable, bool $echo = true): string
|
||||
{
|
||||
$kirby = App::instance();
|
||||
return ($kirby->component('dump'))($kirby, $variable, $echo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a helper was overridden by the user
|
||||
* by setting the `KIRBY_HELPER_*` constant
|
||||
* @internal
|
||||
*
|
||||
* @param string $name Name of the helper
|
||||
* @return bool
|
||||
*/
|
||||
public static function hasOverride(string $name): bool
|
||||
{
|
||||
$name = 'KIRBY_HELPER_' . strtoupper($name);
|
||||
return defined($name) === true && constant($name) === false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the size/length of numbers,
|
||||
* strings, arrays and countable objects
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return int
|
||||
* @throws \Kirby\Exception\InvalidArgumentException
|
||||
*/
|
||||
public static function size($value): int
|
||||
{
|
||||
if (is_numeric($value)) {
|
||||
return (int)$value;
|
||||
}
|
||||
|
||||
if (is_string($value)) {
|
||||
return Str::length(trim($value));
|
||||
}
|
||||
|
||||
if (is_countable($value)) {
|
||||
return count($value);
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException('Could not determine the size of the given value');
|
||||
}
|
||||
}
|
119
kirby/src/Cms/Html.php
Normal file → Executable file
119
kirby/src/Cms/Html.php
Normal file → Executable file
@@ -2,6 +2,9 @@
|
||||
|
||||
namespace Kirby\Cms;
|
||||
|
||||
use Kirby\Filesystem\F;
|
||||
use Kirby\Toolkit\A;
|
||||
|
||||
/**
|
||||
* The `Html` class provides methods for building
|
||||
* common HTML tags and also contains some helper
|
||||
@@ -15,6 +18,50 @@ namespace Kirby\Cms;
|
||||
*/
|
||||
class Html extends \Kirby\Toolkit\Html
|
||||
{
|
||||
/**
|
||||
* Creates one or multiple CSS link tags
|
||||
* @since 3.7.0
|
||||
*
|
||||
* @param string|array $url Relative or absolute URLs, an array of URLs or `@auto` for automatic template css loading
|
||||
* @param string|array $options Pass an array of attributes for the link tag or a media attribute string
|
||||
* @return string|null
|
||||
*/
|
||||
public static function css($url, $options = null): ?string
|
||||
{
|
||||
if (is_array($url) === true) {
|
||||
$links = A::map($url, fn ($url) => static::css($url, $options));
|
||||
return implode(PHP_EOL, $links);
|
||||
}
|
||||
|
||||
if (is_string($options) === true) {
|
||||
$options = ['media' => $options];
|
||||
}
|
||||
|
||||
$kirby = App::instance();
|
||||
|
||||
if ($url === '@auto') {
|
||||
if (!$url = Url::toTemplateAsset('css/templates', 'css')) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// only valid value for 'rel' is 'alternate stylesheet', if 'title' is given as well
|
||||
if (
|
||||
($options['rel'] ?? '') !== 'alternate stylesheet' ||
|
||||
($options['title'] ?? '') === ''
|
||||
) {
|
||||
$options['rel'] = 'stylesheet';
|
||||
}
|
||||
|
||||
$url = ($kirby->component('css'))($kirby, $url, $options);
|
||||
$url = Url::to($url);
|
||||
$attr = array_merge((array)$options, [
|
||||
'href' => $url
|
||||
]);
|
||||
|
||||
return '<link ' . static::attr($attr) . '>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an `a` tag with an absolute Url
|
||||
*
|
||||
@@ -27,4 +74,76 @@ class Html extends \Kirby\Toolkit\Html
|
||||
{
|
||||
return parent::link(Url::to($href), $text, $attr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a script tag to load a javascript file
|
||||
* @since 3.7.0
|
||||
*
|
||||
* @param string|array $url
|
||||
* @param string|array $options
|
||||
* @return string|null
|
||||
*/
|
||||
public static function js($url, $options = null): ?string
|
||||
{
|
||||
if (is_array($url) === true) {
|
||||
$scripts = A::map($url, fn ($url) => static::js($url, $options));
|
||||
return implode(PHP_EOL, $scripts);
|
||||
}
|
||||
|
||||
if (is_bool($options) === true) {
|
||||
$options = ['async' => $options];
|
||||
}
|
||||
|
||||
$kirby = App::instance();
|
||||
|
||||
if ($url === '@auto') {
|
||||
if (!$url = Url::toTemplateAsset('js/templates', 'js')) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
$url = ($kirby->component('js'))($kirby, $url, $options);
|
||||
$url = Url::to($url);
|
||||
$attr = array_merge((array)$options, ['src' => $url]);
|
||||
|
||||
return '<script ' . static::attr($attr) . '></script>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Includes an SVG file by absolute or
|
||||
* relative file path.
|
||||
* @since 3.7.0
|
||||
*
|
||||
* @param string|\Kirby\Cms\File $file
|
||||
* @return string|false
|
||||
*/
|
||||
public static function svg($file)
|
||||
{
|
||||
// support for Kirby's file objects
|
||||
if (
|
||||
is_a($file, 'Kirby\Cms\File') === true &&
|
||||
$file->extension() === 'svg'
|
||||
) {
|
||||
return $file->read();
|
||||
}
|
||||
|
||||
if (is_string($file) === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$extension = F::extension($file);
|
||||
|
||||
// check for valid svg files
|
||||
if ($extension !== 'svg') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// try to convert relative paths to absolute
|
||||
if (file_exists($file) === false) {
|
||||
$root = App::instance()->root();
|
||||
$file = realpath($root . '/' . $file);
|
||||
}
|
||||
|
||||
return F::read($file);
|
||||
}
|
||||
}
|
||||
|
0
kirby/src/Cms/Ingredients.php
Normal file → Executable file
0
kirby/src/Cms/Ingredients.php
Normal file → Executable file
6
kirby/src/Cms/Item.php
Normal file → Executable file
6
kirby/src/Cms/Item.php
Normal file → Executable file
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace Kirby\Cms;
|
||||
|
||||
use Kirby\Toolkit\Str;
|
||||
|
||||
/**
|
||||
* The Item class is the foundation
|
||||
* for every object in context with
|
||||
@@ -53,9 +55,9 @@ class Item
|
||||
{
|
||||
$siblingsClass = static::ITEMS_CLASS;
|
||||
|
||||
$this->id = $params['id'] ?? uuid();
|
||||
$this->id = $params['id'] ?? Str::uuid();
|
||||
$this->params = $params;
|
||||
$this->parent = $params['parent'] ?? site();
|
||||
$this->parent = $params['parent'] ?? App::instance()->site();
|
||||
$this->siblings = $params['siblings'] ?? new $siblingsClass();
|
||||
}
|
||||
|
||||
|
4
kirby/src/Cms/Items.php
Normal file → Executable file
4
kirby/src/Cms/Items.php
Normal file → Executable file
@@ -38,7 +38,7 @@ class Items extends Collection
|
||||
public function __construct($objects = [], array $options = [])
|
||||
{
|
||||
$this->options = $options;
|
||||
$this->parent = $options['parent'] ?? site();
|
||||
$this->parent = $options['parent'] ?? App::instance()->site();
|
||||
|
||||
parent::__construct($objects, $this->parent);
|
||||
}
|
||||
@@ -55,7 +55,7 @@ class Items extends Collection
|
||||
{
|
||||
$options = array_merge([
|
||||
'options' => [],
|
||||
'parent' => site(),
|
||||
'parent' => App::instance()->site(),
|
||||
], $params);
|
||||
|
||||
if (empty($items) === true || is_array($items) === false) {
|
||||
|
2
kirby/src/Cms/Language.php
Normal file → Executable file
2
kirby/src/Cms/Language.php
Normal file → Executable file
@@ -340,7 +340,7 @@ class Language extends Model
|
||||
*/
|
||||
public static function loadRules(string $code)
|
||||
{
|
||||
$kirby = kirby();
|
||||
$kirby = App::instance();
|
||||
$code = Str::contains($code, '.') ? Str::before($code, '.') : $code;
|
||||
$file = $kirby->root('i18n:rules') . '/' . $code . '.json';
|
||||
|
||||
|
0
kirby/src/Cms/LanguageRouter.php
Normal file → Executable file
0
kirby/src/Cms/LanguageRouter.php
Normal file → Executable file
0
kirby/src/Cms/LanguageRoutes.php
Normal file → Executable file
0
kirby/src/Cms/LanguageRoutes.php
Normal file → Executable file
0
kirby/src/Cms/LanguageRules.php
Normal file → Executable file
0
kirby/src/Cms/LanguageRules.php
Normal file → Executable file
0
kirby/src/Cms/Languages.php
Normal file → Executable file
0
kirby/src/Cms/Languages.php
Normal file → Executable file
0
kirby/src/Cms/Layout.php
Normal file → Executable file
0
kirby/src/Cms/Layout.php
Normal file → Executable file
0
kirby/src/Cms/LayoutColumn.php
Normal file → Executable file
0
kirby/src/Cms/LayoutColumn.php
Normal file → Executable file
0
kirby/src/Cms/LayoutColumns.php
Normal file → Executable file
0
kirby/src/Cms/LayoutColumns.php
Normal file → Executable file
3
kirby/src/Cms/Layouts.php
Normal file → Executable file
3
kirby/src/Cms/Layouts.php
Normal file → Executable file
@@ -3,6 +3,7 @@
|
||||
namespace Kirby\Cms;
|
||||
|
||||
use Kirby\Data\Data;
|
||||
use Kirby\Toolkit\Str;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
@@ -27,7 +28,7 @@ class Layouts extends Items
|
||||
if (array_key_exists('content', $first) === true || array_key_exists('type', $first) === true) {
|
||||
$items = [
|
||||
[
|
||||
'id' => uuid(),
|
||||
'id' => Str::uuid(),
|
||||
'columns' => [
|
||||
[
|
||||
'width' => '1/1',
|
||||
|
0
kirby/src/Cms/Loader.php
Normal file → Executable file
0
kirby/src/Cms/Loader.php
Normal file → Executable file
0
kirby/src/Cms/Media.php
Normal file → Executable file
0
kirby/src/Cms/Media.php
Normal file → Executable file
0
kirby/src/Cms/Model.php
Normal file → Executable file
0
kirby/src/Cms/Model.php
Normal file → Executable file
0
kirby/src/Cms/ModelPermissions.php
Normal file → Executable file
0
kirby/src/Cms/ModelPermissions.php
Normal file → Executable file
17
kirby/src/Cms/ModelWithContent.php
Normal file → Executable file
17
kirby/src/Cms/ModelWithContent.php
Normal file → Executable file
@@ -90,7 +90,8 @@ abstract class ModelWithContent extends Model
|
||||
return $this->content;
|
||||
}
|
||||
|
||||
return $this->setContent($this->readContent())->content;
|
||||
// don't normalize field keys (already handled by the `Data` class)
|
||||
return $this->content = new Content($this->readContent(), $this, false);
|
||||
|
||||
// multi language support
|
||||
} else {
|
||||
@@ -102,7 +103,8 @@ abstract class ModelWithContent extends Model
|
||||
|
||||
// get the translation by code
|
||||
if ($translation = $this->translation($languageCode)) {
|
||||
$content = new Content($translation->content(), $this);
|
||||
// don't normalize field keys (already handled by the `ContentTranslation` class)
|
||||
$content = new Content($translation->content(), $this, false);
|
||||
} else {
|
||||
throw new InvalidArgumentException('Invalid language: ' . $languageCode);
|
||||
}
|
||||
@@ -453,7 +455,7 @@ abstract class ModelWithContent extends Model
|
||||
if ($languageCode !== $kirby->defaultLanguage()->code()) {
|
||||
foreach ($this->blueprint()->fields() as $field) {
|
||||
if (($field['translate'] ?? true) === false) {
|
||||
$content[$field['name']] = null;
|
||||
$content[strtolower($field['name'])] = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -544,7 +546,8 @@ abstract class ModelWithContent extends Model
|
||||
$result = Str::$handler($template, array_replace([
|
||||
'kirby' => $this->kirby(),
|
||||
'site' => is_a($this, 'Kirby\Cms\Site') ? $this : $this->site(),
|
||||
static::CLASS_ALIAS => $this
|
||||
'model' => $this,
|
||||
static::CLASS_ALIAS => $this,
|
||||
], $data), ['fallback' => $fallback]);
|
||||
|
||||
return $result;
|
||||
@@ -652,7 +655,6 @@ abstract class ModelWithContent extends Model
|
||||
* Returns the panel icon definition
|
||||
*
|
||||
* @deprecated 3.6.0 Use `->panel()->image()` instead
|
||||
* @todo Add `deprecated()` helper warning in 3.7.0
|
||||
* @todo Remove in 3.8.0
|
||||
*
|
||||
* @internal
|
||||
@@ -662,12 +664,12 @@ abstract class ModelWithContent extends Model
|
||||
*/
|
||||
public function panelIcon(array $params = null): ?array
|
||||
{
|
||||
Helpers::deprecated('Cms\ModelWithContent::panelIcon() has been deprecated and will be removed in Kirby 3.8.0. Use $model->panel()->image() instead.');
|
||||
return $this->panel()->image($params);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated 3.6.0 Use `->panel()->image()` instead
|
||||
* @todo Add `deprecated()` helper warning in 3.7.0
|
||||
* @todo Remove in 3.8.0
|
||||
*
|
||||
* @internal
|
||||
@@ -677,6 +679,7 @@ abstract class ModelWithContent extends Model
|
||||
*/
|
||||
public function panelImage($settings = null): ?array
|
||||
{
|
||||
Helpers::deprecated('Cms\ModelWithContent::panelImage() has been deprecated and will be removed in Kirby 3.8.0. Use $model->panel()->image() instead.');
|
||||
return $this->panel()->image($settings);
|
||||
}
|
||||
|
||||
@@ -686,7 +689,6 @@ abstract class ModelWithContent extends Model
|
||||
* This also checks for the lock status
|
||||
*
|
||||
* @deprecated 3.6.0 Use `->panel()->options()` instead
|
||||
* @todo Add `deprecated()` helper warning in 3.7.0
|
||||
* @todo Remove in 3.8.0
|
||||
*
|
||||
* @param array $unlock An array of options that will be force-unlocked
|
||||
@@ -695,6 +697,7 @@ abstract class ModelWithContent extends Model
|
||||
*/
|
||||
public function panelOptions(array $unlock = []): array
|
||||
{
|
||||
Helpers::deprecated('Cms\ModelWithContent::panelOptions() has been deprecated and will be removed in Kirby 3.8.0. Use $model->panel()->options() instead.');
|
||||
return $this->panel()->options($unlock);
|
||||
}
|
||||
}
|
||||
|
0
kirby/src/Cms/Nest.php
Normal file → Executable file
0
kirby/src/Cms/Nest.php
Normal file → Executable file
0
kirby/src/Cms/NestCollection.php
Normal file → Executable file
0
kirby/src/Cms/NestCollection.php
Normal file → Executable file
0
kirby/src/Cms/NestObject.php
Normal file → Executable file
0
kirby/src/Cms/NestObject.php
Normal file → Executable file
45
kirby/src/Cms/Page.php
Normal file → Executable file
45
kirby/src/Cms/Page.php
Normal file → Executable file
@@ -7,6 +7,7 @@ use Kirby\Exception\InvalidArgumentException;
|
||||
use Kirby\Exception\NotFoundException;
|
||||
use Kirby\Filesystem\Dir;
|
||||
use Kirby\Filesystem\F;
|
||||
use Kirby\Http\Response;
|
||||
use Kirby\Http\Uri;
|
||||
use Kirby\Panel\Page as Panel;
|
||||
use Kirby\Toolkit\A;
|
||||
@@ -465,7 +466,7 @@ class Page extends ModelWithContent
|
||||
*/
|
||||
public function go(array $options = [], int $code = 302)
|
||||
{
|
||||
go($this->url($options), $code);
|
||||
Response::go($this->url($options), $code);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1029,11 +1030,19 @@ class Page extends ModelWithContent
|
||||
|
||||
// try to get the page from cache
|
||||
if (empty($data) === true && $this->isCacheable() === true) {
|
||||
$cache = $kirby->cache('pages');
|
||||
$cacheId = $this->cacheId($contentType);
|
||||
$result = $cache->get($cacheId);
|
||||
$html = $result['html'] ?? null;
|
||||
$response = $result['response'] ?? [];
|
||||
$cache = $kirby->cache('pages');
|
||||
$cacheId = $this->cacheId($contentType);
|
||||
$result = $cache->get($cacheId);
|
||||
$html = $result['html'] ?? null;
|
||||
$response = $result['response'] ?? [];
|
||||
$usesAuth = $result['usesAuth'] ?? false;
|
||||
$usesCookies = $result['usesCookies'] ?? [];
|
||||
|
||||
// if the request contains dynamic data that the cached response
|
||||
// relied on, don't use the cache to allow dynamic code to run
|
||||
if (Responder::isPrivate($usesAuth, $usesCookies) === true) {
|
||||
$html = null;
|
||||
}
|
||||
|
||||
// reconstruct the response configuration
|
||||
if (empty($html) === false && empty($response) === false) {
|
||||
@@ -1060,15 +1069,15 @@ class Page extends ModelWithContent
|
||||
// render the page
|
||||
$html = $template->render($kirby->data);
|
||||
|
||||
// convert the response configuration to an array
|
||||
$response = $kirby->response()->toArray();
|
||||
|
||||
// cache the result
|
||||
if ($cache !== null && $kirby->response()->cache() === true) {
|
||||
$response = $kirby->response();
|
||||
if ($cache !== null && $response->cache() === true) {
|
||||
$cache->set($cacheId, [
|
||||
'html' => $html,
|
||||
'response' => $response
|
||||
], $kirby->response()->expires() ?? 0);
|
||||
'html' => $html,
|
||||
'response' => $response->toArray(),
|
||||
'usesAuth' => $response->usesAuth(),
|
||||
'usesCookies' => $response->usesCookies(),
|
||||
], $response->expires() ?? 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1471,7 +1480,6 @@ class Page extends ModelWithContent
|
||||
* gets dragged onto a textarea
|
||||
*
|
||||
* @deprecated 3.6.0 Use `->panel()->dragText()` instead
|
||||
* @todo Add `deprecated()` helper warning in 3.7.0
|
||||
* @todo Remove in 3.8.0
|
||||
*
|
||||
* @internal
|
||||
@@ -1481,6 +1489,7 @@ class Page extends ModelWithContent
|
||||
*/
|
||||
public function dragText(string $type = null): string
|
||||
{
|
||||
Helpers::deprecated('Cms\Page::dragText() has been deprecated and will be removed in Kirby 3.8.0. Use $page->panel()->dragText() instead.');
|
||||
return $this->panel()->dragText($type);
|
||||
}
|
||||
|
||||
@@ -1489,7 +1498,6 @@ class Page extends ModelWithContent
|
||||
* used in the panel to make routing work properly
|
||||
*
|
||||
* @deprecated 3.6.0 Use `->panel()->id()` instead
|
||||
* @todo Add `deprecated()` helper warning in 3.7.0
|
||||
* @todo Remove in 3.8.0
|
||||
*
|
||||
* @internal
|
||||
@@ -1498,6 +1506,7 @@ class Page extends ModelWithContent
|
||||
*/
|
||||
public function panelId(): string
|
||||
{
|
||||
Helpers::deprecated('Cms\Page::panelId() has been deprecated and will be removed in Kirby 3.8.0. Use $page->panel()->id() instead.');
|
||||
return $this->panel()->id();
|
||||
}
|
||||
|
||||
@@ -1505,7 +1514,6 @@ class Page extends ModelWithContent
|
||||
* Returns the full path without leading slash
|
||||
*
|
||||
* @deprecated 3.6.0 Use `->panel()->path()` instead
|
||||
* @todo Add `deprecated()` helper warning in 3.7.0
|
||||
* @todo Remove in 3.8.0
|
||||
*
|
||||
* @internal
|
||||
@@ -1514,6 +1522,7 @@ class Page extends ModelWithContent
|
||||
*/
|
||||
public function panelPath(): string
|
||||
{
|
||||
Helpers::deprecated('Cms\Page::panelPath() has been deprecated and will be removed in Kirby 3.8.0. Use $page->panel()->path() instead.');
|
||||
return $this->panel()->path();
|
||||
}
|
||||
|
||||
@@ -1522,7 +1531,6 @@ class Page extends ModelWithContent
|
||||
* and page fields
|
||||
*
|
||||
* @deprecated 3.6.0 Use `->panel()->pickerData()` instead
|
||||
* @todo Add `deprecated()` helper warning in 3.7.0
|
||||
* @todo Remove in 3.8.0
|
||||
*
|
||||
* @param array|null $params
|
||||
@@ -1531,6 +1539,7 @@ class Page extends ModelWithContent
|
||||
*/
|
||||
public function panelPickerData(array $params = []): array
|
||||
{
|
||||
Helpers::deprecated('Cms\Page::panelPickerData() has been deprecated and will be removed in Kirby 3.8.0. Use $page->panel()->pickerData() instead.');
|
||||
return $this->panel()->pickerData($params);
|
||||
}
|
||||
|
||||
@@ -1539,7 +1548,6 @@ class Page extends ModelWithContent
|
||||
* in the panel
|
||||
*
|
||||
* @deprecated 3.6.0 Use `->panel()->url()` instead
|
||||
* @todo Add `deprecated()` helper warning in 3.7.0
|
||||
* @todo Remove in 3.8.0
|
||||
*
|
||||
* @internal
|
||||
@@ -1549,6 +1557,7 @@ class Page extends ModelWithContent
|
||||
*/
|
||||
public function panelUrl(bool $relative = false): string
|
||||
{
|
||||
Helpers::deprecated('Cms\Page::panelUrl() has been deprecated and will be removed in Kirby 3.8.0. Use $page->panel()->url() instead.');
|
||||
return $this->panel()->url($relative);
|
||||
}
|
||||
}
|
||||
|
3
kirby/src/Cms/PageActions.php
Normal file → Executable file
3
kirby/src/Cms/PageActions.php
Normal file → Executable file
@@ -11,6 +11,7 @@ use Kirby\Filesystem\Dir;
|
||||
use Kirby\Filesystem\F;
|
||||
use Kirby\Form\Form;
|
||||
use Kirby\Toolkit\A;
|
||||
use Kirby\Toolkit\I18n;
|
||||
use Kirby\Toolkit\Str;
|
||||
|
||||
/**
|
||||
@@ -665,7 +666,7 @@ trait PageActions
|
||||
{
|
||||
|
||||
// create the slug for the duplicate
|
||||
$slug = Str::slug($slug ?? $this->slug() . '-' . Str::slug(t('page.duplicate.appendix')));
|
||||
$slug = Str::slug($slug ?? $this->slug() . '-' . Str::slug(I18n::translate('page.duplicate.appendix')));
|
||||
|
||||
$arguments = [
|
||||
'originalPage' => $this,
|
||||
|
0
kirby/src/Cms/PageBlueprint.php
Normal file → Executable file
0
kirby/src/Cms/PageBlueprint.php
Normal file → Executable file
0
kirby/src/Cms/PagePermissions.php
Normal file → Executable file
0
kirby/src/Cms/PagePermissions.php
Normal file → Executable file
0
kirby/src/Cms/PagePicker.php
Normal file → Executable file
0
kirby/src/Cms/PagePicker.php
Normal file → Executable file
0
kirby/src/Cms/PageRules.php
Normal file → Executable file
0
kirby/src/Cms/PageRules.php
Normal file → Executable file
0
kirby/src/Cms/PageSiblings.php
Normal file → Executable file
0
kirby/src/Cms/PageSiblings.php
Normal file → Executable file
108
kirby/src/Cms/Pages.php
Normal file → Executable file
108
kirby/src/Cms/Pages.php
Normal file → Executable file
@@ -54,12 +54,14 @@ class Pages extends Collection
|
||||
*/
|
||||
public function add($object)
|
||||
{
|
||||
$site = App::instance()->site();
|
||||
|
||||
// add a pages collection
|
||||
if (is_a($object, self::class) === true) {
|
||||
$this->data = array_merge($this->data, $object->data);
|
||||
|
||||
// add a page by id
|
||||
} elseif (is_string($object) === true && $page = page($object)) {
|
||||
} elseif (is_string($object) === true && $page = $site->find($object)) {
|
||||
$this->__set($page->id(), $page);
|
||||
|
||||
// add a page object
|
||||
@@ -92,7 +94,7 @@ class Pages extends Collection
|
||||
*/
|
||||
public function children()
|
||||
{
|
||||
$children = new Pages([], $this->parent);
|
||||
$children = new Pages([]);
|
||||
|
||||
foreach ($this->data as $page) {
|
||||
foreach ($page->children() as $childKey => $child) {
|
||||
@@ -130,7 +132,7 @@ class Pages extends Collection
|
||||
*/
|
||||
public function drafts()
|
||||
{
|
||||
$drafts = new Pages([], $this->parent);
|
||||
$drafts = new Pages([]);
|
||||
|
||||
foreach ($this->data as $page) {
|
||||
foreach ($page->drafts() as $draftKey => $draft) {
|
||||
@@ -199,51 +201,38 @@ class Pages extends Collection
|
||||
* Finds a page in the collection by id.
|
||||
* This works recursively for children and
|
||||
* children of children, etc.
|
||||
* @deprecated 3.7.0 Use `$pages->get()` or `$pages->find()` instead
|
||||
* @todo 3.8.0 Remove method
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @param string|null $id
|
||||
* @return mixed
|
||||
*/
|
||||
public function findById(string $id = null)
|
||||
{
|
||||
if ($id === null) {
|
||||
return null;
|
||||
}
|
||||
Helpers::deprecated('Cms\Pages::findById() has been deprecated and will be removed in Kirby 3.8.0. Use $pages->get() or $pages->find() instead.');
|
||||
|
||||
// remove trailing or leading slashes
|
||||
$id = trim($id, '/');
|
||||
|
||||
// strip extensions from the id
|
||||
if (strpos($id, '.') !== false) {
|
||||
$info = pathinfo($id);
|
||||
|
||||
if ($info['dirname'] !== '.') {
|
||||
$id = $info['dirname'] . '/' . $info['filename'];
|
||||
} else {
|
||||
$id = $info['filename'];
|
||||
}
|
||||
}
|
||||
|
||||
// try the obvious way
|
||||
if ($page = $this->get($id)) {
|
||||
return $page;
|
||||
}
|
||||
|
||||
$start = is_a($this->parent, 'Kirby\Cms\Page') === true ? $this->parent->id() : '';
|
||||
$page = $this->findByIdRecursive($id, $start, App::instance()->multilang());
|
||||
|
||||
return $page;
|
||||
return $this->findByKey($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a child or child of a child recursively.
|
||||
* @deprecated 3.7.0 Use `$pages->find()` instead
|
||||
* @todo 3.8.0 Integrate code into `findByKey()` and remove this method
|
||||
*
|
||||
* @param string $id
|
||||
* @param string|null $startAt
|
||||
* @param bool $multiLang
|
||||
* @return mixed
|
||||
*/
|
||||
public function findByIdRecursive(string $id, string $startAt = null, bool $multiLang = false)
|
||||
public function findByIdRecursive(string $id, string $startAt = null, bool $multiLang = false, bool $silenceWarning = false)
|
||||
{
|
||||
// @codeCoverageIgnoreStart
|
||||
if ($silenceWarning !== true) {
|
||||
Helpers::deprecated('Cms\Pages::findByIdRecursive() has been deprecated and will be removed in Kirby 3.8.0. Use $pages->find() instead.');
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
$path = explode('/', $id);
|
||||
$item = null;
|
||||
$query = $startAt;
|
||||
@@ -272,25 +261,70 @@ class Pages extends Collection
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses the specialized find by id method
|
||||
* Finds a page by its ID or URI
|
||||
* @internal Use `$pages->find()` instead
|
||||
*
|
||||
* @param string|null $key
|
||||
* @return mixed
|
||||
* @return \Kirby\Cms\Page|null
|
||||
*/
|
||||
public function findByKey(string $key = null)
|
||||
public function findByKey(?string $key = null)
|
||||
{
|
||||
return $this->findById($key);
|
||||
if ($key === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// remove trailing or leading slashes
|
||||
$key = trim($key, '/');
|
||||
|
||||
// strip extensions from the id
|
||||
if (strpos($key, '.') !== false) {
|
||||
$info = pathinfo($key);
|
||||
|
||||
if ($info['dirname'] !== '.') {
|
||||
$key = $info['dirname'] . '/' . $info['filename'];
|
||||
} else {
|
||||
$key = $info['filename'];
|
||||
}
|
||||
}
|
||||
|
||||
// try the obvious way
|
||||
if ($page = $this->get($key)) {
|
||||
return $page;
|
||||
}
|
||||
|
||||
// try to find the page by its (translated) URI by stepping through the page tree
|
||||
$start = is_a($this->parent, 'Kirby\Cms\Page') === true ? $this->parent->id() : '';
|
||||
if ($page = $this->findByIdRecursive($key, $start, App::instance()->multilang(), true)) {
|
||||
return $page;
|
||||
}
|
||||
|
||||
// for secondary languages, try the full translated URI
|
||||
// (for collections without parent that won't have a result above)
|
||||
if (
|
||||
App::instance()->multilang() === true &&
|
||||
App::instance()->language()->isDefault() === false &&
|
||||
$page = $this->findBy('uri', $key)
|
||||
) {
|
||||
return $page;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias for Pages::findById
|
||||
* Alias for `$pages->find()`
|
||||
* @deprecated 3.7.0 Use `$pages->find()` instead
|
||||
* @todo 3.8.0 Remove method
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @param string $id
|
||||
* @return \Kirby\Cms\Page|null
|
||||
*/
|
||||
public function findByUri(string $id)
|
||||
{
|
||||
return $this->findById($id);
|
||||
Helpers::deprecated('Cms\Pages::findByUri() has been deprecated and will be removed in Kirby 3.8.0. Use $pages->find() instead.');
|
||||
|
||||
return $this->findByKey($id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -350,7 +384,7 @@ class Pages extends Collection
|
||||
return $index;
|
||||
}
|
||||
|
||||
$index = new Pages([], $this->parent);
|
||||
$index = new Pages([]);
|
||||
|
||||
foreach ($this->data as $pageKey => $page) {
|
||||
$index->data[$pageKey] = $page;
|
||||
|
8
kirby/src/Cms/Pagination.php
Normal file → Executable file
8
kirby/src/Cms/Pagination.php
Normal file → Executable file
@@ -96,9 +96,9 @@ class Pagination extends BasePagination
|
||||
/**
|
||||
* Returns the Url for the first page
|
||||
*
|
||||
* @return string
|
||||
* @return string|null
|
||||
*/
|
||||
public function firstPageUrl(): string
|
||||
public function firstPageUrl(): ?string
|
||||
{
|
||||
return $this->pageUrl(1);
|
||||
}
|
||||
@@ -106,9 +106,9 @@ class Pagination extends BasePagination
|
||||
/**
|
||||
* Returns the Url for the last page
|
||||
*
|
||||
* @return string
|
||||
* @return string|null
|
||||
*/
|
||||
public function lastPageUrl(): string
|
||||
public function lastPageUrl(): ?string
|
||||
{
|
||||
return $this->pageUrl($this->lastPage());
|
||||
}
|
||||
|
2
kirby/src/Cms/Permissions.php
Normal file → Executable file
2
kirby/src/Cms/Permissions.php
Normal file → Executable file
@@ -160,7 +160,7 @@ class Permissions
|
||||
protected function setAction(string $category, string $action, $setting)
|
||||
{
|
||||
// deprecated fallback for the settings/system view
|
||||
// TODO: remove in 3.7
|
||||
// TODO: remove in 3.8.0
|
||||
if ($category === 'access' && $action === 'settings') {
|
||||
$action = 'system';
|
||||
}
|
||||
|
2
kirby/src/Cms/Picker.php
Normal file → Executable file
2
kirby/src/Cms/Picker.php
Normal file → Executable file
@@ -61,7 +61,7 @@ abstract class Picker
|
||||
// optional mapping function for the result array
|
||||
'map' => null,
|
||||
// the reference model
|
||||
'model' => site(),
|
||||
'model' => App::instance()->site(),
|
||||
// current page when paginating
|
||||
'page' => 1,
|
||||
// a query string to fetch specific items
|
||||
|
7
kirby/src/Cms/Plugin.php
Normal file → Executable file
7
kirby/src/Cms/Plugin.php
Normal file → Executable file
@@ -122,9 +122,10 @@ class Plugin extends Model
|
||||
*/
|
||||
public function link(): ?string
|
||||
{
|
||||
$homepage = $this->info['homepage'] ?? null;
|
||||
$docs = $this->info['support']['docs'] ?? null;
|
||||
$source = $this->info['support']['source'] ?? null;
|
||||
$info = $this->info();
|
||||
$homepage = $info['homepage'] ?? null;
|
||||
$docs = $info['support']['docs'] ?? null;
|
||||
$source = $info['support']['source'] ?? null;
|
||||
|
||||
$link = $homepage ?? $docs ?? $source;
|
||||
|
||||
|
0
kirby/src/Cms/PluginAssets.php
Normal file → Executable file
0
kirby/src/Cms/PluginAssets.php
Normal file → Executable file
0
kirby/src/Cms/R.php
Normal file → Executable file
0
kirby/src/Cms/R.php
Normal file → Executable file
150
kirby/src/Cms/Responder.php
Normal file → Executable file
150
kirby/src/Cms/Responder.php
Normal file → Executable file
@@ -43,7 +43,7 @@ class Responder
|
||||
* Flag that defines whether the current
|
||||
* response can be cached by Kirby's cache
|
||||
*
|
||||
* @var string
|
||||
* @var bool
|
||||
*/
|
||||
protected $cache = true;
|
||||
|
||||
@@ -61,6 +61,23 @@ class Responder
|
||||
*/
|
||||
protected $type = null;
|
||||
|
||||
/**
|
||||
* Flag that defines whether the current
|
||||
* response uses the HTTP `Authorization`
|
||||
* request header
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $usesAuth = false;
|
||||
|
||||
/**
|
||||
* List of cookie names the response
|
||||
* relies on
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $usesCookies = [];
|
||||
|
||||
/**
|
||||
* Creates and sends the response
|
||||
*
|
||||
@@ -99,6 +116,11 @@ class Responder
|
||||
public function cache(?bool $cache = null)
|
||||
{
|
||||
if ($cache === null) {
|
||||
// never ever cache private responses
|
||||
if (static::isPrivate($this->usesAuth(), $this->usesCookies()) === true) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->cache;
|
||||
}
|
||||
|
||||
@@ -106,6 +128,59 @@ class Responder
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter and getter for the flag that defines
|
||||
* whether the current response uses the HTTP
|
||||
* `Authorization` request header
|
||||
* @since 3.7.0
|
||||
*
|
||||
* @param bool|null $usesAuth
|
||||
* @return bool|$this
|
||||
*/
|
||||
public function usesAuth(?bool $usesAuth = null)
|
||||
{
|
||||
if ($usesAuth === null) {
|
||||
return $this->usesAuth;
|
||||
}
|
||||
|
||||
$this->usesAuth = $usesAuth;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for a cookie name that is
|
||||
* used by the response
|
||||
* @since 3.7.0
|
||||
*
|
||||
* @param string $name
|
||||
* @return void
|
||||
*/
|
||||
public function usesCookie(string $name): void
|
||||
{
|
||||
// only add unique names
|
||||
if (in_array($name, $this->usesCookies) === false) {
|
||||
$this->usesCookies[] = $name;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter and getter for the list of cookie
|
||||
* names the response relies on
|
||||
* @since 3.7.0
|
||||
*
|
||||
* @param array|null $usesCookies
|
||||
* @return array|$this
|
||||
*/
|
||||
public function usesCookies(?array $usesCookies = null)
|
||||
{
|
||||
if ($usesCookies === null) {
|
||||
return $this->usesCookies;
|
||||
}
|
||||
|
||||
$this->usesCookies = $usesCookies;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter and getter for the cache expiry
|
||||
* timestamp for Kirby's cache
|
||||
@@ -179,10 +254,13 @@ class Responder
|
||||
public function fromArray(array $response): void
|
||||
{
|
||||
$this->body($response['body'] ?? null);
|
||||
$this->expires($response['expires'] ?? null);
|
||||
$this->cache($response['cache'] ?? null);
|
||||
$this->code($response['code'] ?? null);
|
||||
$this->expires($response['expires'] ?? null);
|
||||
$this->headers($response['headers'] ?? null);
|
||||
$this->type($response['type'] ?? null);
|
||||
$this->usesAuth($response['usesAuth'] ?? null);
|
||||
$this->usesCookies($response['usesCookies'] ?? null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -196,7 +274,7 @@ class Responder
|
||||
public function header(string $key, $value = null, bool $lazy = false)
|
||||
{
|
||||
if ($value === null) {
|
||||
return $this->headers[$key] ?? null;
|
||||
return $this->headers()[$key] ?? null;
|
||||
}
|
||||
|
||||
if ($value === false) {
|
||||
@@ -221,7 +299,31 @@ class Responder
|
||||
public function headers(array $headers = null)
|
||||
{
|
||||
if ($headers === null) {
|
||||
return $this->headers;
|
||||
$injectedHeaders = [];
|
||||
|
||||
if (static::isPrivate($this->usesAuth(), $this->usesCookies()) === true) {
|
||||
// never ever cache private responses
|
||||
$injectedHeaders['Cache-Control'] = 'no-store, private';
|
||||
} else {
|
||||
// the response is public, but it may
|
||||
// vary based on request headers
|
||||
$vary = [];
|
||||
|
||||
if ($this->usesAuth() === true) {
|
||||
$vary[] = 'Authorization';
|
||||
}
|
||||
|
||||
if ($this->usesCookies() !== []) {
|
||||
$vary[] = 'Cookie';
|
||||
}
|
||||
|
||||
if ($vary !== []) {
|
||||
$injectedHeaders['Vary'] = implode(', ', $vary);
|
||||
}
|
||||
}
|
||||
|
||||
// lazily inject (never override custom headers)
|
||||
return array_merge($injectedHeaders, $this->headers);
|
||||
}
|
||||
|
||||
$this->headers = $headers;
|
||||
@@ -283,11 +385,14 @@ class Responder
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
// the `cache`, `expires`, `usesAuth` and `usesCookies`
|
||||
// values are explicitly *not* serialized as they are
|
||||
// volatile and not to be exported
|
||||
return [
|
||||
'body' => $this->body,
|
||||
'code' => $this->code,
|
||||
'headers' => $this->headers,
|
||||
'type' => $this->type,
|
||||
'body' => $this->body(),
|
||||
'code' => $this->code(),
|
||||
'headers' => $this->headers(),
|
||||
'type' => $this->type(),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -310,4 +415,33 @@ class Responder
|
||||
$this->type = $type;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the response needs to be exempted from
|
||||
* all caches due to using dynamic data based on auth
|
||||
* and/or cookies; the request data only matters if it
|
||||
* is actually used/relied on by the response
|
||||
* @since 3.7.0
|
||||
* @internal
|
||||
*
|
||||
* @param bool $usesAuth
|
||||
* @param array $usesCookies
|
||||
* @return bool
|
||||
*/
|
||||
public static function isPrivate(bool $usesAuth, array $usesCookies): bool
|
||||
{
|
||||
$kirby = App::instance();
|
||||
|
||||
if ($usesAuth === true && $kirby->request()->hasAuth() === true) {
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach ($usesCookies as $cookie) {
|
||||
if (isset($_COOKIE[$cookie]) === true) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
0
kirby/src/Cms/Response.php
Normal file → Executable file
0
kirby/src/Cms/Response.php
Normal file → Executable file
0
kirby/src/Cms/Role.php
Normal file → Executable file
0
kirby/src/Cms/Role.php
Normal file → Executable file
0
kirby/src/Cms/Roles.php
Normal file → Executable file
0
kirby/src/Cms/Roles.php
Normal file → Executable file
0
kirby/src/Cms/S.php
Normal file → Executable file
0
kirby/src/Cms/S.php
Normal file → Executable file
0
kirby/src/Cms/Search.php
Normal file → Executable file
0
kirby/src/Cms/Search.php
Normal file → Executable file
0
kirby/src/Cms/Section.php
Normal file → Executable file
0
kirby/src/Cms/Section.php
Normal file → Executable file
4
kirby/src/Cms/Site.php
Normal file → Executable file
4
kirby/src/Cms/Site.php
Normal file → Executable file
@@ -668,7 +668,6 @@ class Site extends ModelWithContent
|
||||
/**
|
||||
* Returns the full path without leading slash
|
||||
*
|
||||
* @todo Add `deprecated()` helper warning in 3.7.0
|
||||
* @todo Remove in 3.8.0
|
||||
*
|
||||
* @internal
|
||||
@@ -677,6 +676,7 @@ class Site extends ModelWithContent
|
||||
*/
|
||||
public function panelPath(): string
|
||||
{
|
||||
Helpers::deprecated('Cms\Site::panelPath() has been deprecated and will be removed in Kirby 3.8.0. Use $site->panel()->path() instead.');
|
||||
return $this->panel()->path();
|
||||
}
|
||||
|
||||
@@ -684,7 +684,6 @@ class Site extends ModelWithContent
|
||||
* Returns the url to the editing view
|
||||
* in the panel
|
||||
*
|
||||
* @todo Add `deprecated()` helper warning in 3.7.0
|
||||
* @todo Remove in 3.8.0
|
||||
*
|
||||
* @internal
|
||||
@@ -694,6 +693,7 @@ class Site extends ModelWithContent
|
||||
*/
|
||||
public function panelUrl(bool $relative = false): string
|
||||
{
|
||||
Helpers::deprecated('Cms\Site::panelUrl() has been deprecated and will be removed in Kirby 3.8.0. Use $site->panel()->url() instead.');
|
||||
return $this->panel()->url($relative);
|
||||
}
|
||||
}
|
||||
|
0
kirby/src/Cms/SiteActions.php
Normal file → Executable file
0
kirby/src/Cms/SiteActions.php
Normal file → Executable file
0
kirby/src/Cms/SiteBlueprint.php
Normal file → Executable file
0
kirby/src/Cms/SiteBlueprint.php
Normal file → Executable file
0
kirby/src/Cms/SitePermissions.php
Normal file → Executable file
0
kirby/src/Cms/SitePermissions.php
Normal file → Executable file
0
kirby/src/Cms/SiteRules.php
Normal file → Executable file
0
kirby/src/Cms/SiteRules.php
Normal file → Executable file
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user