Skip to content

Commit f39313a

Browse files
committed
fixed PHPStan errors
1 parent a72c106 commit f39313a

9 files changed

Lines changed: 173 additions & 37 deletions

File tree

phpstan-baseline.neon

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
parameters:
2+
ignoreErrors:
3+
-
4+
identifier: arrayValues.list
5+
path: src/Application/MicroPresenter.php

phpstan.neon

Lines changed: 120 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,127 @@
11
parameters:
2-
level: 5
2+
level: 8
33

44
paths:
55
- src
6+
- tests/types
7+
8+
excludePaths:
9+
- src/compatibility.php
10+
- src/compatibility-intf.php
11+
- src/Bridges/ApplicationLatte/UIMacros.php
12+
- src/Bridges/ApplicationLatte/SnippetBridge.php
13+
14+
ignoreErrors:
15+
# Latte 2/3 compatibility - classes/methods/properties differ between versions
16+
-
17+
paths:
18+
- src/Bridges/ApplicationLatte/TemplateFactory.php
19+
- src/Bridges/ApplicationLatte/UIRuntime.php
20+
identifiers:
21+
- class.notFound
22+
- method.notFound
23+
- property.notFound
24+
- arguments.count
25+
26+
# Latte 2 compatibility - TemplateFactory has Latte 2/3 dual support
27+
-
28+
path: src/Bridges/ApplicationLatte/TemplateFactory.php
29+
identifiers:
30+
- if.alwaysFalse
31+
- function.alreadyNarrowedType
32+
- return.type
33+
34+
# Latte 2/3 compatibility - LatteExtension supports both Latte versions
35+
-
36+
path: src/Bridges/ApplicationDI/LatteExtension.php
37+
identifiers:
38+
- class.notFound
39+
- method.notFound
40+
- property.nonObject
41+
- if.alwaysFalse
42+
43+
# Nette DI config access pattern - $config is array|object depending on DI version
44+
-
45+
identifier: property.nonObject
46+
paths:
47+
- src/Bridges/ApplicationDI/ApplicationExtension.php
48+
- src/Bridges/ApplicationDI/RoutingExtension.php
49+
50+
# Intentional pattern for factory methods and fluent interfaces
51+
-
52+
identifier: new.static
53+
54+
# RoutingPanel uses Closure::bindTo to access private methods of RouteList
55+
-
56+
identifier: method.notFound
57+
path: src/Bridges/ApplicationTracy/RoutingPanel.php
58+
59+
# ErrorPresenter: $code is used in the required template file
60+
-
61+
identifier: closure.unusedUse
62+
path: src/Application/ErrorPresenter.php
63+
64+
# UIExtension: Latte filters/functions have varying callable signatures
65+
-
66+
identifier: missingType.callable
67+
path: src/Bridges/ApplicationLatte/UIExtension.php
68+
69+
# DI extensions use Definition::addSetup()/getResultDefinition() from ServiceDefinition subclass
70+
-
71+
identifier: method.notFound
72+
paths:
73+
- src/Bridges/ApplicationDI/ApplicationExtension.php
74+
- src/Bridges/ApplicationDI/LatteExtension.php
75+
76+
# Presenter readonly properties are assigned via injectPrimary() - intentional Nette DI pattern
77+
-
78+
identifier: property.uninitializedReadonly
79+
path: src/Application/UI/Presenter.php
80+
-
81+
identifier: property.readOnlyAssignNotInConstructor
82+
path: src/Application/UI/Presenter.php
83+
84+
# Latte 3 node compatibility - properties/methods may differ between minor versions
85+
-
86+
paths:
87+
- src/Bridges/ApplicationLatte/Nodes/ControlNode.php
88+
- src/Bridges/ApplicationLatte/Nodes/LinkNode.php
89+
- src/Bridges/ApplicationLatte/Nodes/NNonceNode.php
90+
- src/Bridges/ApplicationLatte/Nodes/SnippetNode.php
91+
- src/Bridges/ApplicationLatte/Nodes/LinkBaseNode.php
92+
- src/Bridges/ApplicationLatte/Nodes/IfCurrentNode.php
93+
- src/Bridges/ApplicationLatte/Nodes/TemplatePrintNode.php
94+
identifiers:
95+
- method.nonObject
96+
- property.nonObject
97+
- property.notFound
98+
- argument.type
99+
- variable.undefined
100+
- postDec.type
101+
- generator.valueType
102+
- booleanAnd.leftAlwaysFalse
103+
- function.alreadyNarrowedType
104+
105+
# SnippetRuntime: Latte Block class and Renderable interface compatibility
106+
-
107+
path: src/Bridges/ApplicationLatte/SnippetRuntime.php
108+
identifiers:
109+
- class.notFound
110+
- property.notFound
111+
- method.notFound
112+
- offsetAccess.nonArray
113+
114+
# Nette Forms compatibility - methods differ between versions
115+
-
116+
identifier: method.notFound
117+
path: src/Application/UI/Form.php
118+
119+
# TemplateFactory::createTemplate() accepts optional $class parameter via phpDoc
120+
-
121+
identifier: arguments.count
122+
paths:
123+
- src/Application/UI/Presenter.php
124+
- src/Application/UI/Control.php
6125

