Upgrade to 3.7.0

This commit is contained in:
Bastian Allgeier
2022-06-27 10:02:22 +02:00
parent 0751a6510d
commit 1c22148d7b
674 changed files with 5052 additions and 3082 deletions

31
kirby/src/Api/Api.php Normal file → Executable file
View 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
View File

0
kirby/src/Api/Model.php Normal file → Executable file
View File

0
kirby/src/Cache/ApcuCache.php Normal file → Executable file
View File

0
kirby/src/Cache/Cache.php Normal file → Executable file
View File

0
kirby/src/Cache/FileCache.php Normal file → Executable file
View File

0
kirby/src/Cache/MemCached.php Normal file → Executable file
View File

0
kirby/src/Cache/MemoryCache.php Normal file → Executable file
View File

0
kirby/src/Cache/NullCache.php Normal file → Executable file
View File

0
kirby/src/Cache/Value.php Normal file → Executable file
View File

2
kirby/src/Cms/Api.php Normal file → Executable file
View 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
View 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
View File

5
kirby/src/Cms/AppErrors.php Normal file → Executable file
View 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
View 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
View 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
View File

5
kirby/src/Cms/Auth.php Normal file → Executable file
View 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
View File

0
kirby/src/Cms/Auth/EmailChallenge.php Normal file → Executable file
View File

0
kirby/src/Cms/Auth/Status.php Normal file → Executable file
View File

43
kirby/src/Cms/Block.php Normal file → Executable file
View 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>';
}

View File

@@ -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
View 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
View File

0
kirby/src/Cms/Collection.php Normal file → Executable file
View File

0
kirby/src/Cms/Collections.php Normal file → Executable file
View File

21
kirby/src/Cms/Content.php Normal file → Executable file
View 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
View File

0
kirby/src/Cms/ContentLocks.php Normal file → Executable file
View File

10
kirby/src/Cms/ContentTranslation.php Normal file → Executable file
View 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
View 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
View File

View 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
View File

0
kirby/src/Cms/Field.php Normal file → Executable file
View File

0
kirby/src/Cms/Fieldset.php Normal file → Executable file
View File

2
kirby/src/Cms/Fieldsets.php Normal file → Executable file
View 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
View 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
View File

0
kirby/src/Cms/FileBlueprint.php Normal file → Executable file
View File

0
kirby/src/Cms/FileModifications.php Normal file → Executable file
View File

0
kirby/src/Cms/FilePermissions.php Normal file → Executable file
View File

0
kirby/src/Cms/FilePicker.php Normal file → Executable file
View File

0
kirby/src/Cms/FileRules.php Normal file → Executable file
View File

0
kirby/src/Cms/FileVersion.php Normal file → Executable file
View File

14
kirby/src/Cms/Files.php Normal file → Executable file
View 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
View File

0
kirby/src/Cms/HasChildren.php Normal file → Executable file
View File

0
kirby/src/Cms/HasFiles.php Normal file → Executable file
View File

0
kirby/src/Cms/HasMethods.php Normal file → Executable file
View File

0
kirby/src/Cms/HasSiblings.php Normal file → Executable file
View File

87
kirby/src/Cms/Helpers.php Executable file
View 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
View 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
View File

6
kirby/src/Cms/Item.php Normal file → Executable file
View 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
View 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
View 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
View File

0
kirby/src/Cms/LanguageRoutes.php Normal file → Executable file
View File

0
kirby/src/Cms/LanguageRules.php Normal file → Executable file
View File

0
kirby/src/Cms/Languages.php Normal file → Executable file
View File

0
kirby/src/Cms/Layout.php Normal file → Executable file
View File

0
kirby/src/Cms/LayoutColumn.php Normal file → Executable file
View File

0
kirby/src/Cms/LayoutColumns.php Normal file → Executable file
View File

3
kirby/src/Cms/Layouts.php Normal file → Executable file
View 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
View File

0
kirby/src/Cms/Media.php Normal file → Executable file
View File

0
kirby/src/Cms/Model.php Normal file → Executable file
View File

0
kirby/src/Cms/ModelPermissions.php Normal file → Executable file
View File

17
kirby/src/Cms/ModelWithContent.php Normal file → Executable file
View 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
View File

0
kirby/src/Cms/NestCollection.php Normal file → Executable file
View File

0
kirby/src/Cms/NestObject.php Normal file → Executable file
View File

45
kirby/src/Cms/Page.php Normal file → Executable file
View 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
View 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
View File

0
kirby/src/Cms/PagePermissions.php Normal file → Executable file
View File

0
kirby/src/Cms/PagePicker.php Normal file → Executable file
View File

0
kirby/src/Cms/PageRules.php Normal file → Executable file
View File

0
kirby/src/Cms/PageSiblings.php Normal file → Executable file
View File

108
kirby/src/Cms/Pages.php Normal file → Executable file
View 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
View 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
View 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
View 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
View 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
View File

0
kirby/src/Cms/R.php Normal file → Executable file
View File

150
kirby/src/Cms/Responder.php Normal file → Executable file
View 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
View File

0
kirby/src/Cms/Role.php Normal file → Executable file
View File

0
kirby/src/Cms/Roles.php Normal file → Executable file
View File

0
kirby/src/Cms/S.php Normal file → Executable file
View File

0
kirby/src/Cms/Search.php Normal file → Executable file
View File

0
kirby/src/Cms/Section.php Normal file → Executable file
View File

4
kirby/src/Cms/Site.php Normal file → Executable file
View 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
View File

0
kirby/src/Cms/SiteBlueprint.php Normal file → Executable file
View File

0
kirby/src/Cms/SitePermissions.php Normal file → Executable file
View File

0
kirby/src/Cms/SiteRules.php Normal file → Executable file
View File

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