1: <?php
2:
3: declare(strict_types=1);
4:
5: namespace Atk4\Ui\Js;
6:
7: use Atk4\Core\WarnDynamicPropertyTrait;
8:
9: class JsFunction implements JsExpressionable
10: {
11: use WarnDynamicPropertyTrait;
12:
13: /** @var list<string> */
14: public array $args;
15:
16: public JsBlock $body;
17:
18: /** Add event.preventDefault() to generated method */
19: public bool $preventDefault = false;
20:
21: /** Add event.stopPropagation() to generated method */
22: public bool $stopPropagation = false;
23:
24: /** Indent of target code (not one indent level) */
25: public string $indent = '';
26:
27: /**
28: * @param JsBlock|array<int, JsExpressionable|null>|array<string, mixed> $statements
29: */
30: public function __construct(array $args, $statements)
31: {
32: $this->args = $args;
33:
34: if (!is_array($statements)) {
35: $this->body = $statements;
36: } else {
37: foreach ($statements as $key => $value) {
38: if (is_string($key)) {
39: $this->{$key} = $value;
40: unset($statements[$key]);
41: } elseif ($value === null) { // TODO this should be not needed
42: unset($statements[$key]);
43: }
44: }
45:
46: $this->body = new JsBlock($statements);
47: }
48: }
49:
50: #[\Override]
51: public function jsRender(): string
52: {
53: $pre = '';
54: if ($this->preventDefault) {
55: $this->args = ['event'];
56: $pre .= $this->indent . ' event.preventDefault();' . "\n";
57: }
58: if ($this->stopPropagation) {
59: $this->args = ['event'];
60: $pre .= $this->indent . ' event.stopPropagation();' . "\n";
61: }
62:
63: $output = $this->indent . 'function (' . implode(', ', $this->args) . ') {' . "\n"
64: . $pre
65: . preg_replace('~^~m', $this->indent . ' ', $this->body->jsRender()) . "\n" // TODO IMPORTANT indentation must ignore multiline strings/comments!
66: . $this->indent . '}';
67:
68: return $output;
69: }
70: }
71: