-
-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
269 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
<?php declare(strict_types = 1); | ||
|
||
namespace Contributte\FormMultiplier\Latte\Extension; | ||
|
||
use Contributte\FormMultiplier\Latte\Extension\Node\MultiplierAddNode; | ||
use Contributte\FormMultiplier\Latte\Extension\Node\MultiplierNode; | ||
use Contributte\FormMultiplier\Latte\Extension\Node\MultiplierRemoveNode; | ||
use Latte\Extension; | ||
|
||
final class MultiplierExtension extends Extension | ||
{ | ||
|
||
/** | ||
* @return array<string, callable> | ||
*/ | ||
public function getTags(): array | ||
{ | ||
return [ | ||
'multiplier' => [MultiplierNode::class, 'create'], | ||
'n:multiplier' => [MultiplierNode::class, 'create'], | ||
'multiplier:remove' => [MultiplierRemoveNode::class, 'create'], | ||
'multiplier:add' => [MultiplierAddNode::class, 'create'], | ||
]; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
<?php declare(strict_types = 1); | ||
|
||
namespace Contributte\FormMultiplier\Latte\Extension\Node; | ||
|
||
use Contributte\FormMultiplier\Multiplier; | ||
use Contributte\FormMultiplier\Submitter; | ||
use Latte\Compiler\Nodes\Php\Expression\ArrayNode; | ||
use Latte\Compiler\Nodes\Php\ExpressionNode; | ||
use Latte\Compiler\Nodes\Php\Scalar\StringNode; | ||
use Latte\Compiler\Nodes\StatementNode; | ||
use Latte\Compiler\PrintContext; | ||
use Latte\Compiler\Tag; | ||
use LogicException; | ||
use Nette\ComponentModel\IComponent; | ||
use Nette\Forms\Container; | ||
use Nette\Forms\SubmitterControl; | ||
|
||
final class MultiplierAddNode extends StatementNode | ||
{ | ||
|
||
/** @var ExpressionNode */ | ||
private $name; | ||
|
||
/** @var ArrayNode */ | ||
private $attributes; | ||
|
||
/** @var ExpressionNode */ | ||
private $part; | ||
|
||
public static function create(Tag $tag): self | ||
{ | ||
$tag->expectArguments('multiplier name'); | ||
|
||
$node = new self(); | ||
$node->name = $tag->parser->parseUnquotedStringOrExpression(false); | ||
|
||
if ($tag->parser->stream->tryConsume(':') && !$tag->parser->stream->is(',')) { | ||
$node->part = $tag->parser->isEnd() | ||
? new StringNode('1') | ||
: $tag->parser->parseUnquotedStringOrExpression(); | ||
} else { | ||
$node->part = new StringNode('1'); | ||
} | ||
|
||
$node->attributes = $tag->parser->parseArguments(); | ||
|
||
return $node; | ||
} | ||
|
||
public function print(PrintContext $context): string | ||
{ | ||
return $context->format( | ||
($this->name instanceof StringNode | ||
? '$ʟ_multiplier = end($this->global->formsStack)[%node];' | ||
: '$ʟ_multiplier = is_object($ʟ_tmp = %node) ? $ʟ_tmp : end($this->global->formsStack)[$ʟ_tmp];') | ||
. 'if ($ʟ_input = %raw::getCreateButton($ʟ_multiplier, %node)) {' | ||
. 'echo $ʟ_input->getControl()' | ||
. ($this->attributes->items ? '->addAttributes(%node)' : '') | ||
. ';' | ||
. '} %4.line', | ||
$this->name, | ||
self::class, | ||
$this->part, | ||
$this->attributes, | ||
$this->position | ||
); | ||
} | ||
|
||
/** | ||
* @param int|string $buttonId | ||
*/ | ||
public static function getCreateButton(Multiplier $multiplier, $buttonId): ?Submitter | ||
{ | ||
return $multiplier->getCreateButtons()[$buttonId] ?? null; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
<?php declare(strict_types = 1); | ||
|
||
namespace Contributte\FormMultiplier\Latte\Extension\Node; | ||
|
||
use Generator; | ||
use Latte\Compiler\Nodes\AreaNode; | ||
use Latte\Compiler\Nodes\Php\ExpressionNode; | ||
use Latte\Compiler\Nodes\Php\Scalar\StringNode; | ||
use Latte\Compiler\Nodes\StatementNode; | ||
use Latte\Compiler\Position; | ||
use Latte\Compiler\PrintContext; | ||
use Latte\Compiler\Tag; | ||
|
||
final class MultiplierNode extends StatementNode | ||
{ | ||
|
||
/** @var ExpressionNode */ | ||
private $name; | ||
|
||
/** @var AreaNode */ | ||
private $content; | ||
|
||
/** | ||
* @return Generator<int, ?mixed[], array{AreaNode, ?Tag}, self> | ||
*/ | ||
public static function create(Tag $tag): Generator | ||
{ | ||
$tag->outputMode = $tag::OutputRemoveIndentation; | ||
$tag->expectArguments(); | ||
|
||
$node = new static; | ||
$node->name = $tag->parser->parseUnquotedStringOrExpression(); | ||
|
||
[$node->content] = yield; | ||
|
||
return $node; | ||
} | ||
|
||
public function print(PrintContext $context): string | ||
{ | ||
return $context->format( | ||
'$multiplier = ' | ||
. ($this->name instanceof StringNode | ||
? 'end($this->global->formsStack)[%node];' | ||
: 'is_object($ʟ_tmp = %node) ? $ʟ_tmp : end($this->global->formsStack)[$ʟ_tmp];') | ||
. 'foreach ($multiplier->getContainers() as $formContainer) {' | ||
. "\n" | ||
. '$this->global->formsStack[] = $formContainer;' | ||
. ' %line %node ' // content | ||
. 'array_pop($this->global->formsStack);' | ||
. "\n" | ||
. '}' | ||
. '$formContainer = end($this->global->formsStack);' | ||
. "\n\n", | ||
$this->name, | ||
$this->position, | ||
$this->content | ||
); | ||
} | ||
public function &getIterator(): \Generator | ||
{ | ||
yield $this->name; | ||
yield $this->content; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
<?php declare(strict_types = 1); | ||
|
||
namespace Contributte\FormMultiplier\Latte\Extension\Node; | ||
|
||
use Contributte\FormMultiplier\Multiplier; | ||
use Latte\Compiler\Nodes\Php\Expression\ArrayNode; | ||
use Latte\Compiler\Nodes\StatementNode; | ||
use Latte\Compiler\PrintContext; | ||
use Latte\Compiler\Tag; | ||
use LogicException; | ||
use Nette\ComponentModel\IComponent; | ||
use Nette\Forms\Container; | ||
use Nette\Forms\SubmitterControl; | ||
|
||
final class MultiplierRemoveNode extends StatementNode | ||
{ | ||
|
||
/** @var ArrayNode */ | ||
private $attributes; | ||
|
||
public static function create(Tag $tag): self | ||
{ | ||
$node = new self(); | ||
$node->attributes = $tag->parser->parseArguments(); | ||
|
||
return $node; | ||
} | ||
|
||
public function print(PrintContext $context): string | ||
{ | ||
return $context->format( | ||
'if ($ʟ_input = %raw::getRemoveButton($this->global->formsStack)) {' | ||
. 'echo $ʟ_input->getControl()' | ||
. ($this->attributes->items ? '->addAttributes(%1.node)' : '') | ||
. ';' | ||
. '} %2.line', | ||
self::class, | ||
$this->attributes, | ||
$this->position | ||
); | ||
} | ||
|
||
/** | ||
* @param Container[] $formsStack | ||
*/ | ||
public static function getRemoveButton(array $formsStack): ?IComponent | ||
{ | ||
$container = end($formsStack); | ||
|
||
if (!$container || !$container->getParent() instanceof Multiplier) { | ||
throw new LogicException('{multiplier:remove} macro must be inside {multiplier} macro.'); | ||
} | ||
|
||
return $container->getComponent(Multiplier::SUBMIT_REMOVE_NAME, false); | ||
} | ||
|
||
} |