7126
includes:
8127
- phpstan-baseline.neon

src/Application/Helpers.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ public static function getClassesAndTraits(string $class): array
3838
{
3939
$res = [$class => $class] + class_parents($class);
4040
$addTraits = function (string $type) use (&$res, &$addTraits): void {
41-
$res += class_uses($type);
42-
foreach (class_uses($type) as $trait) {
41+
$res += class_uses($type) ?: [];
42+
foreach (class_uses($type) ?: [] as $trait) {
4343
$addTraits($trait);
4444
}
4545
};

src/Application/Responses/FileResponse.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ public function send(Nette\Http\IRequest $httpRequest, Nette\Http\IResponse $htt
7474
. '; filename*=utf-8\'\'' . rawurlencode($this->name),
7575
);
7676

77-
$filesize = $length = filesize($this->file);
77+
$filesize = $length = (int) filesize($this->file);
7878
$handle = fopen($this->file, 'r');
7979
if (!$handle) {
8080
throw new Nette\Application\BadRequestException("Cannot open file: '{$this->file}'.");
@@ -109,7 +109,12 @@ public function send(Nette\Http\IRequest $httpRequest, Nette\Http\IResponse $htt
109109

110110
$httpResponse->setHeader('Content-Length', (string) $length);
111111
while (!feof($handle) && $length > 0) {
112-
echo $s = fread($handle, min(4_000_000, $length));
112+
$s = fread($handle, (int) min(4_000_000, $length));
113+
if ($s === false) {
114+
break;
115+
}
116+
117+
echo $s;
113118
$length -= strlen($s);
114119
}
115120

src/Application/UI/AccessPolicy.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ private function checkActions(Attributes\Requires $attribute): void
112112
throw new \LogicException('Requires(actions) used by ' . Reflection::toString($this->element) . ' is allowed only in presenter.');
113113
}
114114

115-
if (!in_array($this->presenter->getAction(), $attribute->actions, strict: true)) {
115+
if (!in_array($this->presenter->getAction(), $attribute->actions ?? [], strict: true)) {
116116
$this->presenter->error("Action '{$this->presenter->getAction()}' is not allowed by " . Reflection::toString($this->element));
117117
}
118118
}
@@ -124,7 +124,7 @@ private function checkHttpMethod(Attributes\Requires $attribute): void
124124
$this->presenter->allowedMethods = []; // bypass Presenter::checkHttpMethod()
125125
}
126126

127-
$allowed = array_map(strtoupper(...), $attribute->methods);
127+
$allowed = array_map(strtoupper(...), $attribute->methods ?? []);
128128
$method = $this->presenter->getHttpRequest()->getMethod();
129129

130130
if ($allowed !== ['*'] && !in_array($method, $allowed, strict: true)) {

src/Application/UI/Component.php

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,8 @@ public function link(string $destination, $args = []): string
298298
$args = func_num_args() < 3 && is_array($args)
299299
? $args
300300
: array_slice(func_get_args(), 1);
301-
return $this->getPresenter()->getLinkGenerator()->link($destination, $args, $this, 'link');
301+
$presenter = $this->getPresenter();
302+
return (string) $presenter->getLinkGenerator()->link($destination, $args, $this, 'link');
302303

303304
} catch (InvalidLinkException $e) {
304305
return $this->getPresenter()->handleInvalidLink($e);
@@ -328,14 +329,15 @@ public function lazyLink(string $destination, $args = []): Link
328329
*/
329330
public function isLinkCurrent(?string $destination = null, $args = []): bool
330331
{
332+
$presenter = $this->getPresenter();
331333
if ($destination !== null) {
332334
$args = func_num_args() < 3 && is_array($args)
333335
? $args
334336
: array_slice(func_get_args(), 1);
335-
$this->getPresenter()->getLinkGenerator()->createRequest($this, $destination, $args, 'test');
337+
$presenter->getLinkGenerator()->createRequest($this, $destination, $args, 'test');
336338
}
337339

338-
return $this->getPresenter()->getLastCreatedRequestFlag('current');
340+
return $presenter->getLastCreatedRequestFlag('current');
339341
}
340342

341343

@@ -353,7 +355,7 @@ public function redirect(string $destination, $args = []): void
353355
: array_slice(func_get_args(), 1);
354356
$presenter = $this->getPresenter();
355357
$presenter->saveGlobalState();
356-
$presenter->redirectUrl($presenter->getLinkGenerator()->link($destination, $args, $this, 'redirect'));
358+
$presenter->redirectUrl((string) $presenter->getLinkGenerator()->link($destination, $args, $this, 'redirect'));
357359
}
358360

359361

@@ -371,7 +373,7 @@ public function redirectPermanent(string $destination, $args = []): void
371373
: array_slice(func_get_args(), 1);
372374
$presenter = $this->getPresenter();
373375
$presenter->redirectUrl(
374-
$presenter->getLinkGenerator()->link($destination, $args, $this, 'redirect'),
376+
(string) $presenter->getLinkGenerator()->link($destination, $args, $this, 'redirect'),
375377
Nette\Http\IResponse::S301_MovedPermanently,
376378
);
377379
}

src/Application/UI/Presenter.php

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -167,14 +167,14 @@ public function getUniqueId(): string
167167

168168
public function isModuleCurrent(string $module): bool
169169
{
170-
$current = Helpers::splitName($this->getName())[0];
170+
$current = Helpers::splitName((string) $this->getName())[0];
171171
return str_starts_with($current . ':', ltrim($module . ':', ':'));
172172
}
173173

174174

175175
public function isForwarded(): bool
176176
{
177-
return $this->forwarded || $this->request->isMethod($this->request::FORWARD);
177+
return $this->forwarded || ($this->request !== null && $this->request->isMethod($this->request::FORWARD));
178178
}
179179

180180

@@ -277,10 +277,11 @@ public function run(Application\Request $request): Application\Response
277277
$this->response = new Responses\VoidResponse;
278278
}
279279

