-
Notifications
You must be signed in to change notification settings - Fork 105
/
BasicExecutor.php
154 lines (119 loc) · 4.06 KB
/
BasicExecutor.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
<?php
declare(strict_types=1);
namespace Atk4\Ui\UserAction;
use Atk4\Core\HookTrait;
use Atk4\Data\Model;
use Atk4\Ui\Button;
use Atk4\Ui\Exception;
use Atk4\Ui\Header;
use Atk4\Ui\Js\JsBlock;
use Atk4\Ui\Js\JsExpressionable;
use Atk4\Ui\Js\JsToast;
use Atk4\Ui\Message;
use Atk4\Ui\View;
class BasicExecutor extends View implements ExecutorInterface
{
use HookTrait;
public const HOOK_AFTER_EXECUTE = self::class . '@afterExecute';
/** @var Model\UserAction|null */
public $action;
/** @var bool display header or not */
public $hasHeader = true;
/** @var string|null header description */
public $description;
/** @var string display message when action is disabled */
public $disableMsg = 'Action is disabled and cannot be executed';
/** @var Button|array Button that trigger the action. Either as an array seed or object */
public $executorButton;
/** @var array */
protected $arguments = [];
/** @var string display message when missing arguments */
public $missingArgsMsg = 'Insufficient arguments';
/** @var array list of validated arguments */
protected $validArguments = [];
/** @var JsExpressionable|\Closure JS expression to return if action was successful, e.g "new JsToast('Thank you')" */
protected $jsSuccess;
public function getAction(): Model\UserAction
{
return $this->action;
}
public function setAction(Model\UserAction $action)
{
$this->action = $action;
if (!$this->executorButton) {
$this->executorButton = $this->getExecutorFactory()->createTrigger($action, ExecutorFactory::BASIC_BUTTON);
}
return $this;
}
/**
* Provide values for named arguments.
*/
public function setArguments(array $arguments): void
{
// TODO: implement mechanism for validating arguments based on definition
$this->arguments = array_merge($this->arguments, $arguments);
}
protected function recursiveRender(): void
{
if (!$this->action) {
throw new Exception('Action is not set. Use setAction()');
}
// check action can be called
if ($this->action->enabled) {
$this->initPreview();
} else {
Message::addTo($this, ['type' => 'error', $this->disableMsg]);
return;
}
parent::recursiveRender();
}
/**
* Check if all argument values have been provided.
*/
public function hasAllArguments(): bool
{
foreach ($this->action->args as $key => $val) {
if (!isset($this->arguments[$key])) {
return false;
}
}
return true;
}
protected function initPreview(): void
{
// lets make sure that all arguments are supplied
if (!$this->hasAllArguments()) {
Message::addTo($this, ['type' => 'error', $this->missingArgsMsg]);
return;
}
$this->addHeader();
Button::addToWithCl($this, $this->executorButton)->on('click', function () {
return $this->executeModelAction();
});
}
/**
* Will call $action->execute() with the correct arguments.
*/
public function executeModelAction(): JsBlock
{
$args = [];
foreach ($this->action->args as $key => $val) {
$args[] = $this->arguments[$key];
}
$return = $this->action->execute(...$args);
$success = $this->jsSuccess instanceof \Closure
? ($this->jsSuccess)($this, $this->action->getModel())
: $this->jsSuccess;
return JsBlock::fromHookResult($this->hook(self::HOOK_AFTER_EXECUTE, [$return]) // @phpstan-ignore-line
?: ($success ?? new JsToast('Success' . (is_string($return) ? (': ' . $return) : ''))));
}
/**
* Will add header if set.
*/
public function addHeader(): void
{
if ($this->hasHeader) {
Header::addTo($this, [$this->action->getCaption(), 'subHeader' => $this->description ?? $this->action->getDescription()]);
}
}
}