Skip to content

Commit

Permalink
Container::getValues($obj) mapping to PHP 8 constructor
Browse files Browse the repository at this point in the history
  • Loading branch information
dg committed Oct 6, 2021
1 parent 3592166 commit 8945195
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 2 deletions.
1 change: 1 addition & 0 deletions ecs.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@
$parameters->set('skip', [
'fixtures/*',
'tests/Forms/Container.values.mapping.74.phpt',
'tests/Forms/Container.values.mapping-constructor.phpt',
]);
};
14 changes: 12 additions & 2 deletions src/Forms/Container.php
Original file line number Diff line number Diff line change
Expand Up @@ -138,13 +138,19 @@ public function getUnsafeValues($returnType, array $controls = null)
{
if (is_object($returnType)) {
$obj = $returnType;
$rc = new \ReflectionClass($obj);

} else {
$returnType = ($returnType ?? $this->mappedType ?? ArrayHash::class);
$obj = $returnType === self::ARRAY ? new \stdClass : new $returnType;
$rc = new \ReflectionClass($returnType === self::ARRAY ? \stdClass::class : $returnType);
if ($rc->hasMethod('__construct') && $rc->getMethod('__construct')->getNumberOfRequiredParameters()) {
$obj = new \stdClass;
$useConstructor = true;
} else {
$obj = $rc->newInstance();
}
}

$rc = new \ReflectionClass($obj);
foreach ($this->getComponents() as $name => $control) {
$allowed = $controls === null || in_array($control, $controls, true);
$name = (string) $name;
Expand All @@ -163,6 +169,10 @@ public function getUnsafeValues($returnType, array $controls = null)
}
}

if (isset($useConstructor)) {
return new $returnType(...(array) $obj);
}

return $returnType === self::ARRAY
? (array) $obj
: $obj;
Expand Down
103 changes: 103 additions & 0 deletions tests/Forms/Container.values.mapping-constructor.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
<?php

/**
* @phpVersion 8.0
*/

declare(strict_types=1);

use Nette\Forms\Form;
use Tester\Assert;


require __DIR__ . '/../bootstrap.php';


class FormDataConstruct
{
public function __construct(
public string $title,
public FormFirstLevelConstruct $first,
...$extra,
) {
}
}


class FormFirstLevelConstruct
{
public function __construct(
public string $name,
public ?FormSecondLevelConstruct $second = null,
public int|null $age = null,
) {
}
}


class FormSecondLevelConstruct
{
public function __construct(
public string $city,
) {
}
}


function hydrate(string $class, array $data)
{
return new $class(...$data);
}


function createForm(): Form
{
$form = new Form;
$form->addText('title');

$first = $form->addContainer('first');
$first->addText('name');
$first->addInteger('age');

$second = $first->addContainer('second');
$second->addText('city');
return $form;
}


test('getValues(...arguments...)', function () {
$form = createForm();

$form->setValues([
'title' => 'new1',
'first' => [
'name' => 'new2',
],
]);

Assert::equal(new FormDataConstruct(
title: 'new1',
first: new FormFirstLevelConstruct(
name: 'new2',
age: null,
second: new FormSecondLevelConstruct(
city: '',
),
),
), $form->getValues(FormDataConstruct::class));

$form->setMappedType(FormDataConstruct::class);
$form['first']->setMappedType(FormFirstLevelConstruct::class);
$form['first-second']->setMappedType(FormSecondLevelConstruct::class);

Assert::equal(new FormDataConstruct(
title: 'new1',
first: new FormFirstLevelConstruct(
name: 'new2',
age: null,
second: new FormSecondLevelConstruct(
city: '',
),
),
), $form->getValues());
});

0 comments on commit 8945195

Please sign in to comment.