Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Buttons 4: View button PHP classes #6542

Merged
merged 3 commits into from
Jul 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/Panel/Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,15 @@ public function lock(): array|false
return $this->model->lock()?->toArray() ?? false;
}

/**
* Returns the corresponding model object
* @since 5.0.0
*/
public function model(): ModelWithContent
{
return $this->model;
}

/**
* Returns an array of all actions
* that can be performed in the Panel
Expand Down
2 changes: 1 addition & 1 deletion src/Panel/Ui/Button.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ class Button extends Component
{
public function __construct(
public string $component = 'k-button',
public string|bool|null $current = null,
public string|null $class = null,
public string|bool|null $current = null,
public string|null $dialog = null,
public bool $disabled = false,
public string|null $drawer = null,
Expand Down
157 changes: 157 additions & 0 deletions src/Panel/Ui/Buttons/ViewButton.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
<?php

namespace Kirby\Panel\Ui\Buttons;

use Closure;
use Kirby\Cms\App;
use Kirby\Panel\Panel;
use Kirby\Panel\Ui\Button;
use Kirby\Toolkit\Controller;

/**
* A view button is a UI button, by default small in size and filles,
* that optionally defines options for a dropdown
*
* @package Kirby Panel
* @author Nico Hoffmann <nico@getkirby.com>
* @link https://getkirby.com
* @copyright Bastian Allgeier
* @license https://getkirby.com/license
* @since 5.0.0
* @internal
*
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
*/
class ViewButton extends Button
{
public function __construct(
public string $component = 'k-view-button',
public string|null $class = null,
public string|bool|null $current = null,
public string|null $dialog = null,
public bool $disabled = false,
public string|null $drawer = null,
public bool|null $dropdown = null,
public string|null $icon = null,
public string|null $link = null,
public array|string|null $options = null,
public bool|string $responsive = true,
public string|null $size = 'sm',
public string|null $style = null,
public string|null $target = null,
public string|null $text = null,
public string|null $theme = null,
public string|null $title = null,
public string $type = 'button',
public string|null $variant = 'filled',
) {
}

/**
* Creates new view button by looking up
* the button in all areas, if referenced by name
* and resolving to proper instance
*/
public static function factory(
string|array|Closure $button,
string|null $view = null,
array $args = []
): static|null {
// referenced by name
if (is_string($button) === true) {
$button = static::find($button, $view);
}

$button = static::resolve($button, $args);

if (
$button === null ||
$button instanceof ViewButton
) {
return $button;
}

return new static(...static::normalize($button));
}

/**
* Finds a view button by name
* among the defined buttons from all areas
*/
public static function find(
string $name,
string|null $view = null
): array|Closure {
// collect all buttons from areas
$buttons = Panel::buttons();

// try to find by full name (view-prefixed)
if ($view && $button = $buttons[$view . '.' . $name] ?? null) {
return $button;
}

// try to find by just name
if ($button = $buttons[$name] ?? null) {
return $button;
}

// assume it must be a custom view button component
return ['component' => 'k-view-' . $name . '-button'];
}

/**
* Transforms an array to be used as
* named arguments in the constructor
* @internal
*/
public static function normalize(array $button): array
{
// if component and props are both not set, assume shortcut
// where props were directly passed on top-level
if (
isset($button['component']) === false &&
isset($button['props']) === false
) {
return $button;
}

// flatten array
if ($props = $button['props'] ?? null) {
$button = [...$props, ...$button];
unset($button['props']);
}

return $button;
}

public function props(): array
{
return [
...parent::props(),
'options' => $this->options
];
}

/**
* Transforms a closure to the actual view button
* by calling it with the provided arguments
* @internal
*/
public static function resolve(
Closure|array $button,
array $args = []
): static|array|null {
if ($button instanceof Closure) {
$kirby = App::instance();
$controller = new Controller($button);
$button = $controller->call(data: [
'kirby' => $kirby,
'site' => $kirby->site(),
'user' => $kirby->user(),
...$args
]);
}

return $button;
}
}
72 changes: 72 additions & 0 deletions src/Panel/Ui/Buttons/ViewButtons.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php

namespace Kirby\Panel\Ui\Buttons;

use Kirby\Cms\App;
use Kirby\Panel\Model;
use Kirby\Toolkit\A;

/**
* Collects view buttons for a specific view
*
* @package Kirby Panel
* @author Nico Hoffmann <nico@getkirby.com>
* @link https://getkirby.com
* @copyright Bastian Allgeier
* @license https://getkirby.com/license
* @since 5.0.0
* @internal
*/
class ViewButtons
{
public function __construct(
public readonly string $view,
public array|null $buttons = null
) {
$this->buttons ??= App::instance()->option(
'panel.viewButtons.' . $view
);
}

/**
* Sets the default buttons
*
* @return $this
*/
public function defaults(string ...$defaults): static
{
$this->buttons ??= $defaults;
return $this;
}
distantnative marked this conversation as resolved.
Show resolved Hide resolved

/**
* Returns array of button component-props definitions
*/
public function render(array $args = []): array
{
$buttons = A::map(
$this->buttons ?? [],
fn ($button) =>
ViewButton::factory($button, $this->view, $args)?->render()
);

return array_values(array_filter($buttons));
}

/**
* Creates new instance for a view
* with special support for model views
*/
public static function view(string|Model $view): static
{
if ($view instanceof Model) {
$blueprint = $view->model()->blueprint()->buttons();
$view = $view->model()::CLASS_ALIAS;
}

return new static(
view: $view,
buttons: $blueprint ?? null
);
}
}
9 changes: 9 additions & 0 deletions tests/Panel/ModelTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,15 @@ public function testLock()
$this->assertSame('unlock', $site->panel()->lock()['state']);
}

/**
* @covers ::model
*/
public function testModel()
{
$panel = $this->panel();
$this->assertInstanceOf(ModelSite::class, $panel->model());
}

/**
* @covers ::props
*/
Expand Down
Loading
Loading