Chore: Type class constants and expand Pint rule set#250
Conversation
Add explicit types to all 110 class constants across the public API (string/int/array) — leveraging PHP 8.3 typed constants now that the floor is 8.3. Expand pint.json beyond the bare `per` preset with rules that match common editor inspections, so CI catches what the editor flags: - native_function_invocation (@compiler_optimized, namespaced scope) - no_unused_imports, ordered_imports - no_useless_else, no_useless_return - no_empty_statement, no_empty_phpdoc, no_empty_comment - array_syntax (short), single_quote - trailing_comma_in_multiline Pint applied the new rules across the codebase (mainly prefixing compiler-optimized builtins with `\` in namespaced files and sorting imports).
k6 benchmark
|
Greptile SummaryThis PR types all 110 class constants across the public API ( Confidence Score: 4/5Safe to merge; all changes are mechanical (tooling-driven) with no logic alterations, but typed public constants are a library API contract change. No P0 or P1 issues. The single P2 concern is that adding explicit types to src/Http/Response.php, src/Http/Request.php, src/Http/Router.php, src/Http/View.php — these hold the public/protected typed constants that affect library consumers. Important Files Changed
Reviews (1): Last reviewed commit: "Chore: Type class constants and expand P..." | Re-trigger Greptile |
| /** | ||
| * HTTP content types | ||
| */ | ||
| public const CONTENT_TYPE_TEXT = 'text/plain'; | ||
| public const string CONTENT_TYPE_TEXT = 'text/plain'; | ||
|
|
||
| public const CONTENT_TYPE_HTML = 'text/html'; | ||
| public const string CONTENT_TYPE_HTML = 'text/html'; | ||
|
|
||
| public const CONTENT_TYPE_JSON = 'application/json'; | ||
| public const string CONTENT_TYPE_JSON = 'application/json'; | ||
|
|
||
| public const CONTENT_TYPE_XML = 'text/xml'; | ||
| public const string CONTENT_TYPE_XML = 'text/xml'; | ||
|
|
||
| public const CONTENT_TYPE_JAVASCRIPT = 'text/javascript'; | ||
| public const string CONTENT_TYPE_JAVASCRIPT = 'text/javascript'; | ||
|
|
||
| public const CONTENT_TYPE_IMAGE = 'image/*'; | ||
| public const string CONTENT_TYPE_IMAGE = 'image/*'; | ||
|
|
||
| public const CONTENT_TYPE_IMAGE_JPEG = 'image/jpeg'; | ||
| public const string CONTENT_TYPE_IMAGE_JPEG = 'image/jpeg'; | ||
|
|
||
| public const CONTENT_TYPE_IMAGE_PNG = 'image/png'; | ||
| public const string CONTENT_TYPE_IMAGE_PNG = 'image/png'; | ||
|
|
||
| public const CONTENT_TYPE_IMAGE_GIF = 'image/gif'; | ||
| public const string CONTENT_TYPE_IMAGE_GIF = 'image/gif'; | ||
|
|
||
| public const CONTENT_TYPE_IMAGE_SVG = 'image/svg+xml'; | ||
| public const string CONTENT_TYPE_IMAGE_SVG = 'image/svg+xml'; | ||
|
|
||
| public const CONTENT_TYPE_IMAGE_WEBP = 'image/webp'; | ||
| public const string CONTENT_TYPE_IMAGE_WEBP = 'image/webp'; | ||
|
|
||
| public const CONTENT_TYPE_IMAGE_ICON = 'image/x-icon'; | ||
| public const string CONTENT_TYPE_IMAGE_ICON = 'image/x-icon'; | ||
|
|
||
| public const CONTENT_TYPE_IMAGE_BMP = 'image/bmp'; | ||
| public const string CONTENT_TYPE_IMAGE_BMP = 'image/bmp'; | ||
|
|
||
| /** | ||
| * Chrsets | ||
| */ | ||
| public const CHARSET_UTF8 = 'UTF-8'; | ||
| public const string CHARSET_UTF8 = 'UTF-8'; | ||
|
|
||
| /** | ||
| * HTTP response status codes | ||
| */ | ||
| public const STATUS_CODE_CONTINUE = 100; | ||
| public const STATUS_CODE_SWITCHING_PROTOCOLS = 101; | ||
| public const STATUS_CODE_PROCESSING = 102; | ||
| public const STATUS_CODE_EARLY_HINTS = 103; | ||
|
|
||
| public const STATUS_CODE_OK = 200; | ||
| public const STATUS_CODE_CREATED = 201; | ||
| public const STATUS_CODE_ACCEPTED = 202; | ||
| public const STATUS_CODE_NON_AUTHORITATIVE_INFORMATION = 203; | ||
| public const STATUS_CODE_NOCONTENT = 204; | ||
| public const STATUS_CODE_RESETCONTENT = 205; | ||
| public const STATUS_CODE_PARTIALCONTENT = 206; | ||
| public const STATUS_CODE_MULTI_STATUS = 207; | ||
| public const STATUS_CODE_ALREADY_REPORTED = 208; | ||
| public const STATUS_CODE_IM_USED = 226; | ||
|
|
||
| public const STATUS_CODE_MULTIPLE_CHOICES = 300; | ||
| public const STATUS_CODE_MOVED_PERMANENTLY = 301; | ||
| public const STATUS_CODE_FOUND = 302; | ||
| public const STATUS_CODE_SEE_OTHER = 303; | ||
| public const STATUS_CODE_NOT_MODIFIED = 304; | ||
| public const STATUS_CODE_USE_PROXY = 305; | ||
| public const STATUS_CODE_UNUSED = 306; | ||
| public const STATUS_CODE_TEMPORARY_REDIRECT = 307; | ||
| public const STATUS_CODE_PERMANENT_REDIRECT = 308; | ||
|
|
||
| public const STATUS_CODE_BAD_REQUEST = 400; | ||
| public const STATUS_CODE_UNAUTHORIZED = 401; | ||
| public const STATUS_CODE_PAYMENT_REQUIRED = 402; | ||
| public const STATUS_CODE_FORBIDDEN = 403; | ||
| public const STATUS_CODE_NOT_FOUND = 404; | ||
| public const STATUS_CODE_METHOD_NOT_ALLOWED = 405; | ||
| public const STATUS_CODE_NOT_ACCEPTABLE = 406; | ||
| public const STATUS_CODE_PROXY_AUTHENTICATION_REQUIRED = 407; | ||
| public const STATUS_CODE_REQUEST_TIMEOUT = 408; | ||
| public const STATUS_CODE_CONFLICT = 409; | ||
| public const STATUS_CODE_GONE = 410; | ||
| public const STATUS_CODE_LENGTH_REQUIRED = 411; | ||
| public const STATUS_CODE_PRECONDITION_FAILED = 412; | ||
| public const STATUS_CODE_REQUEST_ENTITY_TOO_LARGE = 413; | ||
| public const STATUS_CODE_REQUEST_URI_TOO_LONG = 414; | ||
| public const STATUS_CODE_UNSUPPORTED_MEDIA_TYPE = 415; | ||
| public const STATUS_CODE_REQUESTED_RANGE_NOT_SATISFIABLE = 416; | ||
| public const STATUS_CODE_EXPECTATION_FAILED = 417; | ||
| public const STATUS_CODE_IM_A_TEAPOT = 418; | ||
| public const STATUS_CODE_MISDIRECTED_REQUEST = 421; | ||
| public const STATUS_CODE_UNPROCESSABLE_ENTITY = 422; | ||
| public const STATUS_CODE_LOCKED = 423; | ||
| public const STATUS_CODE_FAILED_DEPENDENCY = 424; | ||
| public const STATUS_CODE_TOO_EARLY = 425; | ||
| public const STATUS_CODE_UPGRADE_REQUIRED = 426; | ||
| public const STATUS_CODE_PRECONDITION_REQUIRED = 428; | ||
| public const STATUS_CODE_TOO_MANY_REQUESTS = 429; | ||
| public const STATUS_CODE_REQUEST_HEADER_FIELDS_TOO_LARGE = 431; | ||
| public const STATUS_CODE_UNAVAILABLE_FOR_LEGAL_REASONS = 451; | ||
|
|
||
| public const STATUS_CODE_INTERNAL_SERVER_ERROR = 500; | ||
| public const STATUS_CODE_NOT_IMPLEMENTED = 501; | ||
| public const STATUS_CODE_BAD_GATEWAY = 502; | ||
| public const STATUS_CODE_SERVICE_UNAVAILABLE = 503; | ||
| public const STATUS_CODE_GATEWAY_TIMEOUT = 504; | ||
| public const STATUS_CODE_HTTP_VERSION_NOT_SUPPORTED = 505; | ||
| public const STATUS_CODE_VARIANT_ALSO_NEGOTIATES = 506; | ||
| public const STATUS_CODE_INSUFFICIENT_STORAGE = 507; | ||
| public const STATUS_CODE_LOOP_DETECTED = 508; | ||
| public const STATUS_CODE_NOT_EXTENDED = 510; | ||
| public const STATUS_CODE_NETWORK_AUTHENTICATION_REQUIRED = 511; | ||
| public const int STATUS_CODE_CONTINUE = 100; | ||
| public const int STATUS_CODE_SWITCHING_PROTOCOLS = 101; | ||
| public const int STATUS_CODE_PROCESSING = 102; | ||
| public const int STATUS_CODE_EARLY_HINTS = 103; | ||
|
|
||
| public const int STATUS_CODE_OK = 200; | ||
| public const int STATUS_CODE_CREATED = 201; | ||
| public const int STATUS_CODE_ACCEPTED = 202; | ||
| public const int STATUS_CODE_NON_AUTHORITATIVE_INFORMATION = 203; | ||
| public const int STATUS_CODE_NOCONTENT = 204; | ||
| public const int STATUS_CODE_RESETCONTENT = 205; | ||
| public const int STATUS_CODE_PARTIALCONTENT = 206; | ||
| public const int STATUS_CODE_MULTI_STATUS = 207; | ||
| public const int STATUS_CODE_ALREADY_REPORTED = 208; | ||
| public const int STATUS_CODE_IM_USED = 226; | ||
|
|
||
| public const int STATUS_CODE_MULTIPLE_CHOICES = 300; | ||
| public const int STATUS_CODE_MOVED_PERMANENTLY = 301; | ||
| public const int STATUS_CODE_FOUND = 302; | ||
| public const int STATUS_CODE_SEE_OTHER = 303; | ||
| public const int STATUS_CODE_NOT_MODIFIED = 304; | ||
| public const int STATUS_CODE_USE_PROXY = 305; | ||
| public const int STATUS_CODE_UNUSED = 306; | ||
| public const int STATUS_CODE_TEMPORARY_REDIRECT = 307; | ||
| public const int STATUS_CODE_PERMANENT_REDIRECT = 308; | ||
|
|
||
| public const int STATUS_CODE_BAD_REQUEST = 400; | ||
| public const int STATUS_CODE_UNAUTHORIZED = 401; | ||
| public const int STATUS_CODE_PAYMENT_REQUIRED = 402; | ||
| public const int STATUS_CODE_FORBIDDEN = 403; | ||
| public const int STATUS_CODE_NOT_FOUND = 404; | ||
| public const int STATUS_CODE_METHOD_NOT_ALLOWED = 405; | ||
| public const int STATUS_CODE_NOT_ACCEPTABLE = 406; | ||
| public const int STATUS_CODE_PROXY_AUTHENTICATION_REQUIRED = 407; | ||
| public const int STATUS_CODE_REQUEST_TIMEOUT = 408; | ||
| public const int STATUS_CODE_CONFLICT = 409; | ||
| public const int STATUS_CODE_GONE = 410; | ||
| public const int STATUS_CODE_LENGTH_REQUIRED = 411; | ||
| public const int STATUS_CODE_PRECONDITION_FAILED = 412; | ||
| public const int STATUS_CODE_REQUEST_ENTITY_TOO_LARGE = 413; | ||
| public const int STATUS_CODE_REQUEST_URI_TOO_LONG = 414; | ||
| public const int STATUS_CODE_UNSUPPORTED_MEDIA_TYPE = 415; | ||
| public const int STATUS_CODE_REQUESTED_RANGE_NOT_SATISFIABLE = 416; | ||
| public const int STATUS_CODE_EXPECTATION_FAILED = 417; | ||
| public const int STATUS_CODE_IM_A_TEAPOT = 418; | ||
| public const int STATUS_CODE_MISDIRECTED_REQUEST = 421; | ||
| public const int STATUS_CODE_UNPROCESSABLE_ENTITY = 422; | ||
| public const int STATUS_CODE_LOCKED = 423; | ||
| public const int STATUS_CODE_FAILED_DEPENDENCY = 424; | ||
| public const int STATUS_CODE_TOO_EARLY = 425; | ||
| public const int STATUS_CODE_UPGRADE_REQUIRED = 426; | ||
| public const int STATUS_CODE_PRECONDITION_REQUIRED = 428; | ||
| public const int STATUS_CODE_TOO_MANY_REQUESTS = 429; | ||
| public const int STATUS_CODE_REQUEST_HEADER_FIELDS_TOO_LARGE = 431; | ||
| public const int STATUS_CODE_UNAVAILABLE_FOR_LEGAL_REASONS = 451; | ||
|
|
||
| public const int STATUS_CODE_INTERNAL_SERVER_ERROR = 500; | ||
| public const int STATUS_CODE_NOT_IMPLEMENTED = 501; | ||
| public const int STATUS_CODE_BAD_GATEWAY = 502; | ||
| public const int STATUS_CODE_SERVICE_UNAVAILABLE = 503; | ||
| public const int STATUS_CODE_GATEWAY_TIMEOUT = 504; | ||
| public const int STATUS_CODE_HTTP_VERSION_NOT_SUPPORTED = 505; | ||
| public const int STATUS_CODE_VARIANT_ALSO_NEGOTIATES = 506; | ||
| public const int STATUS_CODE_INSUFFICIENT_STORAGE = 507; | ||
| public const int STATUS_CODE_LOOP_DETECTED = 508; | ||
| public const int STATUS_CODE_NOT_EXTENDED = 510; | ||
| public const int STATUS_CODE_NETWORK_AUTHENTICATION_REQUIRED = 511; | ||
|
|
||
| /** | ||
| * @var array<int, string> |
There was a problem hiding this comment.
Typed constants are a breaking API change for library consumers
Adding explicit types to public and protected class constants (e.g., const int STATUS_CODE_OK, const string CONTENT_TYPE_JSON) is a PHP 8.3 feature. For a library like utopia-php/http, any downstream code that extends these classes and redeclares one of these constants with a different type — or that was relying on coercive assignment — will receive a fatal error at runtime in PHP 8.3+. This applies to the same constants typed across Request.php, Router.php, View.php, and the Swoole adapter files as well.
If this is intentional as part of a major/breaking release, consider documenting it in the changelog or PR description. If it isn't, this warrants a semver bump.
Summary
string/int/array), now that the PHP floor is 8.3 and typed constants are supported.pint.jsonbeyond the bareperpreset with rules that mirror common editor inspections, so CI catches what the editor flags rather than leaving an editor-vs-CI gap.\-prefixing compiler-optimized builtins (array_key_exists,count,strlen,is_array,in_array,func_get_args, etc.) in namespaced files — this lets the PHP opcode compiler emit specialized opcodes instead of going through namespace lookup. Non-optimized builtins are deliberately left unprefixed.New Pint rules
native_function_invocation(@compiler_optimized,scope: namespaced,strict: true)no_unused_imports,ordered_imports(alpha)no_useless_else,no_useless_returnno_empty_statement,no_empty_phpdoc,no_empty_commentarray_syntax: short,single_quotetrailing_comma_in_multiline(arrays, arguments, parameters)Test plan
composer format:checkpassescomposer analyzepasses (PHPStan level 7)composer refactor:checkpasses (Rector dry run clean)