Upgrade to 3.3.5

This commit is contained in:
Bastian Allgeier
2020-03-17 14:20:08 +01:00
parent 211e325864
commit 1f2f39ce58
19 changed files with 359 additions and 167 deletions

View File

@@ -12,7 +12,6 @@ use Kirby\Http\Router;
use Kirby\Http\Server;
use Kirby\Http\Visitor;
use Kirby\Session\AutoSession;
use Kirby\Text\KirbyTag;
use Kirby\Toolkit\A;
use Kirby\Toolkit\Config;
use Kirby\Toolkit\Controller;

View File

@@ -163,7 +163,7 @@ trait FileActions
$props['model'] = strtolower($props['template'] ?? 'default');
// create the basic file and a test upload object
$file = File::factory($props);
$file = static::factory($props);
$upload = new Image($props['source']);
// create a form for the file

View File

@@ -135,6 +135,13 @@ class FileRules
]);
}
if (Str::contains($extension, 'htm')) {
throw new InvalidArgumentException([
'key' => 'file.type.forbidden',
'data' => ['type' => 'HTML']
]);
}
return true;
}

View File

@@ -17,51 +17,81 @@ trait HasSiblings
/**
* Returns the position / index in the collection
*
* @param \Kirby\Cms\Collection|null $collection
*
* @return int
*/
public function indexOf(): int
public function indexOf($collection = null): int
{
return $this->siblingsCollection()->indexOf($this);
if ($collection === null) {
$collection = $this->siblingsCollection();
}
return $collection->indexOf($this);
}
/**
* Returns the next item in the collection if available
*
* @param \Kirby\Cms\Collection|null $collection
*
* @return \Kirby\Cms\Model|null
*/
public function next()
public function next($collection = null)
{
return $this->siblingsCollection()->nth($this->indexOf() + 1);
if ($collection === null) {
$collection = $this->siblingsCollection();
}
return $collection->nth($this->indexOf($collection) + 1);
}
/**
* Returns the end of the collection starting after the current item
*
* @param \Kirby\Cms\Collection|null $collection
*
* @return \Kirby\Cms\Collection
*/
public function nextAll()
public function nextAll($collection = null)
{
return $this->siblingsCollection()->slice($this->indexOf() + 1);
if ($collection === null) {
$collection = $this->siblingsCollection();
}
return $collection->slice($this->indexOf($collection) + 1);
}
/**
* Returns the previous item in the collection if available
*
* @param \Kirby\Cms\Collection|null $collection
*
* @return \Kirby\Cms\Model|null
*/
public function prev()
public function prev($collection = null)
{
return $this->siblingsCollection()->nth($this->indexOf() - 1);
if ($collection === null) {
$collection = $this->siblingsCollection();
}
return $collection->nth($this->indexOf($collection) - 1);
}
/**
* Returns the beginning of the collection before the current item
*
* @param \Kirby\Cms\Collection|null $collection
*
* @return \Kirby\Cms\Collection
*/
public function prevAll()
public function prevAll($collection = null)
{
return $this->siblingsCollection()->slice(0, $this->indexOf());
if ($collection === null) {
$collection = $this->siblingsCollection();
}
return $collection->slice(0, $this->indexOf($collection));
}
/**
@@ -84,51 +114,69 @@ trait HasSiblings
/**
* Checks if there's a next item in the collection
*
* @param \Kirby\Cms\Collection|null $collection
*
* @return bool
*/
public function hasNext(): bool
public function hasNext($collection = null): bool
{
return $this->next() !== null;
return $this->next($collection) !== null;
}
/**
* Checks if there's a previous item in the collection
*
* @param \Kirby\Cms\Collection|null $collection
*
* @return bool
*/
public function hasPrev(): bool
public function hasPrev($collection = null): bool
{
return $this->prev() !== null;
return $this->prev($collection) !== null;
}
/**
* Checks if the item is the first in the collection
*
* @param \Kirby\Cms\Collection|null $collection
*
* @return bool
*/
public function isFirst(): bool
public function isFirst($collection = null): bool
{
return $this->siblingsCollection()->first()->is($this);
if ($collection === null) {
$collection = $this->siblingsCollection();
}
return $collection->first()->is($this);
}
/**
* Checks if the item is the last in the collection
*
* @param \Kirby\Cms\Collection|null $collection
*
* @return bool
*/
public function isLast(): bool
public function isLast($collection = null): bool
{
return $this->siblingsCollection()->last()->is($this);
if ($collection === null) {
$collection = $this->siblingsCollection();
}
return $collection->last()->is($this);
}
/**
* Checks if the item is at a certain position
*
* @param \Kirby\Cms\Collection|null $collection
* @param int $n
*
* @return bool
*/
public function isNth(int $n): bool
public function isNth(int $n, $collection = null): bool
{
return $this->indexOf() === $n;
return $this->indexOf($collection) === $n;
}
}

