Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve type inference for element attributes #245

Merged
merged 7 commits into from
Nov 17, 2023
Merged
Show file tree
Hide file tree
Changes from 3 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
130 changes: 15 additions & 115 deletions psalm-baseline.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<files psalm-version="5.13.0@a0a9c27630bcf8301ee78cb06741d2907d8c9fef">
<files psalm-version="5.15.0@5c774aca4746caf3d239d9c8cadb9f882ca29352">
<file src="src/Annotation/AbstractBuilder.php">
<InvalidArrayOffset>
<code><![CDATA[$params['elementSpec']['spec']['type']]]></code>
Expand Down Expand Up @@ -552,9 +552,6 @@
<code><![CDATA[$inputSpec['validators']]]></code>
<code><![CDATA[$inputSpec['validators']]]></code>
</PossiblyUndefinedArrayOffset>
<UndefinedInterfaceMethod>
<code>getValidator</code>
</UndefinedInterfaceMethod>
</file>
<file src="test/Element/MonthSelectTest.php">
<PossiblyInvalidArrayAccess>
Expand Down Expand Up @@ -601,6 +598,14 @@
</UndefinedMethod>
</file>
<file src="test/Element/MultiCheckboxTest.php">
<InvalidArgument>
<code><![CDATA[[
'options' => [
'a' => 'A',
'b' => 'B',
],
]]]></code>
</InvalidArgument>
<PossiblyInvalidArrayAccess>
<code><![CDATA[$inputSpec['validators'][0]]]></code>
<code><![CDATA[$inputSpec['validators'][0]]]></code>
Expand Down Expand Up @@ -689,6 +694,12 @@
</UndefinedInterfaceMethod>
</file>
<file src="test/Element/SelectTest.php">
<InvalidArgument>
<code><![CDATA[[
'multiple' => true,
'options' => $valueOptions,
]]]></code>
</InvalidArgument>
<PossiblyInvalidArrayAccess>
<code><![CDATA[$inputSpec['validators'][0]]]></code>
<code><![CDATA[$inputSpec['validators'][0]]]></code>
Expand Down Expand Up @@ -1101,9 +1112,6 @@
<InvalidArgument>
<code>$element</code>
</InvalidArgument>
<PossiblyNullArgument>
<code><![CDATA[$element->getAttribute($attribute)]]></code>
</PossiblyNullArgument>
</file>
<file src="test/View/Helper/FormCaptchaTest.php">
<PossiblyFalseArgument>
Expand All @@ -1120,28 +1128,10 @@
<code>setView</code>
</DeprecatedMethod>
</file>
<file src="test/View/Helper/FormColorTest.php">
<PossiblyNullArgument>
<code><![CDATA[$element->getAttribute($attribute)]]></code>
</PossiblyNullArgument>
</file>
<file src="test/View/Helper/FormDateTest.php">
<PossiblyNullArgument>
<code><![CDATA[$element->getAttribute($attribute)]]></code>
</PossiblyNullArgument>
</file>
<file src="test/View/Helper/FormDateTimeLocalTest.php">
<PossiblyNullArgument>
<code><![CDATA[$element->getAttribute($attribute)]]></code>
</PossiblyNullArgument>
</file>
<file src="test/View/Helper/FormDateTimeTest.php">
<DeprecatedClass>
<code>new FormDateTimeHelper()</code>
</DeprecatedClass>
<PossiblyNullArgument>
<code><![CDATA[$element->getAttribute($attribute)]]></code>
</PossiblyNullArgument>
</file>
<file src="test/View/Helper/FormElementTest.php">
<PossiblyInvalidMethodCall>
Expand All @@ -1154,104 +1144,14 @@
<code>getHash</code>
</UndefinedInterfaceMethod>
</file>
<file src="test/View/Helper/FormEmailTest.php">
<PossiblyNullArgument>
<code><![CDATA[$element->getAttribute($attribute)]]></code>
</PossiblyNullArgument>
</file>
<file src="test/View/Helper/FormFileTest.php">
<PossiblyNullArgument>
<code><![CDATA[$element->getAttribute($attribute)]]></code>
</PossiblyNullArgument>
</file>
<file src="test/View/Helper/FormHiddenTest.php">
<PossiblyNullArgument>
<code><![CDATA[$element->getAttribute($attribute)]]></code>
</PossiblyNullArgument>
</file>
<file src="test/View/Helper/FormImageTest.php">
<PossiblyNullArgument>
<code><![CDATA[$element->getAttribute($attribute)]]></code>
</PossiblyNullArgument>
</file>
<file src="test/View/Helper/FormInputTest.php">
<PossiblyNullArgument>
<code><![CDATA[$element->getAttribute($attribute)]]></code>
</PossiblyNullArgument>
</file>
<file src="test/View/Helper/FormLabelTest.php">
<InvalidArgument>
<code>$element</code>
</InvalidArgument>
</file>
<file src="test/View/Helper/FormMonthTest.php">
<PossiblyNullArgument>
<code><![CDATA[$element->getAttribute($attribute)]]></code>
</PossiblyNullArgument>
</file>
<file src="test/View/Helper/FormNumberTest.php">
<PossiblyNullArgument>
<code><![CDATA[$element->getAttribute($attribute)]]></code>
</PossiblyNullArgument>
</file>
<file src="test/View/Helper/FormPasswordTest.php">
<PossiblyNullArgument>
<code><![CDATA[$element->getAttribute($attribute)]]></code>
</PossiblyNullArgument>
</file>
<file src="test/View/Helper/FormRangeTest.php">
<PossiblyNullArgument>
<code><![CDATA[$element->getAttribute($attribute)]]></code>
</PossiblyNullArgument>
</file>
<file src="test/View/Helper/FormResetTest.php">
<PossiblyNullArgument>
<code><![CDATA[$element->getAttribute($attribute)]]></code>
</PossiblyNullArgument>
</file>
<file src="test/View/Helper/FormRowTest.php">
<PossiblyInvalidFunctionCall>
<code>$escapeHelper($label)</code>
</PossiblyInvalidFunctionCall>
</file>
<file src="test/View/Helper/FormSearchTest.php">
<PossiblyNullArgument>
<code><![CDATA[$element->getAttribute($attribute)]]></code>
</PossiblyNullArgument>
</file>
<file src="test/View/Helper/FormSubmitTest.php">
<PossiblyNullArgument>
<code><![CDATA[$element->getAttribute($attribute)]]></code>
</PossiblyNullArgument>
</file>
<file src="test/View/Helper/FormTelTest.php">
<PossiblyNullArgument>
<code><![CDATA[$element->getAttribute($attribute)]]></code>
</PossiblyNullArgument>
</file>
<file src="test/View/Helper/FormTextTest.php">
<PossiblyNullArgument>
<code><![CDATA[$element->getAttribute($attribute)]]></code>
</PossiblyNullArgument>
</file>
<file src="test/View/Helper/FormTextareaTest.php">
<PossiblyNullArgument>
<code><![CDATA[$element->getAttribute($attribute)]]></code>
</PossiblyNullArgument>
</file>
<file src="test/View/Helper/FormTimeTest.php">
<PossiblyNullArgument>
<code><![CDATA[$element->getAttribute($attribute)]]></code>
</PossiblyNullArgument>
</file>
<file src="test/View/Helper/FormUrlTest.php">
<PossiblyNullArgument>
<code><![CDATA[$element->getAttribute($attribute)]]></code>
</PossiblyNullArgument>
</file>
<file src="test/View/Helper/FormWeekTest.php">
<PossiblyNullArgument>
<code><![CDATA[$element->getAttribute($attribute)]]></code>
</PossiblyNullArgument>
</file>
</files>
41 changes: 15 additions & 26 deletions src/Element.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Traversable;

