Upgrade to 3.6.0
This commit is contained in:
379
kirby/src/Panel/Page.php
Executable file
379
kirby/src/Panel/Page.php
Executable file
@@ -0,0 +1,379 @@
|
||||
<?php
|
||||
|
||||
namespace Kirby\Panel;
|
||||
|
||||
/**
|
||||
* Provides information about the page model for the Panel
|
||||
* @since 3.6.0
|
||||
*
|
||||
* @package Kirby Panel
|
||||
* @author Nico Hoffmann <nico@getkirby.com>
|
||||
* @link https://getkirby.com
|
||||
* @copyright Bastian Allgeier GmbH
|
||||
* @license https://getkirby.com/license
|
||||
*/
|
||||
class Page extends Model
|
||||
{
|
||||
/**
|
||||
* Breadcrumb array
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function breadcrumb(): array
|
||||
{
|
||||
$parents = $this->model->parents()->flip()->merge($this->model);
|
||||
return $parents->values(function ($parent) {
|
||||
return [
|
||||
'label' => $parent->title()->toString(),
|
||||
'link' => $parent->panel()->url(true),
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a kirbytag or markdown
|
||||
* tag for the page, which will be
|
||||
* used in the panel, when the page
|
||||
* gets dragged onto a textarea
|
||||
*
|
||||
* @internal
|
||||
* @param string|null $type (`auto`|`kirbytext`|`markdown`)
|
||||
* @return string
|
||||
*/
|
||||
public function dragText(string $type = null): string
|
||||
{
|
||||
$type = $this->dragTextType($type);
|
||||
|
||||
if ($callback = $this->dragTextFromCallback($type)) {
|
||||
return $callback;
|
||||
}
|
||||
|
||||
if ($type === 'markdown') {
|
||||
return '[' . $this->model->title() . '](' . $this->model->url() . ')';
|
||||
}
|
||||
|
||||
return '(link: ' . $this->model->id() . ' text: ' . $this->model->title() . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides options for the page dropdown
|
||||
*
|
||||
* @param array $options
|
||||
* @return array
|
||||
*/
|
||||
public function dropdown(array $options = []): array
|
||||
{
|
||||
$defaults = [
|
||||
'view' => get('view'),
|
||||
'sort' => get('sort'),
|
||||
'delete' => get('delete')
|
||||
];
|
||||
|
||||
$options = array_merge($defaults, $options);
|
||||
$page = $this->model;
|
||||
$permissions = $this->options(['preview']);
|
||||
$view = $options['view'] ?? 'view';
|
||||
$url = $this->url(true);
|
||||
$result = [];
|
||||
|
||||
if ($view === 'list') {
|
||||
$result['preview'] = [
|
||||
'link' => $page->previewUrl(),
|
||||
'target' => '_blank',
|
||||
'icon' => 'open',
|
||||
'text' => t('open'),
|
||||
'disabled' => $this->isDisabledDropdownOption('preview', $options, $permissions)
|
||||
];
|
||||
$result[] = '-';
|
||||
}
|
||||
|
||||
$result['changeTitle'] = [
|
||||
'dialog' => [
|
||||
'url' => $url . '/changeTitle',
|
||||
'query' => [
|
||||
'select' => 'title'
|
||||
]
|
||||
],
|
||||
'icon' => 'title',
|
||||
'text' => t('rename'),
|
||||
'disabled' => $this->isDisabledDropdownOption('changeTitle', $options, $permissions)
|
||||
];
|
||||
|
||||
$result['duplicate'] = [
|
||||
'dialog' => $url . '/duplicate',
|
||||
'icon' => 'copy',
|
||||
'text' => t('duplicate'),
|
||||
'disabled' => $this->isDisabledDropdownOption('duplicate', $options, $permissions)
|
||||
];
|
||||
|
||||
$result[] = '-';
|
||||
|
||||
$result['changeSlug'] = [
|
||||
'dialog' => [
|
||||
'url' => $url . '/changeTitle',
|
||||
'query' => [
|
||||
'select' => 'slug'
|
||||
]
|
||||
],
|
||||
'icon' => 'url',
|
||||
'text' => t('page.changeSlug'),
|
||||
'disabled' => $this->isDisabledDropdownOption('changeSlug', $options, $permissions)
|
||||
];
|
||||
|
||||
$result['changeStatus'] = [
|
||||
'dialog' => $url . '/changeStatus',
|
||||
'icon' => 'preview',
|
||||
'text' => t('page.changeStatus'),
|
||||
'disabled' => $this->isDisabledDropdownOption('changeStatus', $options, $permissions)
|
||||
];
|
||||
|
||||
$siblings = $page->parentModel()->children()->listed()->not($page);
|
||||
|
||||
$result['changeSort'] = [
|
||||
'dialog' => $url . '/changeSort',
|
||||
'icon' => 'sort',
|
||||
'text' => t('page.sort'),
|
||||
'disabled' => $siblings->count() === 0 || $this->isDisabledDropdownOption('sort', $options, $permissions)
|
||||
];
|
||||
|
||||
$result['changeTemplate'] = [
|
||||
'dialog' => $url . '/changeTemplate',
|
||||
'icon' => 'template',
|
||||
'text' => t('page.changeTemplate'),
|
||||
'disabled' => $this->isDisabledDropdownOption('changeTemplate', $options, $permissions)
|
||||
];
|
||||
|
||||
$result[] = '-';
|
||||
$result['delete'] = [
|
||||
'dialog' => $url . '/delete',
|
||||
'icon' => 'trash',
|
||||
'text' => t('delete'),
|
||||
'disabled' => $this->isDisabledDropdownOption('delete', $options, $permissions)
|
||||
];
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the setup for a dropdown option
|
||||
* which is used in the changes dropdown
|
||||
* for example.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function dropdownOption(): array
|
||||
{
|
||||
return [
|
||||
'text' => $this->model->title()->value(),
|
||||
] + parent::dropdownOption();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the escaped Id, which is
|
||||
* used in the panel to make routing work properly
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function id(): string
|
||||
{
|
||||
return str_replace('/', '+', $this->model->id());
|
||||
}
|
||||
|
||||
/**
|
||||
* Default settings for the page's Panel image
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function imageDefaults(): array
|
||||
{
|
||||
$defaults = [];
|
||||
|
||||
if ($icon = $this->model->blueprint()->icon()) {
|
||||
$defaults['icon'] = $icon;
|
||||
}
|
||||
|
||||
return array_merge(parent::imageDefaults(), $defaults);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the image file object based on provided query
|
||||
*
|
||||
* @internal
|
||||
* @param string|null $query
|
||||
* @return \Kirby\Cms\File|\Kirby\Filesystem\Asset|null
|
||||
*/
|
||||
protected function imageSource(string $query = null)
|
||||
{
|
||||
if ($query === null) {
|
||||
$query = 'page.image';
|
||||
}
|
||||
|
||||
return parent::imageSource($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the full path without leading slash
|
||||
*
|
||||
* @internal
|
||||
* @return string
|
||||
*/
|
||||
public function path(): string
|
||||
{
|
||||
return 'pages/' . $this->id();
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the response data for page pickers
|
||||
* and page fields
|
||||
*
|
||||
* @param array|null $params
|
||||
* @return array
|
||||
*/
|
||||
public function pickerData(array $params = []): array
|
||||
{
|
||||
$params['text'] = $params['text'] ?? '{{ page.title }}';
|
||||
|
||||
return array_merge(parent::pickerData($params), [
|
||||
'dragText' => $this->dragText(),
|
||||
'hasChildren' => $this->model->hasChildren(),
|
||||
'url' => $this->model->url()
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* The best applicable position for
|
||||
* the position/status dialog
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function position(): int
|
||||
{
|
||||
return $this->model->num() ?? $this->model->parentModel()->children()->listed()->not($this->model)->count() + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns navigation array with
|
||||
* previous and next page
|
||||
* based on blueprint definition
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function prevNext(): array
|
||||
{
|
||||
$page = $this->model;
|
||||
|
||||
// create siblings collection based on
|
||||
// blueprint navigation
|
||||
$siblings = function (string $direction) use ($page) {
|
||||
$navigation = $page->blueprint()->navigation();
|
||||
$sortBy = $navigation['sortBy'] ?? null;
|
||||
$status = $navigation['status'] ?? null;
|
||||
$template = $navigation['template'] ?? null;
|
||||
$direction = $direction === 'prev' ? 'prev' : 'next';
|
||||
|
||||
// if status is defined in navigation,
|
||||
// all items in the collection are used
|
||||
// (drafts, listed and unlisted) otherwise
|
||||
// it depends on the status of the page
|
||||
$siblings = $status !== null ? $page->parentModel()->childrenAndDrafts() : $page->siblings();
|
||||
|
||||
// sort the collection if custom sortBy
|
||||
// defined in navigation otherwise
|
||||
// default sorting will apply
|
||||
if ($sortBy !== null) {
|
||||
$siblings = $siblings->sort(...$siblings::sortArgs($sortBy));
|
||||
}
|
||||
|
||||
$siblings = $page->{$direction . 'All'}($siblings);
|
||||
|
||||
if (empty($navigation) === false) {
|
||||
$statuses = (array)($status ?? $page->status());
|
||||
$templates = (array)($template ?? $page->intendedTemplate());
|
||||
|
||||
// do not filter if template navigation is all
|
||||
if (in_array('all', $templates) === false) {
|
||||
$siblings = $siblings->filter('intendedTemplate', 'in', $templates);
|
||||
}
|
||||
|
||||
// do not filter if status navigation is all
|
||||
if (in_array('all', $statuses) === false) {
|
||||
$siblings = $siblings->filter('status', 'in', $statuses);
|
||||
}
|
||||
} else {
|
||||
$siblings = $siblings
|
||||
->filter('intendedTemplate', $page->intendedTemplate())
|
||||
->filter('status', $page->status());
|
||||
}
|
||||
|
||||
return $siblings->filter('isReadable', true);
|
||||
};
|
||||
|
||||
return [
|
||||
'next' => function () use ($siblings) {
|
||||
$next = $siblings('next')->first();
|
||||
return $next ? $next->panel()->toLink('title') : null;
|
||||
},
|
||||
'prev' => function () use ($siblings) {
|
||||
$prev = $siblings('prev')->last();
|
||||
return $prev ? $prev->panel()->toLink('title') : null;
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data array for the
|
||||
* view's component props
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function props(): array
|
||||
{
|
||||
$page = $this->model;
|
||||
|
||||
return array_merge(
|
||||
parent::props(),
|
||||
$this->prevNext(),
|
||||
[
|
||||
'blueprint' => $this->model->intendedTemplate()->name(),
|
||||
'model' => [
|
||||
'content' => $this->content(),
|
||||
'id' => $page->id(),
|
||||
'link' => $this->url(true),
|
||||
'parent' => $page->parentModel()->panel()->url(true),
|
||||
'previewUrl' => $page->previewUrl(),
|
||||
'status' => $page->status(),
|
||||
'title' => $page->title()->toString(),
|
||||
],
|
||||
'status' => function () use ($page) {
|
||||
if ($status = $page->status()) {
|
||||
return $page->blueprint()->status()[$status] ?? null;
|
||||
}
|
||||
},
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data array for
|
||||
* this model's Panel view
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function view(): array
|
||||
{
|
||||
$page = $this->model;
|
||||
|
||||
return [
|
||||
'breadcrumb' => $page->panel()->breadcrumb(),
|
||||
'component' => 'k-page-view',
|
||||
'props' => $this->props(),
|
||||
'title' => $page->title()->toString(),
|
||||
];
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user