Call to undefined method Nette\Forms\Control
IJVo opened this issue · 9 comments
Since version 1.2.2 it reports these errors:
Call to an undefined method Nette\Forms\Control::getOption().
Call to an undefined method Nette\Forms\Control::getControlPrototype().
Call to an undefined method Nette\Forms\Control::getContainerPrototype().
Call to an undefined method Nette\Forms\Control::getItemLabelPrototype().
Please show the piece of code that reports this.
/cc @lulco
<?php declare(strict_types = 1);
namespace App\Components\Forms;
use Nette;
use Nette\Application\UI\Form;
use Nette\Forms\Rendering\DefaultFormRenderer;
final class FormFactory
{
public function create(): Form
{
return new Form();
}
public static function makeBootstrap4(Form $form): void
{
/** @var DefaultFormRenderer $renderer */
$renderer = $form->getRenderer();
$renderer->wrappers['controls']['container'] = null;
$renderer->wrappers['pair']['container'] = 'div class="form-group"';
$renderer->wrappers['pair']['.error'] = 'has-danger';
$renderer->wrappers['control']['container'] = '';
$renderer->wrappers['label']['container'] = '';
$renderer->wrappers['control']['description'] = 'span class=form-text';
$renderer->wrappers['control']['errorcontainer'] = 'span class=form-control-feedback';
$renderer->wrappers['control']['.error'] = 'is-invalid';
$usedPrimary = false;
foreach ($form->getControls() as $control) {
$type = $control->getOption('type');
if ($type === 'button') {
$control->getControlPrototype()->addClass($usedPrimary === false ? 'btn btn-primary' : 'btn btn-secondary');
$usedPrimary = true;
} elseif (in_array($type, ['text', 'textarea', 'select'], true)) {
$control->getControlPrototype()->addClass('form-control');
} elseif ($type === 'file') {
$control->getControlPrototype()->addClass('form-control-file');
} elseif (in_array($type, ['checkbox', 'radio'], true)) {
if ($control instanceof Nette\Forms\Controls\Checkbox) {
$control->getLabelPrototype()->addClass('form-check-label');
} else {
$control->getItemLabelPrototype()->addClass('form-check-label');
}
$control->getControlPrototype()->addClass('form-check-input');
$control->getContainerPrototype()->setName('div')->addClass('form-check');
}
}
}
}
------ ---------------------------------------------------------------------------
Line app/Components/Forms/FormFactory.php
------ ---------------------------------------------------------------------------
33 Call to an undefined method Nette\Forms\Control::getOption().
36 Call to an undefined method Nette\Forms\Control::getControlPrototype().
40 Call to an undefined method Nette\Forms\Control::getControlPrototype().
43 Call to an undefined method Nette\Forms\Control::getControlPrototype().
49 Call to an undefined method Nette\Forms\Control::getItemLabelPrototype().
52 Call to an undefined method Nette\Forms\Control::getControlPrototype().
53 Call to an undefined method Nette\Forms\Control::getContainerPrototype().
------ ---------------------------------------------------------------------------
see https://github.com/nette/forms/blob/v3.1.10/examples/bootstrap4-rendering.php
Well, it's correct.
You can add any Control to your Form. Your code use wrong assumption that all controls are BaseControl (I guess).
What happens if you create some custom control (implementung Control interface) and use this renderer? It will fail because method getOption() will not be implemented.
ping @dg
I'm reverting the change for now. It was more precise, yes, but the practical value was questionable. The marked code was most likely fine but static analysis can't understand that.
I thought that's what are stubs about - to be more precise. Now the type of Control is mixed...
I understand that change cause some errors in wild, but it just did what phpstan do - protect users from errors.
Potential error is still there, it just isn't reported by phpstan.
Marked code would be correct (and analysed without errors) if instanceof would be used instead of comparing $type
@lulco How should code of FormFactory kook?
Like I said:
foreach ($form->getControls() as $control) {
if ($control instanceof \Nette\Forms\Controls\Button) {
$control->getControlPrototype()->addClass($usedPrimary === false ? 'btn btn-primary' : 'btn btn-secondary');
$usedPrimary = true;
}
// ...
}
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.