|
11 | 11 |
|
12 | 12 | use Latte;
|
13 | 13 | use Latte\ContentType;
|
| 14 | +use Latte\Essential\Blueprint; |
| 15 | +use Nette\PhpGenerator as Php; |
14 | 16 |
|
15 | 17 |
|
16 | 18 | /**
|
@@ -38,6 +40,7 @@ public function generate(
|
38 | 40 | string $className,
|
39 | 41 | ?string $comment = null,
|
40 | 42 | bool $strictMode = false,
|
| 43 | + array $filters = [], |
41 | 44 | ): string {
|
42 | 45 | $context = new PrintContext($node->contentType);
|
43 | 46 | $scope = $context->getVariableScope();
|
@@ -78,13 +81,18 @@ public function generate(
|
78 | 81 | . ($method['body'] ? "\t\t$method[body]\n" : '') . "\t}";
|
79 | 82 | }
|
80 | 83 |
|
| 84 | + $comment .= "\n@property Filters$className \$filters"; |
| 85 | + $comment = str_replace('*/', '* /', $comment); |
| 86 | + $comment = str_replace("\n", "\n * ", "/**\n" . trim($comment)) . "\n */\n"; |
| 87 | + |
81 | 88 | $code = "<?php\n\n"
|
82 | 89 | . ($strictMode ? "declare(strict_types=1);\n\n" : '')
|
83 | 90 | . "use Latte\\Runtime as LR;\n\n"
|
84 |
| - . ($comment === null ? '' : '/** ' . str_replace('*/', '* /', $comment) . " */\n") |
| 91 | + . $comment |
85 | 92 | . "final class $className extends Latte\\Runtime\\Template\n{\n"
|
86 | 93 | . implode("\n\n", $members)
|
87 |
| - . "\n}\n"; |
| 94 | + . "\n}\n\n\n" |
| 95 | + . $this->generateStub($node, 'Filters' . $className, $filters); |
88 | 96 |
|
89 | 97 | $code = PhpHelpers::optimizeEcho($code);
|
90 | 98 | $code = PhpHelpers::reformatCode($code);
|
@@ -124,6 +132,39 @@ private function generateBlocks(array $blocks, PrintContext $context): void
|
124 | 132 | }
|
125 | 133 |
|
126 | 134 |
|
| 135 | + private function generateStub(Node $node, string $className, $filters): string |
| 136 | + { |
| 137 | + if (!class_exists(Php\ClassType::class)) { |
| 138 | + return ''; |
| 139 | + } |
| 140 | + |
| 141 | + $used = []; |
| 142 | + (new NodeTraverser)->traverse($node, function (Node $node) use (&$used) { |
| 143 | + if ($node instanceof Nodes\Php\FilterNode) { |
| 144 | + $used[$node->name->name] = true; |
| 145 | + } |
| 146 | + }); |
| 147 | + |
| 148 | + $class = new Php\ClassType($className); |
| 149 | + $filters = array_intersect_key($filters, $used); |
| 150 | + foreach ($filters as $name => $callback) { |
| 151 | + $func = (new Php\Factory)->fromCallable($callback); |
| 152 | + $type = Blueprint::printType($func->getReturnType(), $func->isReturnNullable(), null) ?: 'mixed'; |
| 153 | + $params = []; |
| 154 | + $list = $func->getParameters(); |
| 155 | + foreach ($list as $param) { |
| 156 | + $variadic = $func->isVariadic() && $param === end($list); |
| 157 | + $params[] = (Blueprint::printType($param->getType(), $param->isNullable(), null) ?: 'mixed') |
| 158 | + . ($variadic ? '...' : ''); |
| 159 | + } |
| 160 | + |
| 161 | + $class->addComment('@property callable(' . implode(', ', $params) . "): $type \$$name"); |
| 162 | + } |
| 163 | + |
| 164 | + return (string) $class; |
| 165 | + } |
| 166 | + |
| 167 | + |
127 | 168 | /**
|
128 | 169 | * @param Nodes\Php\ParameterNode[] $params
|
129 | 170 | */
|
|
0 commit comments