280-
Arrays::invoke($this->onShutdown, $this, $this->response);
281-
$this->shutdown($this->response);
280+
$response = $this->response;
281+
Arrays::invoke($this->onShutdown, $this, $response);
282+
$this->shutdown($response);
282283

283-
return $this->response;
284+
return $response;
284285
}
285286

286287

@@ -402,7 +403,7 @@ final public function isSignalReceiver(
402403
return $this->signalReceiver === $component;
403404
}
404405

405-
return $this->signalReceiver === $component && strcasecmp($signal, $this->signal) === 0;
406+
return $this->signalReceiver === $component && strcasecmp((string) $signal, $this->signal) === 0;
406407
}
407408

408409

@@ -545,12 +546,12 @@ public function findLayoutTemplateFile(): ?string
545546
public function formatLayoutTemplateFiles(): array
546547
{
547548
if (preg_match('#/|\\\#', (string) $this->layout)) {
548-
return [$this->layout];
549+
return [(string) $this->layout];
549550
}
550551

551552
$layout = $this->layout ?: 'layout';
552-
$dir = dirname(static::getReflection()->getFileName());
553-
$levels = substr_count($this->getName(), ':');
553+
$dir = dirname((string) static::getReflection()->getFileName());
554+
$levels = substr_count((string) $this->getName(), ':');
554555
if (!is_dir("$dir/templates")) {
555556
$dir = dirname($origDir = $dir);
556557
if (!is_dir("$dir/templates")) {
@@ -562,7 +563,7 @@ public function formatLayoutTemplateFiles(): array
562563
}
563564
}
564565

565-
[, $presenter] = Helpers::splitName($this->getName());
566+
[, $presenter] = Helpers::splitName((string) $this->getName());
566567
$list = [
567568
"$dir/templates/$presenter/@$layout.latte",
568569
"$dir/templates/$presenter.@$layout.latte",
@@ -581,7 +582,7 @@ public function formatLayoutTemplateFiles(): array
581582
*/
582583
public function formatTemplateFiles(): array
583584
{
584-
$dir = dirname(static::getReflection()->getFileName());
585+
$dir = dirname((string) static::getReflection()->getFileName());
585586
if (!is_dir("$dir/templates")) {
586587
$dir = dirname($origDir = $dir);
587588
if (!is_dir("$dir/templates")) {
@@ -591,7 +592,7 @@ public function formatTemplateFiles(): array
591592
}
592593
}
593594

594-
[, $presenter] = Helpers::splitName($this->getName());
595+
[, $presenter] = Helpers::splitName((string) $this->getName());
595596
return [
596597
"$dir/templates/$presenter/$this->view.latte",
597598
"$dir/templates/$presenter.$this->view.latte",
@@ -777,7 +778,7 @@ final public function getLastCreatedRequestFlag(string $flag): bool
777778
public function canonicalize(?string $destination = null, ...$args): void
778779
{
779780
$request = $this->request;
780-
if ($this->isAjax() || (!$request->isMethod('get') && !$request->isMethod('head'))) {
781+
if ($this->isAjax() || ($request !== null && !$request->isMethod('get') && !$request->isMethod('head'))) {
781782
return;
782783
}
783784

@@ -798,7 +799,7 @@ public function canonicalize(?string $destination = null, ...$args): void
798799
return;
799800
}
800801

801-
$code = $request->hasFlag($request::VARYING)
802+
$code = $request !== null && $request->hasFlag($request::VARYING)
802803
? Http\IResponse::S302_Found
803804
: Http\IResponse::S301_MovedPermanently;
804805
$this->sendResponse(new Responses\RedirectResponse($url, $code));
@@ -904,6 +905,7 @@ public function restoreRequest(string $key): void
904905
}
905906

906907
$request = clone $data[1];
908+
assert($request instanceof Application\Request);
907909
$session->remove($key);
908910
$params = $request->getParameters();
909911
$params[self::FlashKey] = $this->getFlashKey();
@@ -959,13 +961,14 @@ public function getGlobalState(?string $forClass = null): array
959961

960962
$persistents = $this->getReflection()->getPersistentComponents();
961963

964+
$since = false;
962965
foreach ($this->getComponentTree() as $component) {
963966
if ($component->getParent() === $this) {
964967
// counts on child-first search
965-
$since = $persistents[$component->getName()]['since'] ?? false; // false = nonpersistent
968+
$since = $persistents[(string) $component->getName()]['since'] ?? false; // false = nonpersistent
966969
}
967970

968-
if (!$component instanceof StatePersistent) {
971+
if (!$component instanceof Component) {
969972
continue;
970973
}
971974

@@ -1025,13 +1028,15 @@ private function initGlobalParameters(): void
10251028
// init $this->globalParams
10261029
$this->globalParams = [];
10271030
$selfParams = [];
1031+
$request = $this->request;
1032+
assert($request !== null);
10281033

1029-
$params = $this->request->getParameters();
1030-
if (($tmp = $this->request->getPost('_' . self::SignalKey)) !== null) {
1034+
$params = $request->getParameters();
1035+
if (($tmp = $request->getPost('_' . self::SignalKey)) !== null) {
10311036
$params[self::SignalKey] = $tmp;
10321037
} elseif ($this->isAjax()) {
1033-
$params += $this->request->getPost();
1034-
if (($tmp = $this->request->getPost(self::SignalKey)) !== null) {
1038+
$params += $request->getPost();
1039+
if (($tmp = $request->getPost(self::SignalKey)) !== null) {
10351040
$params[self::SignalKey] = $tmp;
10361041
}
10371042
}

0 commit comments

Comments
 (0)