Conversation
applyJsonBasicFilter compared ParamType ('email'/'url') against PHP
gettype ('string'), which never matched. EMAIL and URL values were
set to null and flagged as invalid.
Fix: treat EMAIL and URL as string types in the JSON filter matching
condition and route them through cleanJsonStr for proper validation.
fix(#112): EMAIL param injection returns null for JSON body requests
…eter - Add ParamOption::ALLOWED_VALUES and ParamOption::PATTERN constants - Add allowedValues/pattern properties, getters, setters to RequestParameter - Add allowedValues/pattern params to #[RequestParam] attribute - Wire attribute properties in WebService::configureParametersFromMethod() - Add checkAllowedAndPattern() in APIFilter for both form-encoded and JSON paths - Generate OpenAPI enum/pattern in Schema::fromRequestParameter() - 34 new tests covering all paths: unit, filter, JSON, attributes, OpenAPI, edge cases
…eter - Add ParamOption::ALLOWED_VALUES and ParamOption::PATTERN constants - Add allowedValues/pattern properties, getters, setters to RequestParameter - Add allowedValues/pattern params to #[RequestParam] attribute - Wire attribute properties in WebService::configureParametersFromMethod() - Add checkAllowedAndPattern() in APIFilter for both form-encoded and JSON paths - Generate OpenAPI enum/pattern in Schema::fromRequestParameter() - 34 new tests covering all paths: unit, filter, JSON, attributes, OpenAPI, edge cases
…WebFiori/http into feat/114-allowed-values-pattern
feat(#114): add allowed-values and pattern validation to RequestParameter
- Change WebService::isAuthorized() return type from bool to string|bool - Update WebServicesManager::isAuth() to capture string result - Update notAuth() to accept optional custom message parameter - Existing bool returns remain fully backward compatible - 4 new tests covering string denial, bool denial, true pass, multiple reasons
…ason feat(#111): allow isAuthorized() to return string as denial reason
- Add Request::parsePutPatchBody() for url-encoded and multipart bodies - Called automatically from Request::createFromGlobals() for PUT/PATCH - Remove populatePutData() calls from WebServicesManager - Deprecate WebServicesManager::populatePutData() as no-op stub - 7 new tests for url-encoded, multipart, file uploads, edge cases - Step 1 of 5 in ADR-0005 (RequestProcessor refactor)
…to-request refactor(#118): move PUT/PATCH body parsing into Request class
- Create ErrorResponse class with static methods for all error types - Each method returns ['json' => Json, 'code' => int] for flexibility - Deprecate WebServicesManager error methods, delegate to ErrorResponse - 12 new unit tests covering all error response types - Step 2 of 5 in ADR-0005 (RequestProcessor refactor)
…onse refactor(#119): extract ErrorResponse helper class
- Create standalone OpenAPI\OpenAPIGenerator class - Accepts array of WebService instances, description, version, basePath - Deprecate WebServicesManager::toOpenAPI(), delegate to generator - Add example in examples/04-advanced/02-openapi-docs/ - Update README with ErrorResponse and OpenAPIGenerator in key classes - 6 new tests covering single/multiple services, basePath, empty, legacy - Step 3 of 5 in ADR-0005 (RequestProcessor refactor)
…nerator refactor(#120): extract OpenAPIGenerator from WebServicesManager
- Add RequestProcessor for standalone service processing without a manager - Accepts WebService + optional Request + optional output stream - Handles full pipeline: content type, method check, params, auth, invocation - Internally uses WebServicesManager (single-service auto-select) - Add example in examples/04-advanced/04-request-processor/ - 6 new tests covering GET, POST, auth denial, method not allowed, content type - Step 4 of 5 in ADR-0005 (RequestProcessor refactor)
…cessor feat(#121): create RequestProcessor class
- Add @deprecated to class docblock with migration guide to RequestProcessor - Add @deprecated to process() and sendResponse() methods - Update README Quick Start to show RequestProcessor as primary approach - All existing tests pass unchanged (full backward compatibility) - Step 5 of 5 in ADR-0005 (RequestProcessor refactor) — COMPLETE
…ices-manager deprecate(#122): mark WebServicesManager as deprecated
- Create ParameterSet interface with getParameters() method - Add #[UseParameterSet] attribute for declarative usage on methods - Add WebService::addParameterSet() for traditional usage - Update getMethodParameters() to handle positional injection from sets - Sets are processed before #[RequestParam], enabling combined usage - Add example in examples/01-core/07-reusable-parameter-sets/ - Update README with parameter sets documentation - 12 new tests covering interface, attribute, validation, edge cases
- Create OpenAPIObject with shared description property and addIfNotNull/addIfTruthy helpers - HeaderObj and ParameterObj extend OpenAPIObject, removing duplicate description property/methods - Refactor toJSON() methods to use helpers instead of repeated if-null-add blocks - Reduces ~60 lines of duplicated code
feat(#116): add reusable parameter sets with ParameterSet interface
… directly - Method-level #[RequiresAuth] now checks SecurityContext instead of isAuthorized() - Class-level #[RequiresAuth] with no method annotations checks SecurityContext - checkMethodAuthorization() falls back to class-level check before isAuthorized() - Add hasClassLevelRequiresAuth() helper method - Services without auth attributes still use isAuthorized() (unchanged) - 8 new tests covering method-level, class-level, AllowAnonymous override, fallback
…-context feat(#117): #[RequiresAuth] checks SecurityContext::isAuthenticated() directly
- Add boolean type check before urldecode in filter() method - Add boolean early return before strip_tags in applyBasicFilterOnly() - Native false was being cast to empty string by urldecode/strip_tags - 2 new regression tests for native true/false
…ting - Create WebFiori\Http\Test\ServiceTestCase with fluent API - Create WebFiori\Http\Test\TestResponse with assertion methods - Deprecate APITestCase, switch its internals to tempnam (no more hardcoded file) - ServiceTestCase uses RequestProcessor directly — no manager needed - Convenience methods: get(), post(), put(), patch(), delete() - TestResponse assertions: assertOk(), assertStatus(), assertJsonEquals(), etc. - 12 new tests demonstrating the new testing API
- Add overridable validate(array $inputs): array on WebService (service-wide)
- Add #[Validate('methodName')] attribute for method-specific validation
- Both run: service-wide first, then method-specific, errors merged
- Returns 422 with error details if validation fails
- Missing validator method throws InvalidArgumentException (caught as 500)
- Uses reflection to invoke private validator methods
- Update README with cross-field validation documentation
- 10 new tests covering all paths
feat(#115): add cross-field validation with #[Validate] attribute
…ages
BREAKING CHANGE: Validation error responses now return HTTP 422 instead of 404.
- Change ErrorResponse::invalidParams() and missingParams() from 404 to 422
- Add ParamOption::MESSAGE for custom per-parameter error messages
- Add RequestParameter::getMessage()/setMessage()
- Add 'message' param to #[RequestParam] attribute
- Response format: {message, type, http-code: 422, more-info: {errors: {field: msg}}}
- If no custom message: auto-generates 'Invalid value for parameter X' or 'Required parameter X is missing'
- WebServicesManager now passes RequestParameter objects to ErrorResponse
- Update existing tests for new 422 status code and response format
- 9 new tests covering all message scenarios
…e constants - Add #[Produces] attribute to declare supported response content types - Add MediaType class with constants (JSON, XML, HTML, PLAIN, etc.) - Add WebService::getNegotiatedContentType() for methods to read the result - Add ErrorResponse::notAcceptable() for 406 responses - Negotiation runs after auth, before validation in processWithAutoHandling() - No #[Produces] = no negotiation (100% backward compatible) - Accept: */* or missing = server's first preference - No match = 406 Not Acceptable with supported types listed - Update README with content negotiation documentation - 14 new tests covering all negotiation paths
…-messages feat!(#113): change validation errors to 422 and add custom error messages
feat: add content negotiation with #[Produces] attribute
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #137 +/- ##
============================================
+ Coverage 92.34% 93.79% +1.45%
- Complexity 1302 1347 +45
============================================
Files 39 39
Lines 3147 3273 +126
============================================
+ Hits 2906 3070 +164
+ Misses 241 203 -38
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
PHPUnit 12 no longer passes return values as arguments to dependent tests. Refactored 7 test methods to be self-contained instead of relying on @Depends parameter injection.
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Release v6.0.0
Breaking Changes
more-infocontains{"errors": {"field": "message"}}instead of{"invalid": [...]}/{"missing": [...]}WebServicesManagerdeprecated — useRequestProcessorinsteadNew Features
#[Produces]attribute +MediaTypeconstants + 406 supportvalidate()method +#[Validate]attributeParameterSetinterface +#[UseParameterSet]attributeParamOption::ALLOWED_VALUESandParamOption::PATTERNParamOption::MESSAGEper parameterBug Fixes
falsedestroyed by APIFilter before boolean check (Bug: APIFilter::applyBasicFilterOnly destroys native PHP false before boolean check #132)minMaxLengthCheckused wrong key for min lengthRefactoring (ADR-0005)
RequestclassErrorResponseextracted fromWebServicesManagerOpenAPIGeneratorextracted fromWebServicesManagerRequestProcessorcreated as the primary processing entry pointWebServicesManagerdeprecated with migration guideOpenAPIObjectbase class reduces duplication in OpenAPI objectsInfrastructure
WebFiori/workflows@v1.2.5actions/checkout@v6Test Coverage
588 tests, 1735 assertions across PHP 8.1–8.5
Migration Guide
See ADR-0007 for validation error changes.
See
WebServicesManagerclass docblock for RequestProcessor migration.