View File

@@ -342,6 +342,45 @@ class Language extends Model
}
}
/**
* Returns the locale array but with the locale
* constants replaced with their string representations
*
* @return array
*/
protected function localeExport(): array
{
// list of all possible constant names
$constantNames = [
'LC_ALL', 'LC_COLLATE', 'LC_CTYPE', 'LC_MONETARY',
'LC_NUMERIC', 'LC_TIME', 'LC_MESSAGES'
];
// build an associative array with the locales
// that are actually supported on this system
$constants = [];
foreach ($constantNames as $name) {
if (defined($name) === true) {
$constants[constant($name)] = $name;
}
}
// replace the keys in the locale data array with the locale names
$return = [];
foreach ($this->locale() as $key => $value) {
if (isset($constants[$key]) === true) {
// the key is a valid constant,
// replace it with its string representation
$return[$constants[$key]] = $value;
} else {
// not found, keep it as-is
$return[$key] = $value;
}
}
return $return;
}
/**
* Returns the human-readable name
* of the language
@@ -448,7 +487,7 @@ class Language extends Model
'code' => $this->code(),
'default' => $this->isDefault(),
'direction' => $this->direction(),
'locale' => $this->locale(),
'locale' => $this->localeExport(),
'name' => $this->name(),
'translations' => $this->translations(),
'url' => $this->url,
@@ -500,7 +539,17 @@ class Language extends Model
protected function setLocale($locale = null)
{
if (is_array($locale)) {
$this->locale = $locale;
// replace string constant keys with the constant values
$convertedLocale = [];
foreach ($locale as $key => $value) {
if (is_string($key) === true && Str::startsWith($key, 'LC_') === true) {
$key = constant($key);
}
$convertedLocale[$key] = $value;
}
$this->locale = $convertedLocale;
} elseif (is_string($locale)) {
$this->locale = [LC_ALL => $locale];
} elseif ($locale === null) {

View File

@@ -117,7 +117,10 @@ class LanguageRouter
$router = new Router($this->routes());
try {
return $router->call($path, $kirby->request()->method(), function ($route) use ($language) {
return $router->call($path, $kirby->request()->method(), function ($route) use ($kirby, $language) {
$kirby->setCurrentTranslation($language);
$kirby->setCurrentLanguage($language);
if ($page = $route->page()) {
return $route->action()->call($route, $language, $page, ...$route->arguments());
} else {

View File

@@ -78,6 +78,17 @@ class LanguageRoutes
]);
if ($url->toString() !== $page->url()) {
// redirect to translated page directly
// if translation is exists and languages detect is enabled
if (
$kirby->option('languages.detect') === true &&
$page->translation($kirby->detectedLanguage()->code())->exists() === true
) {
return $kirby
->response()
->redirect($page->url($kirby->detectedLanguage()->code()));
}
return $kirby
->response()
->redirect($page->url());

View File

@@ -693,24 +693,6 @@ class Page extends ModelWithContent
return $this->id() === $this->site()->errorPageId();
}
/**
* Check if the page can be read by the current user
*
* @return bool
*/
public function isReadable(): bool
{
static $readable = [];
$template = $this->intendedTemplate()->name();
if (isset($readable[$template]) === true) {
return $readable[$template];
}
return $readable[$template] = $this->permissions()->can('read');
}
/**
* Checks if the page is the home page
*
@@ -776,6 +758,34 @@ class Page extends ModelWithContent
return false;
}
/**
* Checks if the page is not a draft.
*
* @return bool
*/
public function isPublished(): bool
{
return $this->isDraft() === false;
}
/**
* Check if the page can be read by the current user
*
* @return bool
*/
public function isReadable(): bool
{
static $readable = [];
$template = $this->intendedTemplate()->name();
if (isset($readable[$template]) === true) {
return $readable[$template];
}
return $readable[$template] = $this->permissions()->can('read');
}
/**
* Checks if the page is sortable
*
@@ -1128,8 +1138,6 @@ class Page extends ModelWithContent
// fetch the page regularly
if ($html === null) {
$kirby->data = $this->controller($data, $contentType);
if ($contentType === 'html') {
$template = $this->template();
} else {
@@ -1142,6 +1150,8 @@ class Page extends ModelWithContent
]);
}
$kirby->data = $this->controller($data, $contentType);
// render the page
$html = $template->render($kirby->data);
@@ -1168,7 +1178,7 @@ class Page extends ModelWithContent
public function representation($type)
{
$kirby = $this->kirby();
$template = $this->intendedTemplate();
$template = $this->template();
$representation = $kirby->template($template->name(), $type);
if ($representation->exists() === true) {

View File

@@ -13,176 +13,104 @@ namespace Kirby\Cms;
*/
trait PageSiblings
{
/**
* @deprecated 3.0.0 Use `Page::hasNextUnlisted()` instead
* @return bool
*/
public function hasNextInvisible(): bool
{
deprecated('$page->hasNextInvisible() is deprecated, use $page->hasNextUnlisted() instead. $page->hasNextInvisible() will be removed in Kirby 3.5.0.');
return $this->hasNextUnlisted();
}
/**
* Checks if there's a next listed
* page in the siblings collection
*
* @param \Kirby\Cms\Collection|null $collection
*
* @return bool
*/
public function hasNextListed(): bool
public function hasNextListed($collection = null): bool
{
return $this->nextListed() !== null;
return $this->nextListed($collection) !== null;
}
/**
* Checks if there's a next unlisted
* page in the siblings collection
*
* @param \Kirby\Cms\Collection|null $collection
*
* @return bool
*/
public function hasNextUnlisted(): bool
public function hasNextUnlisted($collection = null): bool
{
return $this->nextUnlisted() !== null;
}
/**
* @deprecated 3.0.0 Use `Page::hasNextListed()` instead
* @return bool
*/
public function hasNextVisible(): bool
{
deprecated('$page->hasNextVisible() is deprecated, use $page->hasNextListed() instead. $page->hasNextVisible() will be removed in Kirby 3.5.0.');
return $this->hasNextListed();
}
/**
* @deprecated 3.0.0 Use `Page::hasPrevUnlisted()` instead
* @return bool
*/
public function hasPrevInvisible(): bool
{
deprecated('$page->hasPrevInvisible() is deprecated, use $page->hasPrevUnlisted() instead. $page->hasPrevInvisible() will be removed in Kirby 3.5.0.');
return $this->hasPrevUnlisted();
return $this->nextUnlisted($collection) !== null;
}
/**
* Checks if there's a previous listed
* page in the siblings collection
*
* @param \Kirby\Cms\Collection|null $collection
*
* @return bool
*/
public function hasPrevListed(): bool
public function hasPrevListed($collection = null): bool
{
return $this->prevListed() !== null;
return $this->prevListed($collection) !== null;
}
/**
* Checks if there's a previous unlisted
* page in the siblings collection
*
* @param \Kirby\Cms\Collection|null $collection
*
* @return bool
*/
public function hasPrevUnlisted(): bool
public function hasPrevUnlisted($collection = null): bool
{
return $this->prevUnlisted() !== null;
}
/**
* @deprecated 3.0.0 Use `Page::hasPrevListed()` instead
* @return bool
*/
public function hasPrevVisible(): bool
{
deprecated('$page->hasPrevVisible() is deprecated, use $page->hasPrevListed() instead. $page->hasPrevVisible() will be removed in Kirby 3.5.0.');
return $this->hasPrevListed();
}
/**
* @deprecated 3.0.0 Use `Page::nextUnlisted()` instead
* @return self|null
*/
public function nextInvisible()
{
deprecated('$page->nextInvisible() is deprecated, use $page->nextUnlisted() instead. $page->nextInvisible() will be removed in Kirby 3.5.0.');
return $this->nextUnlisted();
return $this->prevUnlisted($collection) !== null;
}
/**
* Returns the next listed page if it exists
*
* @param \Kirby\Cms\Collection|null $collection
*
* @return \Kirby\Cms\Page|null
*/
public function nextListed()
public function nextListed($collection = null)
{
return $this->nextAll()->listed()->first();
return $this->nextAll($collection)->listed()->first();
}
/**
* Returns the next unlisted page if it exists
*
* @param \Kirby\Cms\Collection|null $collection
*
* @return \Kirby\Cms\Page|null
*/
public function nextUnlisted()
public function nextUnlisted($collection = null)
{
return $this->nextAll()->unlisted()->first();
}
/**
* @deprecated 3.0.0 Use `Page::nextListed()` instead
* @return self|null
*/
public function nextVisible()
{
deprecated('$page->nextVisible() is deprecated, use $page->nextListed() instead. $page->nextVisible() will be removed in Kirby 3.5.0.');
return $this->nextListed();
}
/**
* @deprecated 3.0.0 Use `Page::prevUnlisted()` instead
* @return self|null
*/
public function prevInvisible()
{
deprecated('$page->prevInvisible() is deprecated, use $page->prevUnlisted() instead. $page->prevInvisible() will be removed in Kirby 3.5.0.');
return $this->prevUnlisted();
return $this->nextAll($collection)->unlisted()->first();
}
/**
* Returns the previous listed page
*
* @param \Kirby\Cms\Collection|null $collection
*
* @return \Kirby\Cms\Page|null
*/
public function prevListed()
public function prevListed($collection = null)
{
return $this->prevAll()->listed()->last();
return $this->prevAll($collection)->listed()->last();
}
/**
* Returns the previous unlisted page
*
* @param \Kirby\Cms\Collection|null $collection
*
* @return \Kirby\Cms\Page|null
*/
public function prevUnlisted()
public function prevUnlisted($collection = null)
{
return $this->prevAll()->unlisted()->first();
}
/**
* @deprecated 3.0.0 Use `Page::prevListed()` instead
* @return self|null
*/
public function prevVisible()
{
deprecated('$page->prevVisible() is deprecated, use $page->prevListed() instead. $page->prevVisible() will be removed in Kirby 3.5.0.');
return $this->prevListed();
return $this->prevAll($collection)->unlisted()->first();
}
/**
@@ -209,4 +137,93 @@ trait PageSiblings
{
return $this->siblings($self)->filterBy('intendedTemplate', $this->intendedTemplate()->name());
}
/**
* @deprecated 3.0.0 Use `Page::hasNextUnlisted()` instead
* @return bool
*/
public function hasNextInvisible(): bool
{
deprecated('$page->hasNextInvisible() is deprecated, use $page->hasNextUnlisted() instead. $page->hasNextInvisible() will be removed in Kirby 3.5.0.');
return $this->hasNextUnlisted();
}
/**
* @deprecated 3.0.0 Use `Page::hasNextListed()` instead
* @return bool
*/
public function hasNextVisible(): bool
{
deprecated('$page->hasNextVisible() is deprecated, use $page->hasNextListed() instead. $page->hasNextVisible() will be removed in Kirby 3.5.0.');
return $this->hasNextListed();
}
/**
* @deprecated 3.0.0 Use `Page::hasPrevUnlisted()` instead
* @return bool
*/
public function hasPrevInvisible(): bool
{
deprecated('$page->hasPrevInvisible() is deprecated, use $page->hasPrevUnlisted() instead. $page->hasPrevInvisible() will be removed in Kirby 3.5.0.');
return $this->hasPrevUnlisted();
}
/**
* @deprecated 3.0.0 Use `Page::hasPrevListed()` instead
* @return bool
*/
public function hasPrevVisible(): bool
{
deprecated('$page->hasPrevVisible() is deprecated, use $page->hasPrevListed() instead. $page->hasPrevVisible() will be removed in Kirby 3.5.0.');
return $this->hasPrevListed();
}
/**
* @deprecated 3.0.0 Use `Page::nextUnlisted()` instead
* @return self|null
*/
public function nextInvisible()
{
deprecated('$page->nextInvisible() is deprecated, use $page->nextUnlisted() instead. $page->nextInvisible() will be removed in Kirby 3.5.0.');
return $this->nextUnlisted();
}
/**
* @deprecated 3.0.0 Use `Page::nextListed()` instead
* @return self|null
*/
public function nextVisible()
{
deprecated('$page->nextVisible() is deprecated, use $page->nextListed() instead. $page->nextVisible() will be removed in Kirby 3.5.0.');
return $this->nextListed();
}
/**
* @deprecated 3.0.0 Use `Page::prevUnlisted()` instead
* @return self|null
*/
public function prevInvisible()
{
deprecated('$page->prevInvisible() is deprecated, use $page->prevUnlisted() instead. $page->prevInvisible() will be removed in Kirby 3.5.0.');
return $this->prevUnlisted();
}
/**
* @deprecated 3.0.0 Use `Page::prevListed()` instead
* @return self|null
*/
public function prevVisible()
{
deprecated('$page->prevVisible() is deprecated, use $page->prevListed() instead. $page->prevVisible() will be removed in Kirby 3.5.0.');
return $this->prevListed();
}
}

