Skip to content

Commit 5a81d90

Browse files
committed
build(app): Fixing style and sa issues
1 parent a073212 commit 5a81d90

20 files changed

+197
-81
lines changed

composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,10 +117,10 @@
117117
"phpstan:baseline": [
118118
"bash -c \"rm -rf utils/phpstan-baseline/*.neon\"",
119119
"bash -c \"touch utils/phpstan-baseline/loader.neon\"",
120-
"phpstan analyse --ansi --generate-baseline=utils/phpstan-baseline/loader.neon",
120+
"phpstan analyse --ansi --generate-baseline=utils/phpstan-baseline/loader.neon --memory-limit=512M",
121121
"split-phpstan-baseline utils/phpstan-baseline/loader.neon"
122122
],
123-
"phpstan:check": "vendor/bin/phpstan analyse --verbose --ansi",
123+
"phpstan:check": "vendor/bin/phpstan analyse --verbose --ansi --memory-limit=512M",
124124
"sa": "@analyze",
125125
"style": "@cs-fix",
126126
"test": "phpunit"

system/Router/Attributes/Cache.php

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -62,25 +62,19 @@ public function before(RequestInterface $request): RequestInterface|ResponseInte
6262
$cacheKey = $this->key ?? $this->generateCacheKey($request);
6363

