Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions asset/css/primary-submit-btn-duplicate.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
Automatically set CSS class for duplicated submit buttons
used for implicit form submission that should be invisible
and not take up any space. `display: none` is not an option,
because at least Safari will then ignore the element completely
when submitting a form.
*/
.primary-submit-btn-duplicate {
Comment thread
TAINCER marked this conversation as resolved.
border: 0;
height: 0;
margin: 0;
padding: 0;
visibility: hidden;
width: 0;
position: absolute;
}
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
},
"autoload-dev": {
"psr-4": {
"ipl\\Tests\\Web\\": "tests"
"ipl\\Tests\\Web\\": "tests",
"ipl\\Tests\\Html\\": "vendor/ipl/html/tests"
}
},
"require": {
Expand Down
41 changes: 41 additions & 0 deletions src/Compat/CompatForm.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@

namespace ipl\Web\Compat;

use ipl\Html\Contract\FormSubmitElement;
use ipl\Html\Form;
use ipl\Html\FormElement\SubmitElement;
use ipl\Html\HtmlDocument;
use ipl\Html\HtmlString;
use ipl\I18n\Translation;
use ipl\Web\FormDecorator\IcingaFormDecorator;

Expand All @@ -12,6 +16,27 @@ class CompatForm extends Form

protected $defaultAttributes = ['class' => 'icinga-form icinga-controls'];

/**
* Render the content of the element to HTML
Comment thread
lippserd marked this conversation as resolved.
*
* A duplicate of the primary submit button is being prepended if there is more than one present
Comment thread
TAINCER marked this conversation as resolved.
*
* @return string
*/
public function renderContent(): string
Comment thread
TAINCER marked this conversation as resolved.
{
if (count($this->submitElements) > 1) {
return (new HtmlDocument())
->setHtmlContent(
$this->duplicateSubmitButton($this->submitButton),
new HtmlString(parent::renderContent())
)
->render();
}

return parent::renderContent();
}

public function hasDefaultElementDecorator()
{
if (parent::hasDefaultElementDecorator()) {
Expand All @@ -22,4 +47,20 @@ public function hasDefaultElementDecorator()

return true;
}

/**
* Return a duplicate of the given submit button with the `class` attribute fixed to `primary-submit-btn-duplicate`
*
* @param FormSubmitElement $originalSubmitButton
*
* @return SubmitElement
*/
public function duplicateSubmitButton(FormSubmitElement $originalSubmitButton): SubmitElement
{
$attributes = (clone $originalSubmitButton->getAttributes())
->set('class', 'primary-submit-btn-duplicate');
$attributes->remove('id');

return new SubmitElement($originalSubmitButton->getName(), $attributes);
}
}
97 changes: 97 additions & 0 deletions tests/Compat/CompatFormTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<?php

Comment thread
TAINCER marked this conversation as resolved.
namespace ipl\Tests\Web\Compat;

use ipl\Html\FormElement\SubmitElement;
use ipl\Tests\Html\TestCase;
use ipl\Web\Compat\CompatForm;

class CompatFormTest extends TestCase
{
/** @var CompatForm */
private $form;

protected function setUp(): void
{
$this->form = new CompatForm();
}

public function testDuplicateSubmitButtonApplied(): void
{
$this->form->addElement('submit', 'submitCreate');
$this->form->addElement('submit', 'submitDelete');

$expected = <<<'HTML'
<form class="icinga-form icinga-controls" method="POST">
<input class="primary-submit-btn-duplicate" name="submitCreate" type="submit" value="submitCreate"/>
<div class="control-group form-controls">
<input class="btn-primary" name="submitCreate" type="submit" value="submitCreate"/>
</div>
<div class="control-group form-controls">
<input class="btn-primary" name="submitDelete" type="submit" value="submitDelete"/>
</div>
</form>
HTML;

$this->assertHtml($expected, $this->form);
}

public function testDuplicateSubmitButtonOmitted(): void
{
$this->form->addElement('submit', 'submitCreate');

$expected = <<<'HTML'
<form class="icinga-form icinga-controls" method="POST">
<div class="control-group form-controls">
<input class="btn-primary" name="submitCreate" type="submit" value="submitCreate"/>
</div>
</form>
HTML;

$this->assertHtml($expected, $this->form);
}

public function testDuplicateSubmitButtonAddedOnlyOnce(): void
{
$this->form->addElement('submit', 'submitCreate', ['id' => 'submit_id']);
$this->form->addElement('submit', 'submitDelete');

$expected = <<<'HTML'
<form class="icinga-form icinga-controls" method="POST">
<input class="primary-submit-btn-duplicate" name="submitCreate" type="submit" value="submitCreate"/>
<div class="control-group form-controls">
<input id="submit_id" class="btn-primary" name="submitCreate" type="submit" value="submitCreate"/>
</div>
<div class="control-group form-controls">
<input class="btn-primary" name="submitDelete" type="submit" value="submitDelete"/>
</div>
</form>
HTML;

// Call render twice to ensure that the submit button is only prepended once.
$this->form->render();
Comment thread
TAINCER marked this conversation as resolved.
$this->assertHtml($expected, $this->form);
}

public function testDuplicateSubmitButtonRespectsOriginalAttributes(): void
{
$submitButton = new SubmitElement('test_submit', [
'class' => 'autosubmit',
'formnovalidate' => true
]);

$prefixButton = $this->form->duplicateSubmitButton($submitButton);

// Name should stay the same
$this->assertSame($submitButton->getName(), 'test_submit');
$this->assertSame($prefixButton->getName(), 'test_submit');

// Added attributes should stay the same
$this->assertSame($submitButton->getAttributes()->get('formnovalidate')->getValue(), true);
$this->assertSame($prefixButton->getAttributes()->get('formnovalidate')->getValue(), true);

// Class attribute should change to `primary-submit-btn-duplicate`
$this->assertSame($submitButton->getAttributes()->get('class')->getValue(), 'autosubmit');
$this->assertSame($prefixButton->getAttributes()->get('class')->getValue(), 'primary-submit-btn-duplicate');
}
}