Skip to content

Commit

Permalink
View button PHP classes
Browse files Browse the repository at this point in the history
  • Loading branch information
distantnative committed Jul 20, 2024
1 parent ce0b491 commit 3023173
Show file tree
Hide file tree
Showing 6 changed files with 541 additions and 0 deletions.
5 changes: 5 additions & 0 deletions src/Panel/Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,11 @@ public function lock(): array|false
return $this->model->lock()?->toArray() ?? false;
}

public function model(): ModelWithContent
{
return $this->model;
}

/**
* Returns an array of all actions
* that can be performed in the Panel
Expand Down
155 changes: 155 additions & 0 deletions src/Panel/Ui/Buttons/ViewButton.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
<?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 <[email protected]>
* @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|null $dialog = null,
public bool $disabled = false,
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 <[email protected]>
* @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;
}

/**
* 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

0 comments on commit 3023173

Please sign in to comment.