6464
$cached = cache($cacheKey);
65-
if ($cached !== null) {
66-
// Validate cached data structure
67-
if (is_array($cached) && isset($cached['body'], $cached['headers'], $cached['status'])) {
68-
$response = service('response');
69-
$response->setBody($cached['body']);
70-
$response->setStatusCode($cached['status']);
71-
72-
// Mark response as served from cache to prevent re-caching
73-
$response->setHeader('X-Cached-Response', 'true');
74-
75-
// Restore headers from cached array of header name => value strings
76-
foreach ($cached['headers'] as $name => $value) {
77-
$response->setHeader($name, $value);
78-
}
79-
80-
$response->setHeader('Age', (string) (time() - ($cached['timestamp'] ?? time())));
81-
82-
return $response;
65+
// Validate cached data structure
66+
if ($cached !== null && (is_array($cached) && isset($cached['body'], $cached['headers'], $cached['status']))) {
67+
$response = service('response');
68+
$response->setBody($cached['body']);
69+
$response->setStatusCode($cached['status']);
70+
// Mark response as served from cache to prevent re-caching
71+
$response->setHeader('X-Cached-Response', 'true');
72+
// Restore headers from cached array of header name => value strings
73+
foreach ($cached['headers'] as $name => $value) {
74+
$response->setHeader($name, $value);
8375
}
76+
$response->setHeader('Age', (string) (time() - ($cached['timestamp'] ?? time())));
77+
return $response;
8478
}
8579

8680
return null; // Continue to controller

system/Router/Attributes/Filter.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public function after(RequestInterface $request, ResponseInterface $response): ?
5858

5959
public function getFilters(): array
6060
{
61-
if (empty($this->having)) {
61+
if ($this->having === []) {
6262
return [$this->by];
6363
}
6464

system/Router/Attributes/Restrict.php

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -176,22 +176,18 @@ private function getSubdomain(RequestInterface $request): string
176176
if ($partCount < 3) {
177177
return '';
178178
}
179-
180179
// Check if we have a two-part TLD (e.g., co.uk, com.au)
181-
if ($partCount >= 3) {
182-
$lastTwoParts = $parts[$partCount - 2] . '.' . $parts[$partCount - 1];
183-
184-
if (in_array($lastTwoParts, self::TWO_PART_TLDS, true)) {
185-
// For two-part TLD, need at least 4 parts for subdomain
186-
// e.g., api.example.co.uk (4 parts)
187-
if ($partCount < 4) {
188-
return ''; // No subdomain, just domain.co.uk
189-
}
190-
191-
// Remove the two-part TLD and domain name (last 3 parts)
192-
// e.g., admin.api.example.co.uk -> admin.api
193-
return implode('.', array_slice($parts, 0, $partCount - 3));
180+
$lastTwoParts = $parts[$partCount - 2] . '.' . $parts[$partCount - 1];
181+
if (in_array($lastTwoParts, self::TWO_PART_TLDS, true)) {
182+
// For two-part TLD, need at least 4 parts for subdomain
183+
// e.g., api.example.co.uk (4 parts)
184+
if ($partCount < 4) {
185+
return ''; // No subdomain, just domain.co.uk
194186
}
187+
188+
// Remove the two-part TLD and domain name (last 3 parts)
189+
// e.g., admin.api.example.co.uk -> admin.api
190+
return implode('.', array_slice($parts, 0, $partCount - 3));
195191
}
196192

197193
// Standard TLD: Remove TLD and domain (last 2 parts)

system/Router/Router.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ public function getFilters(): array
259259
$filters = $this->filtersInfo;
260260

261261
// Check for attribute-based filters
262-
foreach ($this->routeAttributes as $location => $attributes) {
262+
foreach ($this->routeAttributes as $attributes) {
263263
foreach ($attributes as $attribute) {
264264
if ($attribute instanceof Filter) {
265265
$filters = array_merge($filters, $attribute->getFilters());

tests/system/CodeIgniterTest.php

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -955,6 +955,12 @@ public function testStartControllerPermitsInvoke(): void
955955
{
956956
$this->setPrivateProperty($this->codeigniter, 'benchmark', new Timer());
957957
$this->setPrivateProperty($this->codeigniter, 'controller', '\\' . Home::class);
958+
959+
// Set up the router with routes
960+
$routes = service('routes');
961+
$router = service('router', $routes, service('incomingrequest'));
962+
$this->setPrivateProperty($this->codeigniter, 'router', $router);
963+
958964
$startController = self::getPrivateMethodInvoker($this->codeigniter, 'startController');
959965

960966
$this->setPrivateProperty($this->codeigniter, 'method', '__invoke');
@@ -969,9 +975,9 @@ public function testRouteAttributeCacheIntegration(): void
969975
$_SERVER['argv'] = ['index.php', 'attribute/cached'];
970976
$_SERVER['argc'] = 2;
971977

972-
$_SERVER['REQUEST_URI'] = '/attribute/cached';
973-
$_SERVER['SCRIPT_NAME'] = '/index.php';
974-
$_SERVER['REQUEST_METHOD'] = 'GET';
978+
Services::superglobals()->setServer('REQUEST_URI', '/attribute/cached');
979+
Services::superglobals()->setServer('SCRIPT_NAME', '/index.php');
980+
Services::superglobals()->setServer('REQUEST_METHOD', 'GET');
975981

976982
// Clear cache before test
977983
cache()->clean();
@@ -1000,9 +1006,9 @@ public function testRouteAttributeCacheIntegration(): void
10001006
$this->resetServices();
10011007
$_SERVER['argv'] = ['index.php', 'attribute/cached'];
10021008
$_SERVER['argc'] = 2;
1003-
$_SERVER['REQUEST_URI'] = '/attribute/cached';
1004-
$_SERVER['SCRIPT_NAME'] = '/index.php';
1005-
$_SERVER['REQUEST_METHOD'] = 'GET';
1009+
Services::superglobals()->setServer('REQUEST_URI', '/attribute/cached');
1010+
Services::superglobals()->setServer('SCRIPT_NAME', '/index.php');
1011+
Services::superglobals()->setServer('REQUEST_METHOD', 'GET');
10061012
$this->codeigniter = new MockCodeIgniter(new App());
10071013

10081014
$routes = service('routes');
@@ -1029,8 +1035,8 @@ public function testRouteAttributeFilterIntegration(): void
10291035
$_SERVER['argv'] = ['index.php', 'attribute/filtered'];
10301036
$_SERVER['argc'] = 2;
10311037

1032-
$_SERVER['REQUEST_URI'] = '/attribute/filtered';
1033-
$_SERVER['SCRIPT_NAME'] = '/index.php';
1038+
Services::superglobals()->setServer('REQUEST_URI', '/attribute/filtered');
1039+
Services::superglobals()->setServer('SCRIPT_NAME', '/index.php');
10341040

10351041
// Register the test filter
10361042
$filterConfig = config('Filters');
@@ -1057,8 +1063,8 @@ public function testRouteAttributeRestrictIntegration(): void
10571063
$_SERVER['argv'] = ['index.php', 'attribute/restricted'];
10581064
$_SERVER['argc'] = 2;
10591065

1060-
$_SERVER['REQUEST_URI'] = '/attribute/restricted';
1061-
$_SERVER['SCRIPT_NAME'] = '/index.php';
1066+
Services::superglobals()->setServer('REQUEST_URI', '/attribute/restricted');
1067+
Services::superglobals()->setServer('SCRIPT_NAME', '/index.php');
10621068

10631069
// Inject mock router
10641070
$routes = service('routes');
@@ -1079,8 +1085,8 @@ public function testRouteAttributeRestrictThrowsException(): void
10791085
$_SERVER['argv'] = ['index.php', 'attribute/restricted'];
10801086
$_SERVER['argc'] = 2;
10811087

1082-
$_SERVER['REQUEST_URI'] = '/attribute/shouldBeRestricted';
1083-
$_SERVER['SCRIPT_NAME'] = '/index.php';
1088+
Services::superglobals()->setServer('REQUEST_URI', '/attribute/shouldBeRestricted');
1089+
Services::superglobals()->setServer('SCRIPT_NAME', '/index.php');
10841090

10851091
// Inject mock router
10861092
$routes = service('routes');
@@ -1100,8 +1106,8 @@ public function testRouteAttributeMultipleAttributesIntegration(): void
11001106
$_SERVER['argv'] = ['index.php', 'attribute/multiple'];
11011107
$_SERVER['argc'] = 2;
11021108

1103-
$_SERVER['REQUEST_URI'] = '/attribute/multiple';
1104-
$_SERVER['SCRIPT_NAME'] = '/index.php';
1109+
Services::superglobals()->setServer('REQUEST_URI', '/attribute/multiple');
1110+
Services::superglobals()->setServer('SCRIPT_NAME', '/index.php');
11051111

11061112
// Register the test filter
11071113
$filterConfig = config('Filters');
@@ -1128,8 +1134,8 @@ public function testRouteAttributeNoAttributesIntegration(): void
11281134
$_SERVER['argv'] = ['index.php', 'attribute/none'];
11291135
$_SERVER['argc'] = 2;
11301136

1131-
$_SERVER['REQUEST_URI'] = '/attribute/none';
1132-
$_SERVER['SCRIPT_NAME'] = '/index.php';
1137+
Services::superglobals()->setServer('REQUEST_URI', '/attribute/none');
1138+
Services::superglobals()->setServer('SCRIPT_NAME', '/index.php');
11331139

11341140
// Inject mock router
11351141
$routes = service('routes');
@@ -1150,9 +1156,9 @@ public function testRouteAttributeCustomCacheKeyIntegration(): void
11501156
$_SERVER['argv'] = ['index.php', 'attribute/customkey'];
11511157
$_SERVER['argc'] = 2;
11521158

1153-
$_SERVER['REQUEST_URI'] = '/attribute/customkey';
1154-
$_SERVER['SCRIPT_NAME'] = '/index.php';
1155-
$_SERVER['REQUEST_METHOD'] = 'GET';
1159+
Services::superglobals()->setServer('REQUEST_URI', '/attribute/customkey');
1160+
Services::superglobals()->setServer('SCRIPT_NAME', '/index.php');
1161+
Services::superglobals()->setServer('REQUEST_METHOD', 'GET');
11561162

11571163
// Clear cache before test
11581164
cache()->clean();
@@ -1166,14 +1172,14 @@ public function testRouteAttributeCustomCacheKeyIntegration(): void
11661172
// First request
11671173
ob_start();
11681174
$this->codeigniter->run();
1169-
$output1 = ob_get_clean();
1175+
ob_get_clean();
11701176

11711177
// Verify custom cache key was used
11721178
$cached = cache('custom_cache_key');
11731179
$this->assertNotNull($cached);
11741180
$this->assertIsArray($cached);
11751181
$this->assertArrayHasKey('body', $cached);
1176-
$this->assertStringContainsString('Custom key content at', $cached['body']);
1182+
$this->assertStringContainsString('Custom key content at', (string) $cached['body']);
11771183

11781184
// Clear cache after test
11791185
cache()->clean();

tests/system/Router/Attributes/CacheTest.php

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
namespace CodeIgniter\Router\Attributes;
1515

16+
use CodeIgniter\HTTP\ResponseInterface;
1617
use CodeIgniter\HTTP\IncomingRequest;
1718
use CodeIgniter\HTTP\SiteURI;
1819
use CodeIgniter\HTTP\UserAgent;
@@ -78,7 +79,7 @@ public function testBeforeReturnsCachedResponseWhenFound(): void
7879

7980
$result = $cache->before($request);
8081

81-
$this->assertInstanceOf('CodeIgniter\HTTP\ResponseInterface', $result);
82+
$this->assertInstanceOf(ResponseInterface::class, $result);
8283
$this->assertSame('Cached content', $result->getBody());
8384
$this->assertSame(200, $result->getStatusCode());
8485
$this->assertSame('text/html', $result->getHeaderLine('Content-Type'));
@@ -129,7 +130,7 @@ public function testBeforeUsesCustomCacheKey(): void
129130

130131
$result = $cache->before($request);
131132

132-
$this->assertInstanceOf('CodeIgniter\HTTP\ResponseInterface', $result);
133+
$this->assertInstanceOf(ResponseInterface::class, $result);
133134
$this->assertSame('Custom cached content', $result->getBody());
134135
}
135136

@@ -141,7 +142,7 @@ public function testAfterReturnsNullForNonGetRequest(): void
141142

142143
$result = $cache->after($request, $response);
143144

144-
$this->assertNull($result);
145+
$this->assertNotInstanceOf(ResponseInterface::class, $result);
145146
}
146147

147148
public function testAfterCachesGetRequestResponse(): void
@@ -199,7 +200,7 @@ public function testGenerateCacheKeyIncludesMethodPathAndQuery(): void
199200
private function createMockRequest(string $method, string $path, string $query = ''): IncomingRequest
200201
{
201202
$config = new MockAppConfig();
202-
$uri = new SiteURI($config, 'http://example.com' . $path . ($query ? '?' . $query : ''));
203+
$uri = new SiteURI($config, 'http://example.com' . $path . ($query !== '' ? '?' . $query : ''));
203204
$userAgent = new UserAgent();
204205

205206
$request = $this->getMockBuilder(IncomingRequest::class)

tests/system/Router/Attributes/FilterTest.php

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
namespace CodeIgniter\Router\Attributes;
1515

16+
use CodeIgniter\HTTP\ResponseInterface;
1617
use CodeIgniter\HTTP\IncomingRequest;
1718
use CodeIgniter\HTTP\SiteURI;
1819
use CodeIgniter\HTTP\UserAgent;
@@ -69,7 +70,7 @@ public function testAfterReturnsNull(): void
6970

7071
$result = $filter->after($request, $response);
7172

72-
$this->assertNull($result);
73+
$this->assertNotInstanceOf(ResponseInterface::class, $result);
7374
}
7475

7576
public function testGetFiltersReturnsArrayWithFilterNameOnly(): void
@@ -78,7 +79,6 @@ public function testGetFiltersReturnsArrayWithFilterNameOnly(): void
7879

7980
$filters = $filter->getFilters();
8081

81-
$this->assertIsArray($filters);
8282
$this->assertCount(1, $filters);
8383
$this->assertSame('csrf', $filters[0]);
8484
}
@@ -89,7 +89,6 @@ public function testGetFiltersReturnsArrayWithFilterNameAndArguments(): void
8989

9090
$filters = $filter->getFilters();
9191

92-
$this->assertIsArray($filters);
9392
$this->assertCount(1, $filters);
9493
$this->assertArrayHasKey('auth', $filters);
9594
$this->assertSame(['admin'], $filters['auth']);
@@ -101,7 +100,6 @@ public function testGetFiltersReturnsArrayWithMultipleArguments(): void
101100

102101
$filters = $filter->getFilters();
103102

104-
$this->assertIsArray($filters);
105103
$this->assertCount(1, $filters);
106104
$this->assertArrayHasKey('permission', $filters);
107105
$this->assertSame(['posts.edit', 'posts.delete'], $filters['permission']);
@@ -113,7 +111,6 @@ public function testGetFiltersWithEmptyHavingReturnsSimpleArray(): void
113111

114112
$filters = $filter->getFilters();
115113

116-
$this->assertIsArray($filters);
117114
$this->assertCount(1, $filters);
118115
$this->assertSame('cors', $filters[0]);
119116
}
@@ -138,10 +135,6 @@ public function testGetFiltersFormatIsConsistentAcrossInstances(): void
138135
$filters1 = $filterWithoutArgs->getFilters();
139136
$filters2 = $filterWithArgs->getFilters();
140137

141-
// Both should return arrays
142-
$this->assertIsArray($filters1);
143-
$this->assertIsArray($filters2);
144-
145138
// Without args: simple array
146139
$this->assertArrayNotHasKey('filter1', $filters1);
147140
$this->assertContains('filter1', $filters1);
@@ -206,15 +199,15 @@ public function testAfterDoesNotModifyResponse(): void
206199

207200
$result = $filter->after($request, $response);
208201

209-
$this->assertNull($result);
202+
$this->assertNotInstanceOf(ResponseInterface::class, $result);
210203
$this->assertSame('Test content', $response->getBody());
211204
$this->assertSame(200, $response->getStatusCode());
212205
}
213206

214207
private function createMockRequest(string $method, string $path, string $query = ''): IncomingRequest
215208
{
216209
$config = new MockAppConfig();
217-
$uri = new SiteURI($config, 'http://example.com' . $path . ($query ? '?' . $query : ''));
210+
$uri = new SiteURI($config, 'http://example.com' . $path . ($query !== '' ? '?' . $query : ''));
218211
$userAgent = new UserAgent();
219212

220213
$request = $this->getMockBuilder(IncomingRequest::class)

tests/system/Router/Attributes/RestrictTest.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
namespace CodeIgniter\Router\Attributes;
1515

16+
use CodeIgniter\HTTP\ResponseInterface;
1617
use CodeIgniter\Exceptions\PageNotFoundException;
1718
use CodeIgniter\HTTP\IncomingRequest;
1819
use CodeIgniter\HTTP\SiteURI;
@@ -95,7 +96,7 @@ public function testAfterReturnsNull(): void
9596

9697
$result = $restrict->after($request, $response);
9798

98-
$this->assertNull($result);
99+
$this->assertNotInstanceOf(ResponseInterface::class, $result);
99100
}
100101

101102
public function testCheckEnvironmentAllowsCurrentEnvironment(): void
@@ -448,7 +449,7 @@ private function createMockRequest(string $method, string $path, string $host =
448449
{
449450
$config = new MockAppConfig();
450451
// Use the host parameter to properly set the host in SiteURI
451-
$uri = new SiteURI($config, $path . ($query ? '?' . $query : ''), $host, 'http');
452+
$uri = new SiteURI($config, $path . ($query !== '' ? '?' . $query : ''), $host, 'http');
452453
$userAgent = new UserAgent();
453454

454455
$request = $this->getMockBuilder(IncomingRequest::class)

user_guide_src/source/incoming/controller_attributes.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
.. _incoming/controller_attributes:
2+
13
#####################
24
Controller Attributes
35
#####################
@@ -15,7 +17,7 @@ Controller Attributes can be applied to either the entire class, or to a specifi
1517

1618
.. literalinclude:: controller_attributes/001.php
1719

18-
In this example, the ``Auth`` filter will be applied to all methods in ``AdminController`.
20+
In this example, the ``Auth`` filter will be applied to all methods in ``AdminController``.
1921

2022
You can also apply the ``Filters`` attribute to a specific method within a controller. This allows you to apply filters only to certain methods, while leaving others unaffected. Here's an example:
2123

0 commit comments

Comments
 (0)