View File

@@ -277,6 +277,26 @@ trait UserActions
return F::read($this->root() . '/.htpasswd');
}
/**
* Updates the user data
*
* @param array $input
* @param string $language
* @param bool $validate
* @return self
*/
public function update(array $input = null, string $language = null, bool $validate = false)
{
$user = parent::update($input, $language, $validate);
// set auth user data only if the current user is this user
if ($user->isLoggedIn() === true) {
$this->kirby()->auth()->setUser($user);
}
return $user;
}
/**
* This always merges the existing credentials
* with the given input.

View File

@@ -98,6 +98,17 @@ class Dir
return $result;
}
/**
* Checks if the directory exsits on disk
*
* @param string $dir
* @return bool
*/
public static function exists(string $dir): bool
{
return is_dir($dir) === true;
}
/**
* Get all files
*

View File

@@ -15,7 +15,7 @@ namespace Kirby\Toolkit;
*/
class Query
{
const PARTS = '!([a-zA-Z_]*(\(.*?\))?)\.|' . self::SKIP . '!';
const PARTS = '!([a-zA-Z_][a-zA-Z0-9_]*(\(.*?\))?)\.|' . self::SKIP . '!';
const METHOD = '!\((.*)\)!';
const PARAMETERS = '!,|' . self::SKIP . '!';