use function array_key_exists;
use function assert;
use function is_string;

class Element implements
Expand All @@ -17,19 +18,19 @@ class Element implements
InitializableInterface,
LabelAwareInterface
{
/** @var array */
/** @var array<string, scalar|null> */
protected $attributes = [];

/** @var null|string */
protected $label;

/** @var array */
/** @var array<string, scalar|null> */
protected $labelAttributes = [];

/**
* Label specific options
*
* @var array
* @var array<string, mixed>
*/
protected $labelOptions = [];

Expand Down Expand Up @@ -87,7 +88,10 @@ public function setName(string $name)
*/
public function getName(): ?string
{
return $this->getAttribute('name');
$name = $this->getAttribute('name');
assert(is_string($name) || $name === null);

return $name;
}

/**
Expand Down Expand Up @@ -158,12 +162,7 @@ public function setOption(string $key, $value)
return $this;
}

/**
* Set a single element attribute
*
* @param mixed $value
* @return $this
*/
/** @inheritDoc */
public function setAttribute(string $key, $value)
{
// Do not include the value in the list of attributes
Expand All @@ -175,11 +174,7 @@ public function setAttribute(string $key, $value)
return $this;
}

/**
* Retrieve a single element attribute
*
* @return mixed|null
*/
/** @inheritDoc */
public function getAttribute(string $key)
{
if (! isset($this->attributes[$key])) {
Expand Down Expand Up @@ -209,11 +204,7 @@ public function hasAttribute(string $key): bool
}

/**
* Set many attributes at once
*
* Implementation will decide if this will overwrite or merge.
*
* @return $this
* @inheritDoc
* @throws Exception\InvalidArgumentException
*/
public function setAttributes(iterable $arrayOrTraversable)
Expand All @@ -224,9 +215,7 @@ public function setAttributes(iterable $arrayOrTraversable)
return $this;
}

/**
* Retrieve all attributes at once
*/
/** @inheritDoc */
public function getAttributes(): array
{
return $this->attributes;
Expand All @@ -235,7 +224,7 @@ public function getAttributes(): array
/**
* Remove many attributes at once
*
* @param array $keys
* @param list<string> $keys
* @return $this
*/
public function removeAttributes(array $keys)
Expand Down Expand Up @@ -307,7 +296,7 @@ public function getLabel(): ?string
/**
* Set the attributes to use with the label
*
* @param array $labelAttributes
* @param array<string, mixed> $labelAttributes
* @return $this
*/
public function setLabelAttributes(array $labelAttributes)
Expand All @@ -319,7 +308,7 @@ public function setLabelAttributes(array $labelAttributes)
/**
* Get the attributes to use with the label
*
* @return array
* @return array<string, mixed>
*/
public function getLabelAttributes(): array
{
Expand Down
12 changes: 6 additions & 6 deletions src/Element/AbstractDateTime.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,41 +106,41 @@ protected function getValidators(): array

if (
isset($this->attributes['min'])
&& $this->valueIsValidDateTimeFormat($this->attributes['min'])
&& $this->valueIsValidDateTimeFormat((string) $this->attributes['min'])
) {
$validators[] = new GreaterThanValidator([
'min' => $this->attributes['min'],
'inclusive' => true,
]);
} elseif (
isset($this->attributes['min'])
&& ! $this->valueIsValidDateTimeFormat($this->attributes['min'])
&& ! $this->valueIsValidDateTimeFormat((string) $this->attributes['min'])
) {
throw new InvalidArgumentException(sprintf(
'%1$s expects "min" to conform to %2$s; received "%3$s"',
__METHOD__,
$this->format,
$this->attributes['min']
(string) $this->attributes['min']
));
}

if (
isset($this->attributes['max'])
&& $this->valueIsValidDateTimeFormat($this->attributes['max'])
&& $this->valueIsValidDateTimeFormat((string) $this->attributes['max'])
) {
$validators[] = new LessThanValidator([
'max' => $this->attributes['max'],
'inclusive' => true,
]);
} elseif (
isset($this->attributes['max'])
&& ! $this->valueIsValidDateTimeFormat($this->attributes['max'])
&& ! $this->valueIsValidDateTimeFormat((string) $this->attributes['max'])
) {
throw new InvalidArgumentException(sprintf(
'%1$s expects "max" to conform to %2$s; received "%3$s"',
__METHOD__,
$this->format,
$this->attributes['max']
(string) $this->attributes['max']
));
}
if (
Expand Down
6 changes: 1 addition & 5 deletions src/Element/Button.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,7 @@

class Button extends Element
{
/**
* Seed attributes
*
* @var array
*/
/** @var array<string, scalar|null> */
protected $attributes = [
'type' => 'button',
];
Expand Down
6 changes: 1 addition & 5 deletions src/Element/Checkbox.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,7 @@

class Checkbox extends Element implements InputProviderInterface
{
/**
* Seed attributes
*
* @var array
*/
/** @var array<string, scalar|null> */
protected $attributes = [
'type' => 'checkbox',
];
Expand Down
6 changes: 1 addition & 5 deletions src/Element/Color.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,7 @@

class Color extends Element implements InputProviderInterface
{
/**
* Seed attributes
*
* @var array
*/
/** @var array<string, scalar|null> */
protected $attributes = [
'type' => 'color',
];
Expand Down
Loading