Upgrade to 3.5.2
This commit is contained in:
@@ -68,7 +68,7 @@ class FileCache extends Cache
|
||||
*/
|
||||
protected function file(string $key): string
|
||||
{
|
||||
$file = $this->root . '/' . $key;
|
||||
$file = $this->root . '/' . basename($key);
|
||||
|
||||
if (isset($this->options['extension'])) {
|
||||
return $file . '.' . $this->options['extension'];
|
||||
|
@@ -188,6 +188,11 @@ trait AppTranslations
|
||||
// get injected translation data from plugins etc.
|
||||
$inject = $this->extensions['translations'][$locale] ?? [];
|
||||
|
||||
// inject current language translations
|
||||
if ($language = $this->language($locale)) {
|
||||
$inject = array_merge($inject, $language->translations());
|
||||
}
|
||||
|
||||
// load from disk instead
|
||||
return Translation::load($locale, $this->root('i18n:translations') . '/' . $locale . '.json', $inject);
|
||||
}
|
||||
@@ -203,6 +208,23 @@ trait AppTranslations
|
||||
return $this->translations;
|
||||
}
|
||||
|
||||
return Translations::load($this->root('i18n:translations'), $this->extensions['translations'] ?? []);
|
||||
$translations = $this->extensions['translations'] ?? [];
|
||||
|
||||
// injects languages translations
|
||||
if ($languages = $this->languages()) {
|
||||
foreach ($languages as $language) {
|
||||
// merges language translations with extension translations
|
||||
if ($language->translations()) {
|
||||
$translations[$language->code()] = array_merge(
|
||||
$translations[$language->code()],
|
||||
$language->translations()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->translations = Translations::load($this->root('i18n:translations'), $translations);
|
||||
|
||||
return $this->translations;
|
||||
}
|
||||
}
|
||||
|
@@ -375,7 +375,9 @@ class Blueprint
|
||||
protected function normalizeColumns(string $tabName, array $columns): array
|
||||
{
|
||||
foreach ($columns as $columnKey => $columnProps) {
|
||||
// unset/remove column if its property is not array
|
||||
if (is_array($columnProps) === false) {
|
||||
unset($columns[$columnKey]);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@@ -105,6 +105,12 @@ class Fieldset extends Item
|
||||
|
||||
// normalize tabs props
|
||||
foreach ($tabs as $name => $tab) {
|
||||
// unset/remove tab if its property is false
|
||||
if ($tab === false) {
|
||||
unset($tabs[$name]);
|
||||
continue;
|
||||
}
|
||||
|
||||
$tab = Blueprint::extend($tab);
|
||||
|
||||
$tab['fields'] = $this->createFields($tab['fields'] ?? []);
|
||||
|
@@ -75,6 +75,31 @@ class Layout extends Item
|
||||
return $this->columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the layout is empty
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isEmpty(): bool
|
||||
{
|
||||
return $this
|
||||
->columns()
|
||||
->filter(function ($column) {
|
||||
return $column->isNotEmpty();
|
||||
})
|
||||
->count() === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the layout is not empty
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isNotEmpty(): bool
|
||||
{
|
||||
return $this->isEmpty() === false;
|
||||
}
|
||||
|
||||
/**
|
||||
* The result is being sent to the editor
|
||||
* via the API in the panel
|
||||
|
@@ -54,6 +54,29 @@ class LayoutColumn extends Item
|
||||
return $this->blocks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the column is empty
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isEmpty(): bool
|
||||
{
|
||||
return $this
|
||||
->blocks()
|
||||
->filter('isHidden', false)
|
||||
->count() === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the column is not empty
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isNotEmpty(): bool
|
||||
{
|
||||
return $this->isEmpty() === false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of columns this column spans
|
||||
*
|
||||
|
@@ -139,7 +139,7 @@ class Page extends ModelWithContent
|
||||
/**
|
||||
* The intended page template
|
||||
*
|
||||
* @var string
|
||||
* @var \Kirby\Cms\Template
|
||||
*/
|
||||
protected $template;
|
||||
|
||||
|
@@ -533,7 +533,9 @@ trait PageActions
|
||||
$lang = $this->kirby()->defaultLanguage() ?? null;
|
||||
$field = $this->content($lang)->get('date');
|
||||
$date = $field->isEmpty() ? 'now' : $field;
|
||||
return date($format, strtotime($date));
|
||||
// TODO: in 3.6.0 throw an error if date() doesn't
|
||||
// return a number, see https://github.com/getkirby/kirby/pull/3061#discussion_r552783943
|
||||
return (int)date($format, strtotime($date));
|
||||
break;
|
||||
case 'default':
|
||||
|
||||
|
@@ -23,12 +23,19 @@ use Kirby\Exception\InvalidArgumentException;
|
||||
class Pages extends Collection
|
||||
{
|
||||
/**
|
||||
* Cache for the index
|
||||
* Cache for the index only listed and unlisted pages
|
||||
*
|
||||
* @var \Kirby\Cms\Pages|null
|
||||
*/
|
||||
protected $index = null;
|
||||
|
||||
/**
|
||||
* Cache for the index all statuses also including drafts
|
||||
*
|
||||
* @var \Kirby\Cms\Pages|null
|
||||
*/
|
||||
protected $indexWithDrafts = null;
|
||||
|
||||
/**
|
||||
* All registered pages methods
|
||||
*
|
||||
@@ -331,24 +338,31 @@ class Pages extends Collection
|
||||
*/
|
||||
public function index(bool $drafts = false)
|
||||
{
|
||||
if (is_a($this->index, 'Kirby\Cms\Pages') === true) {
|
||||
return $this->index;
|
||||
// get object property by cache mode
|
||||
$index = $drafts === true ? $this->indexWithDrafts : $this->index;
|
||||
|
||||
if (is_a($index, 'Kirby\Cms\Pages') === true) {
|
||||
return $index;
|
||||
}
|
||||
|
||||
$this->index = new Pages([], $this->parent);
|
||||
$index = new Pages([], $this->parent);
|
||||
|
||||
foreach ($this->data as $pageKey => $page) {
|
||||
$this->index->data[$pageKey] = $page;
|
||||
$index = $page->index($drafts);
|
||||
$index->data[$pageKey] = $page;
|
||||
$pageIndex = $page->index($drafts);
|
||||
|
||||
if ($index) {
|
||||
foreach ($index as $childKey => $child) {
|
||||
$this->index->data[$childKey] = $child;
|
||||
if ($pageIndex) {
|
||||
foreach ($pageIndex as $childKey => $child) {
|
||||
$index->data[$childKey] = $child;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->index;
|
||||
if ($drafts === true) {
|
||||
return $this->indexWithDrafts = $index;
|
||||
}
|
||||
|
||||
return $this->index = $index;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -19,12 +19,12 @@ class Response extends \Kirby\Http\Response
|
||||
* parses locations with the Url::to method
|
||||
* first.
|
||||
*
|
||||
* @param string|null $location
|
||||
* @param int|null $code
|
||||
* @param string $location
|
||||
* @param int $code
|
||||
* @return self
|
||||
*/
|
||||
public static function redirect(?string $location = null, ?int $code = null)
|
||||
public static function redirect(string $location = '/', int $code = 302)
|
||||
{
|
||||
return parent::redirect(Url::to($location ?? '/'), $code);
|
||||
return parent::redirect(Url::to($location), $code);
|
||||
}
|
||||
}
|
||||
|
@@ -95,7 +95,7 @@ class Location
|
||||
$parts = explode('/', $part);
|
||||
|
||||
if (count($parts) === 1) {
|
||||
return $parts[0];
|
||||
return (float)$parts[0];
|
||||
}
|
||||
|
||||
return (float)($parts[0]) / (float)($parts[1]);
|
||||
|
@@ -597,7 +597,7 @@ class A
|
||||
*/
|
||||
public static function isAssociative(array $array): bool
|
||||
{
|
||||
return ctype_digit(implode(null, array_keys($array))) === false;
|
||||
return ctype_digit(implode('', array_keys($array))) === false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -252,7 +252,7 @@ class Collection extends Iterator implements Countable
|
||||
$split = $args[1] ?? false;
|
||||
|
||||
// filter by custom filter function
|
||||
if (is_callable($field) === true) {
|
||||
if (is_string($field) === false && is_callable($field) === true) {
|
||||
$collection = clone $this;
|
||||
$collection->data = array_filter($this->data, $field);
|
||||
|
||||
|
@@ -525,9 +525,12 @@ class F
|
||||
* Converts an integer size into a human readable format
|
||||
*
|
||||
* @param mixed $size The file size or a file path
|
||||
* @return string|int
|
||||
* @param string|null|false $locale Locale for number formatting,
|
||||
* `null` for the current locale,
|
||||
* `false` to disable number formatting
|
||||
* @return string
|
||||
*/
|
||||
public static function niceSize($size): string
|
||||
public static function niceSize($size, $locale = null): string
|
||||
{
|
||||
// file mode
|
||||
if (is_string($size) === true && file_exists($size) === true) {
|
||||
@@ -539,11 +542,18 @@ class F
|
||||
|
||||
// avoid errors for invalid sizes
|
||||
if ($size <= 0) {
|
||||
return '0 KB';
|
||||
return '0 KB';
|
||||
}
|
||||
|
||||
// the math magic
|
||||
return round($size / pow(1024, ($i = floor(log($size, 1024)))), 2) . ' ' . static::$units[$i];
|
||||
$size = round($size / pow(1024, ($unit = floor(log($size, 1024)))), 2);
|
||||
|
||||
// format the number if requested
|
||||
if ($locale !== false) {
|
||||
$size = I18n::formatNumber($size, $locale);
|
||||
}
|
||||
|
||||
return $size . ' ' . static::$units[$unit];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -129,7 +129,7 @@ class Iterator implements IteratorAggregate
|
||||
* Tries to find the index number for the given element
|
||||
*
|
||||
* @param mixed $needle the element to search for
|
||||
* @return string|false the name of the key or false
|
||||
* @return int|false the index (int) of the element or false
|
||||
*/
|
||||
public function indexOf($needle)
|
||||
{
|
||||
|
@@ -196,7 +196,7 @@ class Pagination
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ceil($this->total() / $this->limit());
|
||||
return (int)ceil($this->total() / $this->limit());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -410,7 +410,7 @@ class Str
|
||||
*/
|
||||
public static function isURL(string $string = null): bool
|
||||
{
|
||||
return filter_var($string, FILTER_VALIDATE_URL);
|
||||
return filter_var($string, FILTER_VALIDATE_URL) !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -803,6 +803,78 @@ class Str
|
||||
return static::short($string, $maxlength, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the similarity between two strings with multibyte support
|
||||
*
|
||||
* @author Based on the work of Antal Áron
|
||||
* @copyright Original Copyright (c) 2017, Antal Áron
|
||||
* @license https://github.com/antalaron/mb-similar-text/blob/master/LICENSE MIT License
|
||||
* @param string $first
|
||||
* @param string $second
|
||||
* @param bool $caseInsensitive If `true`, strings are compared case-insensitively
|
||||
* @return array matches: Number of matching chars in both strings
|
||||
* percent: Similarity in percent
|
||||
*/
|
||||
public static function similarity(string $first, string $second, bool $caseInsensitive = false): array
|
||||
{
|
||||
$matches = 0;
|
||||
$percent = 0.0;
|
||||
|
||||
if ($caseInsensitive === true) {
|
||||
$first = static::lower($first);
|
||||
$second = static::lower($second);
|
||||
}
|
||||
|
||||
if (static::length($first) + static::length($second) > 0) {
|
||||
$pos1 = $pos2 = $max = 0;
|
||||
$len1 = static::length($first);
|
||||
$len2 = static::length($second);
|
||||
|
||||
for ($p = 0; $p < $len1; ++$p) {
|
||||
for ($q = 0; $q < $len2; ++$q) {
|
||||
for (
|
||||
$l = 0;
|
||||
($p + $l < $len1) && ($q + $l < $len2) &&
|
||||
static::substr($first, $p + $l, 1) === static::substr($second, $q + $l, 1);
|
||||
++$l
|
||||
) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
if ($l > $max) {
|
||||
$max = $l;
|
||||
$pos1 = $p;
|
||||
$pos2 = $q;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$matches = $max;
|
||||
|
||||
if ($matches) {
|
||||
if ($pos1 && $pos2) {
|
||||
$similarity = static::similarity(
|
||||
static::substr($first, 0, $pos1),
|
||||
static::substr($second, 0, $pos2)
|
||||
);
|
||||
$matches += $similarity['matches'];
|
||||
}
|
||||
|
||||
if (($pos1 + $max < $len1) && ($pos2 + $max < $len2)) {
|
||||
$similarity = static::similarity(
|
||||
static::substr($first, $pos1 + $max, $len1 - $pos1 - $max),
|
||||
static::substr($second, $pos2 + $max, $len2 - $pos2 - $max)
|
||||
);
|
||||
$matches += $similarity['matches'];
|
||||
}
|
||||
}
|
||||
|
||||
$percent = ($matches * 200.0) / ($len1 + $len2);
|
||||
}
|
||||
|
||||
return compact('matches', 'percent');
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a string to snake case.
|
||||
*
|
||||
|
Reference in New Issue
Block a user