Skip to content

Commit d311fdf

Browse files
committed
phpstan level 7
1 parent 738afd2 commit d311fdf

22 files changed

Lines changed: 119 additions & 65 deletions

phpstan-baseline.neon

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -384,12 +384,6 @@ parameters:
384384
count: 1
385385
path: src/Forms/Rules.php
386386

387-
-
388-
message: '#^Call to function is_callable\(\) with callable\(\)\: mixed will always evaluate to true\.$#'
389-
identifier: function.alreadyNarrowedType
390-
count: 1
391-
path: src/Forms/Rules.php
392-
393387
-
394388
message: '#^Method Nette\\Forms\\Rules\:\:addCondition\(\) has parameter \$validator with no signature specified for callable\.$#'
395389
identifier: missingType.callable

phpstan.neon

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
parameters:
2-
level: 6
2+
level: 7
33

44
paths:
55
- src

src/Bridges/FormsLatte/Runtime.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ public static function renderFormEnd(Form $form, bool $withTags = true): string
5858
{
5959
$s = '';
6060
if ($form->isMethod('get')) {
61-
foreach (preg_split('#[;&]#', (string) parse_url($form->getElementPrototype()->action, PHP_URL_QUERY), -1, PREG_SPLIT_NO_EMPTY) as $param) {
61+
$params = preg_split('#[;&]#', (string) parse_url($form->getElementPrototype()->action, PHP_URL_QUERY), -1, PREG_SPLIT_NO_EMPTY);
62+
foreach ($params ?: [] as $param) {
6263
$parts = explode('=', $param, 2);
6364
$name = urldecode($parts[0]);
6465
$prefix = explode('[', $name, 2)[0];
@@ -84,6 +85,7 @@ public static function item(object|string|int $item, object $global): object
8485
if (is_object($item)) {
8586
return $item;
8687
}
88+
8789
$form = end($global->formsStack) ?: throw new \LogicException('Form declaration is missing, did you use {form} or <form n:name> tag?');
8890
return $form[$item];
8991
}

src/Forms/Blueprint.php

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -156,14 +156,15 @@ public function getOption(mixed $key): mixed
156156

157157
ob_start();
158158
$dummyForm->render('end');
159-
$end = ob_get_clean();
159+
$end = (string) ob_get_clean();
160160
}
161161

162162
ob_start();
163163
$dummyForm->render();
164-
$body = ob_get_clean();
164+
$body = (string) ob_get_clean();
165165

166-
$body = str_replace($dummyForm->getElementPrototype()->startTag(), '<form n:name="' . $form->getName() . '">', $body);
166+
$startTag = $dummyForm->getElementPrototype()->startTag();
167+
$body = str_replace($startTag ?: '', '<form n:name="' . $form->getName() . '">', $body);
167168
$body = str_replace($end ?? '', '</form>', $body);
168169
return $body;
169170
}
@@ -175,7 +176,7 @@ public function generateDataClass(
175176
?string $baseName = null,
176177
): string
177178
{
178-
$baseName ??= preg_replace('~Form$~', '', ucwords((string) $container->getName()));
179+
$baseName ??= preg_replace('~Form$~', '', ucwords((string) $container->getName())) ?: '';
179180
$nextCode = '';
180181
$props = [];
181182
foreach ($container->getComponents() as $name => $input) {
@@ -208,7 +209,7 @@ public function generateDataClass(
208209
$type = '?' . $type;
209210
}
210211
} elseif ($input instanceof Container) {
211-
$type = $baseName . ucwords($name);
212+
$type = $baseName . ucwords((string) $name);
212213
$nextCode .= $this->generateDataClass($input, $propertyPromotion, $type);
213214
$type .= self::ClassNameSuffix;
214215
} else {

src/Forms/Container.php

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ public function getValues(string|object|bool|null $returnType = null, ?array $co
121121
$returnType = self::Array;
122122
}
123123

124+
/** @var list<Control>|null $controls */
124125
return $this->getUntrustedValues($returnType, $controls);
125126
}
126127

@@ -140,7 +141,9 @@ public function getUntrustedValues(string|object|null $returnType = null, ?array
140141

141142
} else {
142143
$returnType ??= $this->mappedType ?? ArrayHash::class;
143-
$rc = new \ReflectionClass($returnType === self::Array ? \stdClass::class : $returnType);
144+
/** @var class-string $rcClass */
145+
$rcClass = $returnType === self::Array ? \stdClass::class : $returnType;
146+
$rc = new \ReflectionClass($rcClass);
144147
$constructor = $rc->hasMethod('__construct') ? $rc->getMethod('__construct') : null;
145148
if ($constructor?->getNumberOfRequiredParameters()) {
146149
$resultObj = new \stdClass;
@@ -166,23 +169,28 @@ public function getUntrustedValues(string|object|null $returnType = null, ?array
166169
$resultObj->$name = Helpers::tryEnumConversion($control->getValue(), $property);
167170

168171
} elseif ($control instanceof self) {
172+
/** @var class-string|'array'|null $type */
169173
$type = $returnType === self::Array && !$control->mappedType
170174
? self::Array
171175
: ($property ? Helpers::getSingleType($property) : null);
172176
$resultObj->$name = $control->getUntrustedValues($type, $allowed ? null : $controls);
173177
}
174178
}
175179

176-
return match (true) {
177-
isset($constructor) => new $returnType(...(array) $resultObj),
178-
$returnType === self::Array => (array) $resultObj,
179-
default => $resultObj,
180-
};
180+
if ($returnType === self::Array) {
181+
return (array) $resultObj;
182+
} elseif (isset($constructor)) {
183+
/** @var class-string $returnType */
184+
return new $returnType(...(array) $resultObj);
185+
}
186+
187+
return $resultObj;
181188
}
182189

183190

184191
/**
185192
* @deprecated use getUntrustedValues()
193+
* @param class-string|'array'|object|null $returnType
186194
* @param ?list<Control> $controls
187195
* @return object|array<string, mixed>
188196
*/
@@ -242,6 +250,7 @@ public function validate(?array $controls = null): void
242250

243251
foreach ($this->onValidate as $handler) {
244252
$params = Nette\Utils\Callback::toReflection($handler)->getParameters();
253+
/** @var list<?class-string> $types */
245254
$types = array_map(Helpers::getSingleType(...), $params);
246255
$args = isset($types[0]) && !$this instanceof $types[0]
247256
? [$this->getUntrustedValues($types[0])]

src/Forms/Controls/BaseControl.php

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,8 @@ public function getControl()
256256
public function getLabel(string|Stringable|null $caption = null)
257257
{
258258
$label = clone $this->label;
259-
$label->for = $this->getHtmlId();
259+
$htmlId = $this->getHtmlId();
260+
$label->for = is_string($htmlId) ? $htmlId : null;
260261
$caption ??= $this->caption;
261262
$translator = $this->getForm()->getTranslator();
262263
$label->setText($translator && !$caption instanceof Nette\HtmlStringable ? $translator->translate($caption) : $caption);
@@ -266,13 +267,15 @@ public function getLabel(string|Stringable|null $caption = null)
266267

267268
public function getControlPart(): ?Html
268269
{
269-
return $this->getControl();
270+
$control = $this->getControl();
271+
return $control instanceof Html ? $control : null;
270272
}
271273

272274

273275
public function getLabelPart(): ?Html
274276
{
275-
return $this->getLabel();
277+
$label = $this->getLabel();
278+
return $label instanceof Html ? $label : null;
276279
}
277280

278281

@@ -299,7 +302,7 @@ public function getLabelPrototype(): Html
299302
*/
300303
public function setHtmlId(string|bool|null $id): static
301304
{
302-
$this->control->id = $id;
305+
$this->control->id = is_string($id) ? $id : null;
303306
return $this;
304307
}
305308

@@ -374,7 +377,7 @@ public function getTranslator(): ?Nette\Localization\Translator
374377
: null;
375378
}
376379

377-
return $this->translator;
380+
return $this->translator ?: null;
378381
}
379382

380383

@@ -486,7 +489,9 @@ public function validate(): void
486489
*/
487490
public function addError(string|Stringable $message, bool $translate = true): void
488491
{
489-
$this->errors[] = $translate ? $this->translate($message) : $message;
492+
$translated = $translate ? $this->translate($message) : $message;
493+
assert(is_string($translated) || $translated instanceof Stringable);
494+
$this->errors[] = (string) $translated;
490495
}
491496

492497

src/Forms/Controls/Checkbox.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,13 +71,17 @@ public function getLabel(string|Stringable|null $caption = null): Html|string|nu
7171

7272
public function getControlPart(): Html
7373
{
74-
return parent::getControl()->checked($this->value);
74+
$control = parent::getControl();
75+
assert($control instanceof Html);
76+
return $control->checked($this->value);
7577
}
7678

7779

7880
public function getLabelPart(): Html
7981
{
80-
return parent::getLabel();
82+
$label = parent::getLabel();
83+
assert($label instanceof Html);
84+
return $label;
8185
}
8286

8387

src/Forms/Controls/CheckboxList.php

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,15 @@ public function loadHttpData(): void
4545
$data = $this->getForm()->getHttpData(Nette\Forms\Form::DataText, substr($this->getHtmlName(), 0, -2));
4646
$data = $data === null
4747
? $this->getHttpData(Nette\Forms\Form::DataText)
48-
: explode(',', $data);
49-
$this->value = array_keys(array_flip($data));
48+
: (is_string($data) ? explode(',', $data) : []);
49+
$this->value = array_keys(array_flip((array) $data));
5050
}
5151

5252

5353
public function getControl(): Html
5454
{
5555
$input = parent::getControl();
56+
assert($input instanceof Html);
5657
$items = $this->getItems();
5758
if (!$items) {
5859
return Html::el();
@@ -76,14 +77,18 @@ public function getControl(): Html
7677

7778
public function getLabel(string|Stringable|null $caption = null): Html
7879
{
79-
return parent::getLabel($caption)->for(null);
80+
$label = parent::getLabel($caption);
81+
assert($label instanceof Html);
82+
return $label->for(null);
8083
}
8184

8285

8386
public function getControlPart(int|string|null $key = null): Html
8487
{
8588
$key = key([(string) $key => null]);
86-
return parent::getControl()->addAttributes([
89+
$control = parent::getControl();
90+
assert($control instanceof Html);
91+
return $control->addAttributes([
8792
'id' => $this->getHtmlId() . '-' . $key,
8893
'checked' => in_array($key, (array) $this->value, strict: true),
8994
'disabled' => is_array($this->disabled) ? isset($this->disabled[$key]) : $this->disabled,

src/Forms/Controls/ColorPicker.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,9 @@ public function loadHttpData(): void
5353

5454
public function getControl(): Nette\Utils\Html
5555
{
56-
return parent::getControl()->addAttributes([
56+
$control = parent::getControl();
57+
assert($control instanceof Nette\Utils\Html);
58+
return $control->addAttributes([
5759
'type' => 'color',
5860
'value' => $this->value,
5961
]);

src/Forms/Controls/CsrfProtection.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@ public function __construct(string|Stringable|null $errorMessage = null)
3737

3838
$this->monitor(Presenter::class, function (Presenter $presenter): void {
3939
if (!$this->session) {
40-
$this->session = $presenter->getSession();
40+
$session = $presenter->getSession();
41+
assert($session instanceof Nette\Http\Session);
42+
$this->session = $session;
4143
$this->session->start();
4244
}
4345
});

0 commit comments

Comments
 (0)