Upgrade to 3.1.4
This commit is contained in:
@@ -650,6 +650,11 @@ class App
|
||||
$text = $this->apply('kirbytext:before', $text);
|
||||
$text = $this->kirbytags($text, $data);
|
||||
$text = $this->markdown($text, $inline);
|
||||
|
||||
if ($this->option('smartypants', false) !== false) {
|
||||
$text = $this->smartypants($text);
|
||||
}
|
||||
|
||||
$text = $this->apply('kirbytext:after', $text);
|
||||
|
||||
return $text;
|
||||
@@ -700,7 +705,11 @@ class App
|
||||
*/
|
||||
public function languages(): Languages
|
||||
{
|
||||
return $this->languages = $this->languages ?? Languages::load();
|
||||
if ($this->languages !== null) {
|
||||
return clone $this->languages;
|
||||
}
|
||||
|
||||
return $this->languages = Languages::load();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1122,7 +1131,13 @@ class App
|
||||
*/
|
||||
public function smartypants(string $text = null): string
|
||||
{
|
||||
return $this->component('smartypants')($this, $text, $this->options['smartypants'] ?? []);
|
||||
$options = $this->option('smartypants', []);
|
||||
|
||||
if ($options === true) {
|
||||
$options = [];
|
||||
}
|
||||
|
||||
return $this->component('smartypants')($this, $text, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -3,6 +3,7 @@
|
||||
namespace Kirby\Cms;
|
||||
|
||||
use Closure;
|
||||
use Exception;
|
||||
use Kirby\Exception\InvalidArgumentException;
|
||||
use Kirby\Toolkit\Collection as BaseCollection;
|
||||
use Kirby\Toolkit\Str;
|
||||
@@ -125,8 +126,12 @@ class Collection extends BaseCollection
|
||||
* @param bool $i (ignore upper/lowercase for group names)
|
||||
* @return Collection A collection with an item for each group and a Collection for each group
|
||||
*/
|
||||
public function groupBy(string $field, bool $i = true)
|
||||
public function groupBy($field, bool $i = true)
|
||||
{
|
||||
if (is_string($field) === false) {
|
||||
throw new Exception('Cannot group by non-string values. Did you mean to call group()?');
|
||||
}
|
||||
|
||||
$groups = new Collection([], $this->parent());
|
||||
|
||||
foreach ($this->data as $key => $item) {
|
||||
|
@@ -67,17 +67,23 @@ class Collections
|
||||
}
|
||||
|
||||
// if not yet cached
|
||||
if (isset($this->cache[$name]) === false) {
|
||||
if (
|
||||
isset($this->cache[$name]) === false ||
|
||||
$this->cache[$name]['data'] !== $data
|
||||
) {
|
||||
$controller = new Controller($this->collections[$name]);
|
||||
$this->cache[$name] = $controller->call(null, $data);
|
||||
$this->cache[$name] = [
|
||||
'result' => $controller->call(null, $data),
|
||||
'data' => $data
|
||||
];
|
||||
}
|
||||
|
||||
// return cloned object
|
||||
if (is_object($this->cache[$name]) === true) {
|
||||
return clone $this->cache[$name];
|
||||
if (is_object($this->cache[$name]['result']) === true) {
|
||||
return clone $this->cache[$name]['result'];
|
||||
}
|
||||
|
||||
return $this->cache[$name];
|
||||
return $this->cache[$name]['result'];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -132,6 +132,11 @@ class Language extends Model
|
||||
$kirby = App::instance();
|
||||
$site = $kirby->site();
|
||||
|
||||
// convert site
|
||||
foreach ($site->files() as $file) {
|
||||
F::move($file->contentFile($from, true), $file->contentFile($to, true));
|
||||
}
|
||||
|
||||
F::move($site->contentFile($from, true), $site->contentFile($to, true));
|
||||
|
||||
// convert all pages
|
||||
@@ -489,7 +494,7 @@ class Language extends Model
|
||||
*/
|
||||
public function url(): string
|
||||
{
|
||||
return Url::to($this->pattern());
|
||||
return Url::makeAbsolute($this->pattern(), $this->kirby()->url());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -25,7 +25,7 @@ class Nest
|
||||
foreach ($data as $key => $value) {
|
||||
if (is_array($value) === true) {
|
||||
$result[$key] = static::create($value, $parent);
|
||||
} elseif (is_string($value) === true) {
|
||||
} elseif (is_scalar($value) === true) {
|
||||
$result[$key] = new Field($parent, $key, $value);
|
||||
}
|
||||
}
|
||||
|
@@ -247,9 +247,13 @@ class Page extends ModelWithContent
|
||||
}
|
||||
|
||||
$blueprints = [];
|
||||
$templates = $this->blueprint()->options()['changeTemplate'] ?? false;
|
||||
$templates = $this->blueprint()->options()['changeTemplate'] ?? [];
|
||||
$currentTemplate = $this->intendedTemplate()->name();
|
||||
|
||||
if (is_array($templates) === false) {
|
||||
$templates = [];
|
||||
}
|
||||
|
||||
// add the current template to the array
|
||||
$templates[] = $currentTemplate;
|
||||
|
||||
|
@@ -133,7 +133,7 @@ class PanelPlugins
|
||||
*/
|
||||
public function id(): string
|
||||
{
|
||||
return crc32(implode(array_values($this->files())));
|
||||
return hash('crc32', implode(array_values($this->files())));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -101,6 +101,21 @@ class StructureObject extends Model
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares the current object with the given structure object
|
||||
*
|
||||
* @param mixed $structure
|
||||
* @return bool
|
||||
*/
|
||||
public function is($structure): bool
|
||||
{
|
||||
if (is_a($structure, StructureObject::class) === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this === $structure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the parent Model object
|
||||
*
|
||||
|
@@ -372,6 +372,8 @@ class User extends ModelWithContent
|
||||
* @param string $password
|
||||
* @param Session|array $session Session options or session object to set the user in
|
||||
* @return bool
|
||||
*
|
||||
* @throws PermissionException If the password is not valid
|
||||
*/
|
||||
public function login(string $password, $session = null): bool
|
||||
{
|
||||
@@ -783,6 +785,10 @@ class User extends ModelWithContent
|
||||
*
|
||||
* @param string $password
|
||||
* @return boolean
|
||||
*
|
||||
* @throws NotFoundException If the user has no password
|
||||
* @throws InvalidArgumentException If the entered password is not valid
|
||||
* @throws InvalidArgumentException If the entered password does not match the user password
|
||||
*/
|
||||
public function validatePassword(string $password = null): bool
|
||||
{
|
||||
|
@@ -132,7 +132,7 @@ class Collection extends Iterator implements Countable
|
||||
* @return Collection A new collection with an element for each chunk and
|
||||
* a sub collection in each chunk
|
||||
*/
|
||||
public function chunk(int $size): self
|
||||
public function chunk(int $size)
|
||||
{
|
||||
// create a multidimensional array that is chunked with the given
|
||||
// chunk size keep keys of the elements
|
||||
@@ -219,7 +219,7 @@ class Collection extends Iterator implements Countable
|
||||
* @param Closure $filter
|
||||
* @return self
|
||||
*/
|
||||
public function filter($filter): self
|
||||
public function filter($filter)
|
||||
{
|
||||
if (is_callable($filter) === true) {
|
||||
$collection = clone $this;
|
||||
@@ -246,7 +246,7 @@ class Collection extends Iterator implements Countable
|
||||
* @param string $field
|
||||
* @return self
|
||||
*/
|
||||
public function filterBy(string $field, ...$args): self
|
||||
public function filterBy(string $field, ...$args)
|
||||
{
|
||||
$operator = '==';
|
||||
$test = $args[0] ?? null;
|
||||
@@ -405,7 +405,7 @@ class Collection extends Iterator implements Countable
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function flip(): self
|
||||
public function flip()
|
||||
{
|
||||
$collection = clone $this;
|
||||
$collection->data = array_reverse($this->data, true);
|
||||
@@ -433,14 +433,19 @@ class Collection extends Iterator implements Countable
|
||||
* @param array|object $item
|
||||
* @param string $attribute
|
||||
* @param boolean $split
|
||||
* @param mixed $related
|
||||
* @return mixed
|
||||
*/
|
||||
public function getAttribute($item, string $attribute, $split = false)
|
||||
public function getAttribute($item, string $attribute, $split = false, $related = null)
|
||||
{
|
||||
$value = $this->{'getAttributeFrom' . gettype($item)}($item, $attribute);
|
||||
|
||||
if ($split !== false) {
|
||||
$value = Str::split($value, $split === true ? ',' : $split);
|
||||
return Str::split($value, $split === true ? ',' : $split);
|
||||
}
|
||||
|
||||
if ($related !== null) {
|
||||
return Str::toType((string)$value, $related);
|
||||
}
|
||||
|
||||
return $value;
|
||||
@@ -516,7 +521,7 @@ class Collection extends Iterator implements Countable
|
||||
* @param bool $i
|
||||
* @return Collection A new collection with an element for each group and a subcollection in each group
|
||||
*/
|
||||
public function groupBy(string $field, bool $i = true)
|
||||
public function groupBy($field, bool $i = true)
|
||||
{
|
||||
if (is_string($field) === false) {
|
||||
throw new Exception('Cannot group by non-string values. Did you mean to call group()?');
|
||||
@@ -587,7 +592,7 @@ class Collection extends Iterator implements Countable
|
||||
* @param int $limit The number of elements to return
|
||||
* @return Collection
|
||||
*/
|
||||
public function limit(int $limit): self
|
||||
public function limit(int $limit)
|
||||
{
|
||||
return $this->slice(0, $limit);
|
||||
}
|
||||
@@ -598,7 +603,7 @@ class Collection extends Iterator implements Countable
|
||||
* @param callable $callback
|
||||
* @return Collection
|
||||
*/
|
||||
public function map(callable $callback): self
|
||||
public function map(callable $callback)
|
||||
{
|
||||
$this->data = array_map($callback, $this->data);
|
||||
return $this;
|
||||
@@ -625,7 +630,7 @@ class Collection extends Iterator implements Countable
|
||||
{
|
||||
$collection = clone $this;
|
||||
foreach ($keys as $key) {
|
||||
unset($collection->$key);
|
||||
unset($collection->data[$key]);
|
||||
}
|
||||
return $collection;
|
||||
}
|
||||
@@ -636,7 +641,7 @@ class Collection extends Iterator implements Countable
|
||||
* @param int $offset The index to start from
|
||||
* @return Collection
|
||||
*/
|
||||
public function offset(int $offset): self
|
||||
public function offset(int $offset)
|
||||
{
|
||||
return $this->slice($offset);
|
||||
}
|
||||
@@ -798,7 +803,7 @@ class Collection extends Iterator implements Countable
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function shuffle(): self
|
||||
public function shuffle()
|
||||
{
|
||||
$data = $this->data;
|
||||
$keys = $this->keys();
|
||||
@@ -821,7 +826,7 @@ class Collection extends Iterator implements Countable
|
||||
* @param int $limit The optional number of elements to return
|
||||
* @return Collection
|
||||
*/
|
||||
public function slice(int $offset = 0, int $limit = null): self
|
||||
public function slice(int $offset = 0, int $limit = null)
|
||||
{
|
||||
if ($offset === 0 && $limit === null) {
|
||||
return $this;
|
||||
@@ -840,7 +845,7 @@ class Collection extends Iterator implements Countable
|
||||
* @param $method int The sort flag, SORT_REGULAR, SORT_NUMERIC etc.
|
||||
* @return Collection
|
||||
*/
|
||||
public function sortBy(): self
|
||||
public function sortBy()
|
||||
{
|
||||
// there is no need to sort empty collections
|
||||
if (empty($this->data) === true) {
|
||||
@@ -983,13 +988,13 @@ class Collection extends Iterator implements Countable
|
||||
*/
|
||||
Collection::$filters['=='] = function ($collection, $field, $test, $split = false) {
|
||||
foreach ($collection->data as $key => $item) {
|
||||
$value = $collection->getAttribute($item, $field, $split);
|
||||
$value = $collection->getAttribute($item, $field, $split, $test);
|
||||
|
||||
if ($split !== false) {
|
||||
if (in_array($test, $value) === false) {
|
||||
unset($collection->data[$key]);
|
||||
}
|
||||
} elseif ($value != $test) {
|
||||
} elseif ($value !== $test) {
|
||||
unset($collection->data[$key]);
|
||||
}
|
||||
}
|
||||
@@ -1002,13 +1007,13 @@ Collection::$filters['=='] = function ($collection, $field, $test, $split = fals
|
||||
*/
|
||||
Collection::$filters['!='] = function ($collection, $field, $test, $split = false) {
|
||||
foreach ($collection->data as $key => $item) {
|
||||
$value = $collection->getAttribute($item, $field, $split);
|
||||
$value = $collection->getAttribute($item, $field, $split, $test);
|
||||
|
||||
if ($split !== false) {
|
||||
if (in_array($test, $value) === true) {
|
||||
unset($collection->data[$key]);
|
||||
}
|
||||
} elseif ($value == $test) {
|
||||
} elseif ((string)$value == $test) {
|
||||
unset($collection->data[$key]);
|
||||
}
|
||||
}
|
||||
|
@@ -54,8 +54,8 @@ class Html
|
||||
/**
|
||||
* Generates an a tag
|
||||
*
|
||||
* @param string $href The url for the a tag
|
||||
* @param mixed $text The optional text. If null, the url will be used as text
|
||||
* @param string $href The url for the `a` tag
|
||||
* @param mixed $text The optional text. If `null`, the url will be used as text
|
||||
* @param array $attr Additional attributes for the tag
|
||||
* @return string the generated html
|
||||
*/
|
||||
@@ -64,7 +64,7 @@ class Html
|
||||
$attr = array_merge(['href' => $href], $attr);
|
||||
|
||||
if (empty($text) === true) {
|
||||
$text = $href;
|
||||
$text = $attr['href'];
|
||||
}
|
||||
|
||||
if (is_string($text) === true && Str::isUrl($text) === true) {
|
||||
@@ -160,7 +160,7 @@ class Html
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an "a mailto" tag
|
||||
* Generates an `a` tag with `mailto:`
|
||||
*
|
||||
* @param string $email The url for the a tag
|
||||
* @param mixed $text The optional text. If null, the url will be used as text
|
||||
@@ -328,7 +328,7 @@ class Html
|
||||
}
|
||||
|
||||
/**
|
||||
* Add noopeener noreferrer to rels when target is _blank
|
||||
* Add noopeener noreferrer to rels when target is `_blank`
|
||||
*
|
||||
* @param string $rel
|
||||
* @param string $target
|
||||
@@ -352,8 +352,8 @@ class Html
|
||||
/**
|
||||
* Generates an Html tag with optional content and attributes
|
||||
*
|
||||
* @param string $name The name of the tag, i.e. "a"
|
||||
* @param mixed $content The content if availble. Pass null to generate a self-closing tag, Pass an empty string to generate empty content
|
||||
* @param string $name The name of the tag, i.e. `a`
|
||||
* @param mixed $content The content if availble. Pass `null` to generate a self-closing tag, Pass an empty string to generate empty content
|
||||
* @param array $attr An associative array with additional attributes for the tag
|
||||
* @return string The generated Html
|
||||
*/
|
||||
@@ -383,10 +383,10 @@ class Html
|
||||
|
||||
|
||||
/**
|
||||
* Generates an a tag for a phone number
|
||||
* Generates an `a` tag for a phone number
|
||||
*
|
||||
* @param string $tel The phone number
|
||||
* @param mixed $text The optional text. If null, the number will be used as text
|
||||
* @param mixed $text The optional text. If `null`, the number will be used as text
|
||||
* @param array $attr Additional attributes for the tag
|
||||
* @return string the generated html
|
||||
*/
|
||||
@@ -404,7 +404,7 @@ class Html
|
||||
/**
|
||||
* Creates a video embed via iframe for Youtube or Vimeo
|
||||
* videos. The embed Urls are automatically detected from
|
||||
* the given Url.
|
||||
* the given URL.
|
||||
*
|
||||
* @param string $url
|
||||
* @param array $options
|
||||
|
@@ -124,8 +124,9 @@ class Mime
|
||||
'svg' => [Mime::class, 'fromSvg'],
|
||||
],
|
||||
'text/plain' => [
|
||||
'css' => 'text/css',
|
||||
'svg' => [Mime::class, 'fromSvg'],
|
||||
'css' => 'text/css',
|
||||
'json' => 'application/json',
|
||||
'svg' => [Mime::class, 'fromSvg'],
|
||||
],
|
||||
'text/x-asm' => [
|
||||
'css' => 'text/css'
|
||||
|
@@ -870,6 +870,36 @@ class Str
|
||||
}, $string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the string to the given type
|
||||
*
|
||||
* @param string $string
|
||||
* @param mixed $type
|
||||
* @return mixed
|
||||
*/
|
||||
public static function toType($string = null, $type)
|
||||
{
|
||||
if (is_string($type) === false) {
|
||||
$type = gettype($type);
|
||||
}
|
||||
|
||||
switch ($type) {
|
||||
case 'array':
|
||||
return (array)$string;
|
||||
case 'bool':
|
||||
case 'boolean':
|
||||
return filter_var($string, FILTER_VALIDATE_BOOLEAN);
|
||||
case 'double':
|
||||
case 'float':
|
||||
return floatval($string);
|
||||
case 'int':
|
||||
case 'integer':
|
||||
return intval($string);
|
||||
}
|
||||
|
||||
return (string)$string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Safe trim alternative
|
||||
*
|
||||
|
Reference in New Issue
Block a user