Skip to content

Commit

Permalink
Merge pull request #11 from nymo/master
Browse files Browse the repository at this point in the history
Added Twig Form Extension as Helper
  • Loading branch information
naucon authored Aug 29, 2022
2 parents e00140d + 97bdc0d commit 4dadff3
Show file tree
Hide file tree
Showing 4 changed files with 233 additions and 2 deletions.
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,31 @@ It's also possible to use the `{ncform_field}` element to output only parts of a

<input type="text" name="{ncform_field type='name' field='email'}" value="{ncform_field type='value' field='email'}" id="{ncform_field type='id' field='email'}" maxlength="32" />

##### FormHelper with Twig Templates

First you have to register the twig extension

```php
use Naucon\Form\Helper\Twig\NcFormExtension;
$twig = new \Twig\Environment($loader);
$twig->addExtension(new NcFormExtension());
```


Functions | Tags | Attributes
:------------ |:-------------------| :----------
ncform_start | {{ncform_start()}} | form, method?, action?, enctype?, id?, class?, style?
ncform_field | {{ncform_field()}} | form, type, field, value?, maxlength?, id?, class?, style?, data-attributes?, required?
ncform_end | {{ncform_end()}} | form

Example

```php
{{ ncform_start(form, method='post', action='some-action', enctype='some type', {furtherOptions:'option'}) }}
{{ ncform_field(form, 'text', 'activation_code', { style: 'some style', id: 'some id', value: 'some value', maxlength: 'some lenght', class: 'css class', required: 'required', 'data-attribute': 'some attribute'}) }}
{{ ncform_end(form) }}
```


##### without form helper

Expand Down
6 changes: 4 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,13 @@
"symfony/intl": "^3.2 || ^4.0",
"symfony/config": "^3.2 || ^4.0",
"naucon/iban": "~1.0",
"phpunit/phpunit": "^7.0"
"phpunit/phpunit": "^7.0",
"twig/twig" : "^2.4"
},
"suggest": {
"symfony/config": "Is required to use xml mapping.",
"naucon/iban": "Is required to validate iban."
"naucon/iban": "Is required to validate iban.",
"twig/twig": "Is required for using the twig form extension"
},
"autoload": {
"psr-4": {"Naucon\\Form\\": "src/"}
Expand Down
63 changes: 63 additions & 0 deletions src/Helper/Twig/NcFormExtension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php

namespace Naucon\Form\Helper\Twig;

use InvalidArgumentException;
use Naucon\Form\FormHelper;
use Naucon\Form\FormInterface;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;

class NcFormExtension extends AbstractExtension
{
public function getFunctions()
{
return [
new TwigFunction('ncform_start', [$this, 'formStart'], ['is_safe' => ['html']]),
new TwigFunction('ncform_end', [$this, 'formEnd'], ['is_safe' => ['html']]),
new TwigFunction('ncform_field', [$this, 'field'], ['is_safe' => ['html']])
];
}

public function formStart(
FormInterface $form,
string $method = 'post',
?string $action = null,
?string $enctype = null,
array $options = []
): string
{
$formHelper = new FormHelper($form);

return $formHelper->formStart($method, $action, $enctype, $options);
}

public function formEnd(FormInterface $form): string
{
$formHelper = new FormHelper($form);

return $formHelper->formEnd();
}

public function field(FormInterface $form, string $type, string $field, ?array $options = []): string
{
$formHelper = new FormHelper($form);
$validOptions = ['style', 'class', 'id', 'value', 'maxlength', 'required', 'data-'];

foreach (array_keys($options) as $option) {
$isInvalid = true;
foreach ($validOptions as $validOption) {
if (strpos($option, $validOption) !== false) {
$isInvalid = false;
}
}
if ($isInvalid) {
throw new InvalidArgumentException(
'Only following options are allowed: ' . implode(', ', $validOptions)
);
}
}

return $formHelper->formField($type, $field, $options);
}
}
141 changes: 141 additions & 0 deletions tests/Helper/Twig/NcFormExtensionTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
<?php

namespace Naucon\Form\Tests\Helper\Twig;

use Naucon\Form\Configuration;
use Naucon\Form\FormInterface;
use Naucon\Form\Helper\AbstractFormHelperField;
use Naucon\Form\Helper\Twig\NcFormExtension;
use Naucon\Form\Mapper\EntityContainer;
use Naucon\Form\Mapper\Property;
use Naucon\Utility\Iterator;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Twig\TwigFunction;

class NcFormExtensionTest extends TestCase
{

/**
* @var FormInterface&MockObject
*/
private $form;
/**
* @var Configuration&MockObject
*/
private $configuration;
/**
* @var Iterator&MockObject
*/
private $iterator;
/**
* @var AbstractFormHelperField&MockObject
*/
private $formHelperField;
/**
* @var Property&MockObject
*/
private $property;
/**
* @var EntityContainer&MockObject
*/
private $entityContainer;

public function testFormEnd()
{
$extension = $this->createExtension();
$this->configureMocks();

$html = $extension->formEnd($this->form);
$this->assertStringContainsString('</form>', $html);

}

public function testField()
{
$extension = $this->createExtension();
$this->configureMocks();
$this->iterator
->expects($this->once())
->method('current')
->willReturn($this->formHelperField);

$this->formHelperField
->expects($this->once())
->method('getProperty')
->willReturn($this->property);

$this->property
->expects($this->once())
->method('getEntityContainer')
->willReturn($this->entityContainer);

$this->entityContainer
->expects($this->once())
->method('hasError')
->willReturn(false);

$html = $extension->field($this->form, 'text', 'my-name', ['class' => 'css-class', 'data-foo' => 'some-attribute']);
$this->assertStringContainsString('<input type="text"', $html);
$this->assertStringContainsString('class="css-class"', $html);
$this->assertStringContainsString('data-foo="some-attribute"', $html);

}

public function testGetFunctions()
{
$extension = $this->createExtension();
$functions = $extension->getFunctions();

$this->assertCount(3, $functions);
$this->assertContainsOnlyInstancesOf(TwigFunction::class, $functions);


}

public function testFormStart()
{
$extension = $this->createExtension();
$this->configureMocks();

$html = $extension->formStart($this->form);
$this->assertStringContainsString('<form', $html);
$this->assertStringContainsString('method="post"', $html);

}

protected function createExtension(): NcFormExtension
{
return new NcFormExtension();
}

protected function configureMocks()
{
$this->form
->expects($this->once())
->method('getConfiguration')
->willReturn($this->configuration);

$this->form
->expects($this->once())
->method('getEntityContainerIterator')
->willReturn($this->iterator);

$this->configuration
->expects($this->once())
->method('get')
->with('csrf_protection')
->willReturn(false);
}

protected function setUp(): void
{
parent::setUp();
$this->form = $this->createMock(FormInterface::class);
$this->configuration = $this->createMock(Configuration::class);
$this->iterator = $this->createMock(Iterator::class);
$this->formHelperField = $this->createMock(AbstractFormHelperField::class);
$this->property = $this->createMock(Property::class);
$this->entityContainer = $this->createMock(EntityContainer::class);
}
}

0 comments on commit 4dadff3

Please sign in to comment.