├── .gitignore ├── LICENSE ├── README.md ├── circle.yml ├── composer.json ├── examples ├── autocompletion.php ├── custom-exception.php ├── not-symfony.php ├── psr7.php └── symfony.php ├── images ├── autocomplete-anim.gif ├── autocompletion-required.png └── autocompletion-type.png ├── phpunit.xml.dist ├── src ├── AbstractValueParser.php ├── BaseControllerHelperTrait.php ├── BooleanParser.php ├── CommaSeparatedBooleanParser.php ├── CommaSeparatedDateTimeParser.php ├── CommaSeparatedFloatParser.php ├── CommaSeparatedIntParser.php ├── CommaSeparatedJsonParser.php ├── CommaSeparatedParser.php ├── CommaSeparatedStringParser.php ├── CommaSeparatedYesNoBooleanParser.php ├── Config.php ├── DateTimeParser.php ├── ExceptionFactory.php ├── ExceptionMessageFactory.php ├── FloatParser.php ├── IntParser.php ├── InvalidValueException.php ├── JsonParser.php ├── LegacyExceptionFactory.php ├── LegacyExceptionMessageFactory.php ├── NotFoundException.php ├── Psr7 │ ├── ControllerHelperTrait.php │ └── Psr7RequestParserFactory.php ├── RequestParser.php ├── RequestParserFactory.php ├── StringParser.php ├── Symfony │ ├── ControllerHelperTrait.php │ ├── SymfonyRequestParser.php │ └── SymfonyRequestParserFactory.php ├── TrimParser.php ├── TypeParser.php ├── Validator │ ├── AbstractBetweenParser.php │ ├── AbstractLargerThanOrEqualToParser.php │ ├── AbstractLargerThanParser.php │ ├── AbstractSmallerThanOrEqualToParser.php │ ├── AbstractSmallerThanParser.php │ ├── EmailParser.php │ ├── FloatBetweenParser.php │ ├── FloatLargerThanOrEqualToParser.php │ ├── FloatLargerThanParser.php │ ├── FloatSmallerThanOrEqualToParser.php │ ├── FloatSmallerThanParser.php │ ├── IntBetweenParser.php │ ├── IntLargerThanOrEqualToParser.php │ ├── IntLargerThanParser.php │ ├── IntSmallerThanOrEqualToParser.php │ ├── IntSmallerThanParser.php │ ├── OneOfParser.php │ ├── StringLengthBetween.php │ ├── StringLengthLargerThanOrEqualToParser.php │ ├── StringLengthLargerThanParser.php │ ├── StringLengthSmallerThanOrEqualToParser.php │ ├── StringLengthSmallerThanParser.php │ └── UrlParser.php └── YesNoBooleanParser.php └── tests ├── CommaSeparatedTypeParserTest.php ├── ConfigTest.php ├── ExceptionFactoryTest.php ├── ExceptionMessageFactoryTest.php ├── Integration ├── Psr7IntegrationTest.php ├── SymfonyIntegrationTest.php └── setup.php ├── LegacyExceptionFactoryTest.php ├── ParserSpecTest.php └── TypeSpecTest.php /.gitignore: -------------------------------------------------------------------------------- 1 | vendor 2 | composer.lock 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Marc Scholten and Yuval Herziger 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # request parser 2 | 3 | [![Latest Stable Version](https://poser.pugx.org/mpscholten/request-parser/version)](https://packagist.org/packages/mpscholten/request-parser) 4 | [![License](https://poser.pugx.org/mpscholten/request-parser/license)](https://packagist.org/packages/mpscholten/request-parser) 5 | [![Circle CI](https://circleci.com/gh/mpscholten/request-parser.svg?style=shield)](https://circleci.com/gh/mpscholten/request-parser) 6 | [![Total Downloads](https://poser.pugx.org/mpscholten/request-parser/downloads)](https://packagist.org/packages/mpscholten/request-parser) 7 | 8 | Small PHP Library for type-safe input handling. 9 | 10 | * [The Problem](https://github.com/mpscholten/request-parser/#the-problem) 11 | * [Examples](https://github.com/mpscholten/request-parser/#examples) 12 | * [Getting Started](https://github.com/mpscholten/request-parser/#getting-started) 13 | * [Integrations](https://github.com/mpscholten/request-parser/#integrations) 14 | * [Symfony HttpFoundation](https://github.com/mpscholten/request-parser/#symfony-httpfoundation) 15 | * [Psr7](https://github.com/mpscholten/request-parser/#psr7) 16 | * [Optional Parameters](https://github.com/mpscholten/request-parser/#additional-parameters) 17 | * [Integers, Enums, DateTimes and Json Payloads](https://github.com/mpscholten/request-parser/#integers-enums-datetimes-and-json-payloads) 18 | * [Supported Data Types](https://github.com/mpscholten/request-parser/#supported-data-types) 19 | * [GET Requests](https://github.com/mpscholten/request-parser/#get-requests) 20 | * [POST Requests](https://github.com/mpscholten/request-parser/#post-requests) 21 | * [Autocompletion](https://github.com/mpscholten/request-parser/#autocompletion) 22 | * [Static Analysis](https://github.com/mpscholten/request-parser/#static-analysis) 23 | * [Error Handling](https://github.com/mpscholten/request-parser/#error-handling) 24 | * [Using Custom Exception Classes](https://github.com/mpscholten/request-parser/#using-custom-exception-classes) 25 | * [Using Custom Exception Messages](https://github.com/mpscholten/request-parser/#using-custom-exception-messages) 26 | * [Is It Production Ready?](https://github.com/mpscholten/request-parser/#is-it-production-ready) 27 | * [Tests](https://github.com/mpscholten/request-parser/#tests) 28 | * [Contributing](https://github.com/mpscholten/request-parser/#contributing) 29 | 30 | ### The Problem 31 | 32 | Let's say you have an action which lists some entities. This includes paging, ascending or descending ordering and optional filtering by the time the entity was created. 33 | This action will have some kind of input parsing, which can look like this: 34 | 35 | ```php 36 | public function index() 37 | { 38 | $page = $this->request->query->get('page'); 39 | if ($page === null || !is_integer($page)) { 40 | throw new Exception("Parameter page not found"); 41 | } 42 | 43 | $order = $this->request->query->get('order'); 44 | if ($order === null || !in_array($order, ['asc', 'desc'])) { 45 | throw new Exception("Parameter order not found"); 46 | } 47 | 48 | // Optional parameter 49 | $createdAt = $this->query->query->get('createdAt'); 50 | if (is_string($createdAt)) { 51 | $createdAt = new DateTime($createdAt); 52 | } else { 53 | $createdAt = null; 54 | } 55 | } 56 | ``` 57 | 58 | Obviously this code is not very nice to read because it is not very descriptive. It's also pretty verbose for what it's doing. 59 | And when you don't pay close attention you will probably miss a null check or a type check. 60 | 61 | Now compare the above code to this version: 62 | 63 | ```php 64 | public function index() 65 | { 66 | $page = $this->queryParameter('page')->int()->required(); 67 | $order = $this->queryParameter('order')->oneOf(['asc', 'desc'])->required(); 68 | $createdAt = $this->queryParameter('createdAt')->dateTime()->defaultsTo(null); 69 | } 70 | ``` 71 | 72 | That's what this library offers. It allows you to express "_this action requires a page parameter of type int_" or "_this action has an optional parameter createdAt of type DateTime, and will be set to a default value if absent_". 73 | 74 | ### Examples 75 | 76 | If you'd like to go straight to the code now, you can just play around with the examples. 77 | 78 | 0. `cd /tmp` 79 | 1. `git clone git@github.com:mpscholten/request-parser.git` 80 | 2. `cd request-parser` 81 | 3. `composer install` 82 | 4. `cd examples` 83 | 5. `php -S localhost:8080` 84 | 6. Open it: http://localhost:8080/symfony.php?action=hello 85 | 86 | There are also several other php files inside the examples directory. To get your hands dirty, I suggest just modifying the examples a bit. 87 | 88 | ### Getting Started 89 | 90 | Install via composer 91 | 92 | ``` 93 | composer require mpscholten/request-parser 94 | ``` 95 | 96 | 97 | ### Integrations 98 | 99 | - If you're using `symfony/http-foundation`, [click here](#symfony-httpfoundation). 100 | - If you're using a Psr7 `ServerRequestInterface` implementation, [click here](#psr7). 101 | - If you're using some other `Request` abstraction (or maybe just plain old `$_GET` and friends), [check out this example](https://github.com/mpscholten/request-parser/blob/master/examples/not-symfony.php). 102 | 103 | #### Symfony HttpFoundation 104 | 105 | The following example assumes you're using the symfony `Request`: 106 | 107 | ```php 108 | class MyController 109 | { 110 | use \MPScholten\RequestParser\Symfony\ControllerHelperTrait; 111 | 112 | public function __construct(Request $request) 113 | { 114 | $this->initRequestParser($request); 115 | } 116 | } 117 | ``` 118 | 119 | Then you can use the library like this: 120 | ```php 121 | class MyController 122 | { 123 | use \MPScholten\RequestParser\Symfony\ControllerHelperTrait; 124 | 125 | public function __construct(Request $request) 126 | { 127 | $this->initRequestParser($request); 128 | } 129 | 130 | public function myAction() 131 | { 132 | $someParameter = $this->queryParameter('someParameter')->string()->required(); 133 | } 134 | } 135 | ``` 136 | 137 | When doing `GET /MyController/myAction?someParameter=example`, the `$someParameter` variable will contain the string `"example"`. 138 | 139 | You might wonder what happens when we leave out the `?someParameter` part, like `GET /MyController/myAction`. In this case the 140 | `$this->queryParameter('someParameter')->string()->required()` will throw a `NotFoundException`. This exception can 141 | be handled by your application to show an error message. 142 | 143 | Take a look at [the examples](https://github.com/mpscholten/request-parser/tree/master/examples). 144 | 145 | #### Psr7 146 | 147 | The following example assumes you're using the Psr7 `ServerRequestInterface`: 148 | 149 | ```php 150 | class MyController 151 | { 152 | use \MPScholten\RequestParser\Psr7\ControllerHelperTrait; 153 | 154 | public function __construct(ServerRequestInterface $request) 155 | { 156 | $this->initRequestParser($request); 157 | } 158 | } 159 | ``` 160 | 161 | Then you can use the library like this: 162 | ```php 163 | class MyController 164 | { 165 | use \MPScholten\RequestParser\Psr7\ControllerHelperTrait; 166 | 167 | public function __construct(ServerRequestInterface $request) 168 | { 169 | $this->initRequestParser($request); 170 | } 171 | 172 | public function myAction() 173 | { 174 | $someParameter = $this->queryParameter('someParameter')->string()->required(); 175 | } 176 | } 177 | ``` 178 | 179 | When doing `GET /MyController/myAction?someParameter=example`, the `$someParameter` variable will contain the string `"example"`. 180 | 181 | You might wonder what happens when we leave out the `?someParameter` part, like `GET /MyController/myAction`. In this case the 182 | `$this->queryParameter('someParameter')->string()->required()` will throw a `NotFoundException`. This exception can 183 | be handled by your application to show an error message. 184 | 185 | Take a look at [the examples](https://github.com/mpscholten/request-parser/tree/master/examples). 186 | 187 | #### Optional Parameters 188 | 189 | To make the `someParameter` optional, we can just replace `required()` with `defaultsTo($someDefaultValue)`: 190 | ```php 191 | class MyController 192 | { 193 | use \MPScholten\RequestParser\Symfony\ControllerHelperTrait; 194 | 195 | public function __construct(Request $request) 196 | { 197 | $this->initRequestParser($request); 198 | } 199 | 200 | public function myAction() 201 | { 202 | $someParameter = $this->queryParameter('someParameter')->string()->defaultsTo('no value given'); 203 | } 204 | } 205 | ``` 206 | 207 | When doing `GET /MyController/myAction`, the `$someParameter` variable will now contain the string `"no value given"`. No 208 | exception will be thrown because we specified a default value. 209 | 210 | 211 | In general you first specify the parameter name, followed by the type and then specify whether the parameter is required or is optional with a default value. 212 | 213 | For more examples, check out the `examples/` directory of this repository. It contains several runnable examples. 214 | 215 | ##### Integers, Enums, DateTimes and Json Payloads 216 | 217 | Often we need more than just strings. *RequestParser* also provides methods for other data types: 218 | 219 | ```php 220 | class DashboardController 221 | { 222 | public function show() 223 | { 224 | $dashboardId = $this->queryParameter('id')->int()->required(); 225 | 226 | // GET /dashboard?name=Hello => $dashboardName == "Hello" 227 | $dashboardName = $this->queryParameter('name')->string()->required(); 228 | 229 | // Get /dashboard?name= => $dashboardName == "default value" 230 | $dashboardName = $this->queryParameter('name')->string()->defaultsToIfEmpty("default value"); 231 | 232 | // GET /dashboard?status=private => $dashboardStatus == "private" 233 | // GET /dashboard?status=public => $dashboardStatus == "public" 234 | // GET /dashboard?status=invalid => A NotFoundException will be thrown 235 | $dashboardStatus = $this->queryParameter('status')->oneOf(['private', 'public'])->required(); 236 | 237 | // GET /dashboard?createdAt=01.01.2016 => $dateTime == new DateTime("01.01.2016") 238 | // GET /dashboard?createdAt=invalid_date => A NotFoundException will be thrown 239 | $dateTime = $this->queryParameter('createdAt')->dateTime()->required(); 240 | 241 | // GET /dashboard?config={"a":true} => $json == ['a' => true] 242 | $json = $this->queryParameter('config')->json()->required(); 243 | 244 | // GET /dashboard?includeWidgets=true => $includeWidgets == true 245 | // GET /dashboard?includeWidgets=false => $includeWidgets == false 246 | // GET /dashboard?includeWidgets=0 => $includeWidgets == false 247 | // GET /dashboard?includeWidgets=abcde => A NotFoundException will be thrown 248 | $includeWidgets = $this->queryParameter('includeWidgets')->boolean()->required(); 249 | 250 | // GET /dashboard?includeWidgets=yes => $includeWidgets == true 251 | // GET /dashboard?includeWidgets=no => $includeWidgets == false 252 | $includeWidgets = $this->queryParameter('includeWidgets')->yesNoBoolean()->required(); 253 | 254 | // GET /image?scale=2.5 => $scale == 2.5 255 | $scale = $this->queryParameter('scale')->float()->required(); 256 | } 257 | } 258 | ``` 259 | 260 | All of these types also provide a `defaultsTo` variant. 261 | 262 | ###### Supported Data Types 263 | 264 | | Type | Code example | Input example | 265 | | ------------- | ------------- | ------------- | 266 | | **String** | `$this->queryParameter('name')->string()->required();` | `'John Doe'` | 267 | | **Comma-Separated String** | `$this->queryParameter('names')->commaSeparated()->string()->required();` | `'John Doe,John Oliver'` | 268 | | **Integer** | `$this->queryParameter('id')->int()->required();` | `'5'` | 269 | | **Comma-Separated Integer** | `$this->queryParameter('groupIds')->commaSeparated()->int()->required();` | `'5,6,7,8'` | 270 | | **Float** | `$this->queryParameter('ratio')->float()->required();` | `'0.98'` | 271 | | **Comma-Separated Float** | `$this->queryParameter('precipitation')->commaSeparated()->float()->required();` | `'0.98,1.24,5.21'` | 272 | | **DateTime** | `$this->queryParameter('timestamp')->dateTime()->required();` | `'2016-07-20'` | 273 | | **Comma-Separated DateTime** | `$this->queryParameter('eventTimes')->commaSeparated()->dateTime()->required();` | `'2016-07-20 13:10:50,2016-07-21 12:01:07'` | 274 | | **Boolean** | `$this->queryParameter('success')->boolean()->required();` | `'true'` | 275 | | **Comma-Separated Boolean** | `$this->queryParameter('answers')->commaSeparated()->boolean()->required();` | `'1,0,0,1'` | 276 | | **Yes/No Boolean** | `$this->queryParameter('success')->yesNoBoolean()->required();` | `'yes'` | 277 | | **Comma-Separated Yes/No Boolean** | `$this->queryParameter('answers')->commaSeparated()->yesNoBoolean()->required();` | `'y,n,n,y,n'` | 278 | | **JSON** | `$this->queryParameter('payload')->json()->required();` | `'{"event":"click","timestamp":"2016-07-20 13:10:50"}'` | 279 | | **Comma-Separated JSON** | `$this->queryParameter('events')->commaSeparated()->json()->required();` | `'{"event":"click","timestamp":"2016-07-20 13:10:50"},{"event":"add_to_basket","timestamp":"2016-07-20 13:11:01"}'` | 280 | 281 | 282 | ##### GET Requests: 283 | `$this->queryParameter($name)` tells the controller that we want a query parameter ([everything after the "?" is called the query string](https://en.wikipedia.org/wiki/Query_string)). This is usually what we want when dealing with GET requests 284 | 285 | ##### POST Requests: 286 | When we're dealing with a POST request, we need to use `$this->bodyParameter($name)` to access form fields or the ajax payload. 287 | 288 | ### Autocompletion 289 | 290 | The library allows you to take extensive use of autocompletion features of your IDE. E.g. after typing `$this->queryParameter('someParameter)->` 291 | your IDE will offer you all the possible input types, e.g. `string()` or `int()`. After picking a type, e.g. `string()`, your IDE will offer 292 | `required()` or `defaultsTo(defaultValue)` to specify the behavior when the parameter is not set. 293 | 294 | ![](https://github.com/mpscholten/request-parser/blob/master/images/autocomplete-anim.gif?raw=true) 295 | 296 | ![](https://github.com/mpscholten/request-parser/blob/master/images/autocompletion-type.png?raw=true) 297 | ![](https://github.com/mpscholten/request-parser/blob/master/images/autocompletion-required.png?raw=true) 298 | 299 | ### Static Analysis 300 | 301 | The library supports static analysis by your IDE. E.g. when having a parameter like `$createdAt = $this->queryParameter('createdAt')->dateTime()->required();`, 302 | your IDE will know that `$createdAt` is a `DateTime` object. This allows you to detect type errors while editing and also decreases the maintenance cost of 303 | an action because the types improve legibility. 304 | 305 | The library also decreases the risk of unexpected null values because parameters always have an explicit default value or are required. 306 | 307 | ### Error Handling 308 | 309 | When a parameter is required but not found or when validation fails, the library will throw an exception. The default exceptions are `\MPScholten\RequestParser\NotFoundException` and `\MPScholten\RequestParser\InvalidValueException`. 310 | The suggested way to handle the errors thrown by the library is to catch them inside your front controller: 311 | 312 | ```php 313 | try { 314 | $controller->$action(); 315 | } catch (NotFoundException $e) { 316 | echo $e->getMessage(); 317 | } catch (InvalidValueException $e) { 318 | echo $e->getMessage(); 319 | } 320 | ``` 321 | 322 | #### Using Custom Exception Classes 323 | 324 | ```php 325 | class MyController 326 | { 327 | use \MPScholten\RequestParser\Symfony\ControllerHelperTrait; 328 | 329 | public function __construct(Request $request) 330 | { 331 | $exceptionFactory = new ExceptionFactory(CustomNotFoundException::class, CustomInvalidValueException::class)); 332 | 333 | $config = new \MPScholten\RequestParser\Config(); 334 | $config->setExceptionFactory($exceptionFactory); 335 | 336 | $this->initRequestParser($request, $config); 337 | } 338 | } 339 | ``` 340 | 341 | #### Using Custom Exception Messages 342 | 343 | ##### Overriding Single Messages 344 | If you need to override the exception message thrown by the library just once or twice, you can do this by passing the exception messages as the first and second argument to `->required()`: 345 | 346 | ```php 347 | class DashboardController 348 | { 349 | public function show() 350 | { 351 | $dashboardId = $this->queryParameter('id')->int()->required("The dashboard id has to be a valid number", "No dashboard id given"); 352 | } 353 | } 354 | ``` 355 | 356 | ##### Overriding All Messages 357 | If you don't want to specify a custom exception message for all your actions, but still don't want to use the built-in exception messages, you can provide your own exception message generator: 358 | 359 | ```php 360 | 361 | class FriendlyExceptionMessageFactory extends \MPScholten\RequestParser\ExceptionMessageFactory 362 | { 363 | protected function createNotFoundMessage($parameterName) 364 | { 365 | return "Looks like $parameterName is missing :)"; 366 | } 367 | 368 | protected function createInvalidValueMessage($parameterName, $parameterValue, $expected) 369 | { 370 | return "Whoops :) $parameterName seems to be invalid. We're looking for $expected but you provided '$parameterValue'"; 371 | } 372 | } 373 | 374 | class MyController 375 | { 376 | use \MPScholten\RequestParser\Symfony\ControllerHelperTrait; 377 | 378 | public function __construct(Request $request) 379 | { 380 | $config = new \MPScholten\RequestParser\Config(); 381 | $config->setExceptionMessageFactory(new FriendlyExceptionMessageFactory()); 382 | 383 | $this->initRequestParser($request, $config); 384 | } 385 | } 386 | ``` 387 | 388 | Check it out [this example about custom exceptions](https://github.com/mpscholten/request-parser/blob/master/examples/custom-exception.php). 389 | 390 | 391 | ### Is It Production Ready? 392 | 393 | Absolutely. This library was initially developed at [quintly](https://www.quintly.com) and is extensively used in production since april 2015. Using it at scale in production means there's a a big focus on backwards compatibility and not breaking stuff. 394 | 395 | ### Tests 396 | 397 | ``` 398 | composer tests 399 | composer tests-coverage 400 | ``` 401 | 402 | ### Contributing 403 | 404 | Feel free to send pull requests! 405 | -------------------------------------------------------------------------------- /circle.yml: -------------------------------------------------------------------------------- 1 | machine: 2 | php: 3 | version: 5.5.9 4 | 5 | dependencies: 6 | pre: 7 | - sed -i 's/^;//' ~/.phpenv/versions/$(phpenv global)/etc/conf.d/xdebug.ini 8 | 9 | test: 10 | override: 11 | - vendor/bin/phpunit --coverage-html=$CIRCLE_ARTIFACTS 12 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mpscholten/request-parser", 3 | "authors": [ 4 | { 5 | "name": "Marc Scholten", 6 | "email": "marc@quintly.com" 7 | } 8 | ], 9 | "license": "MIT", 10 | "require": {}, 11 | "require-dev": { 12 | "phpunit/phpunit": "3.7.*", 13 | "symfony/http-foundation": "3.1.*", 14 | "symfony/psr-http-message-bridge": "^0.2.0", 15 | "zendframework/zend-diactoros": "^1.3" 16 | }, 17 | "autoload": { 18 | "psr-4": {"MPScholten\\RequestParser\\": "src/"} 19 | }, 20 | "scripts": { 21 | "tests" : "vendor/bin/phpunit", 22 | "tests-coverage" : "vendor/bin/phpunit --coverage-text" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /examples/autocompletion.php: -------------------------------------------------------------------------------- 1 | initRequestParser($request); 19 | } 20 | 21 | public function autcompletion() 22 | { 23 | // Type `$name = $this->queryParameter('name')->` below: 24 | 25 | // Now you should see something along the lines of: 26 | // 27 | // $name = $this->queryParameter('name')-> 28 | // dateTime() 29 | // int() 30 | // json() 31 | // oneOf(validValues : array) 32 | // string() 33 | // Let's pick `string()` for now 34 | // So now you should have 35 | // $name = $this->queryParameter('name')->string()-> 36 | // 37 | // Autocompletion pops up again, now you should see something along the lines of: 38 | // $name = $this->queryParameter('name')->string()-> 39 | // required() 40 | // defaultsTo(defaultValue : string) 41 | } 42 | } 43 | 44 | $controller = new MyController($request); 45 | $action = $request->get('action'); 46 | 47 | try { 48 | echo $controller->$action(); 49 | } catch (\MPScholten\RequestParser\NotFoundException $e) { 50 | echo $e->getMessage(); 51 | } 52 | -------------------------------------------------------------------------------- /examples/custom-exception.php: -------------------------------------------------------------------------------- 1 | setExceptionFactory(new ExceptionFactory(CustomException::class, CustomException::class)); 39 | $config->setExceptionMessageFactory(new FriendlyExceptionMessageFactory()); 40 | 41 | $this->initRequestParser($request, $config); 42 | } 43 | 44 | public function hello() 45 | { 46 | $name = $this->queryParameter('name')->string()->required(); // Will now throw the CustomException 47 | 48 | return "Hello $name"; 49 | } 50 | } 51 | 52 | $controller = new MyController($request); 53 | $action = $request->get('action'); 54 | 55 | try { 56 | echo $controller->$action(); 57 | } catch (CustomException $e) { 58 | echo $e->getMessage(); 59 | } 60 | -------------------------------------------------------------------------------- /examples/not-symfony.php: -------------------------------------------------------------------------------- 1 | request = $request; 26 | $this->config = $config; 27 | } 28 | 29 | public function createQueryParser() 30 | { 31 | return new MPScholten\RequestParser\RequestParser( 32 | function ($parameterName) { 33 | if (isset($this->request[$parameterName])) { 34 | return $this->request[$parameterName]; 35 | } 36 | 37 | return null; 38 | }, 39 | $this->config 40 | ); 41 | } 42 | 43 | public function createBodyParser() 44 | { 45 | return new MPScholten\RequestParser\RequestParser( 46 | function ($parameterName) { 47 | if (isset($this->request[$parameterName])) { 48 | return $this->request[$parameterName]; 49 | } 50 | 51 | return null; 52 | }, 53 | $this->config 54 | ); 55 | } 56 | } 57 | 58 | trait CustomControllerHelperTrait 59 | { 60 | use \MPScholten\RequestParser\BaseControllerHelperTrait; 61 | 62 | /** 63 | * Will be called during the `initRequestParser()` call in `MyController` 64 | */ 65 | protected final function createRequestParserFactory($request, $config) 66 | { 67 | return new CustomRequestParserFactory($request, $config); 68 | } 69 | } 70 | 71 | class MyController 72 | { 73 | use CustomControllerHelperTrait; 74 | 75 | public function __construct() 76 | { 77 | if ($_SERVER['REQUEST_METHOD'] === 'GET') { 78 | $request = $_GET; 79 | } else { 80 | $request = $_POST; 81 | } 82 | 83 | $this->initRequestParser($request); 84 | } 85 | 86 | public function hello() 87 | { 88 | $name = $this->queryParameter('name')->string()->required(); 89 | 90 | return "Hello $name"; 91 | } 92 | 93 | public function helloWithDefault() 94 | { 95 | $name = $this->queryParameter('name')->string()->defaultsTo('unknown'); 96 | 97 | return "Hello $name"; 98 | } 99 | 100 | public function json() 101 | { 102 | $payload = $this->queryParameter('payload')->json()->required(); 103 | 104 | return print_r($payload, true); 105 | } 106 | } 107 | 108 | $controller = new MyController(); 109 | $action = $_GET['action']; 110 | 111 | try { 112 | echo $controller->$action(); 113 | } catch (\MPScholten\RequestParser\NotFoundException $e) { 114 | echo $e->getMessage(); 115 | } 116 | -------------------------------------------------------------------------------- /examples/psr7.php: -------------------------------------------------------------------------------- 1 | createRequest($symfonyRequest); 23 | 24 | class MyController 25 | { 26 | use ControllerHelperTrait; 27 | 28 | public function __construct(ServerRequestInterface $request) 29 | { 30 | $this->initRequestParser($request); 31 | } 32 | 33 | public function hello() 34 | { 35 | $name = $this->queryParameter('name')->string()->required(); 36 | 37 | return "Hello $name"; 38 | } 39 | 40 | public function helloWithDefault() 41 | { 42 | $name = $this->queryParameter('name')->string()->defaultsTo('unknown'); 43 | 44 | return "Hello $name"; 45 | } 46 | 47 | public function json() 48 | { 49 | $payload = $this->queryParameter('payload')->json()->required(); 50 | 51 | return print_r($payload, true); 52 | } 53 | } 54 | 55 | $controller = new MyController($request); 56 | $action = $request->getQueryParams()['action']; 57 | 58 | try { 59 | echo $controller->$action(); 60 | } catch (\MPScholten\RequestParser\NotFoundException $e) { 61 | echo $e->getMessage(); 62 | } 63 | -------------------------------------------------------------------------------- /examples/symfony.php: -------------------------------------------------------------------------------- 1 | initRequestParser($request); 30 | } 31 | 32 | public function hello() 33 | { 34 | $name = $this->queryParameter('name')->string()->required(); 35 | 36 | return "Hello $name"; 37 | } 38 | 39 | public function helloWithDefault() 40 | { 41 | $name = $this->queryParameter('name')->string()->defaultsTo('unknown'); 42 | 43 | return "Hello $name"; 44 | } 45 | 46 | public function json() 47 | { 48 | $payload = $this->queryParameter('payload')->json()->required(); 49 | 50 | return print_r($payload, true); 51 | } 52 | 53 | public function intArray() 54 | { 55 | $userIds = $this->queryParameter('userIds')->commaSeparated()->int()->required(); 56 | return print_r($userIds, true); 57 | } 58 | 59 | public function dateTimeArray() 60 | { 61 | $userIds = $this->queryParameter('timestamps')->commaSeparated()->dateTime()->required(); 62 | return print_r($userIds, true); 63 | } 64 | 65 | public function booleanArray() 66 | { 67 | $userIds = $this->queryParameter('answers')->commaSeparated()->boolean()->required(); 68 | return print_r($userIds, true); 69 | } 70 | 71 | public function jsonArray() 72 | { 73 | $userIds = $this->queryParameter('events')->commaSeparated()->json()->required(); 74 | return print_r($userIds, true); 75 | } 76 | } 77 | 78 | $controller = new MyController($request); 79 | $action = $request->get('action'); 80 | 81 | try { 82 | echo $controller->$action(); 83 | } catch (\MPScholten\RequestParser\NotFoundException $e) { 84 | echo $e->getMessage(); 85 | } 86 | -------------------------------------------------------------------------------- /images/autocomplete-anim.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mpscholten/request-parser/de69c3b746fdea5138ae27ed55ba44617399f71a/images/autocomplete-anim.gif -------------------------------------------------------------------------------- /images/autocompletion-required.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mpscholten/request-parser/de69c3b746fdea5138ae27ed55ba44617399f71a/images/autocompletion-required.png -------------------------------------------------------------------------------- /images/autocompletion-type.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mpscholten/request-parser/de69c3b746fdea5138ae27ed55ba44617399f71a/images/autocompletion-type.png -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 6 | 7 | ./tests/ 8 | 9 | 10 | 11 | 12 | ./src 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/AbstractValueParser.php: -------------------------------------------------------------------------------- 1 | config = $config; 23 | $this->name = $name; 24 | $this->unparsedValue = $value; 25 | 26 | if ($value === null) { 27 | $this->notFound = true; 28 | } else { 29 | $parsed = $this->parse($value); 30 | if ($parsed === null) { 31 | $this->invalid = true; 32 | } else { 33 | $this->value = $parsed; 34 | } 35 | } 36 | } 37 | 38 | abstract protected function parse($value); 39 | 40 | public function defaultsTo($defaultValue) 41 | { 42 | return ($this->notFound || $this->invalid) ? $defaultValue : $this->value; 43 | } 44 | 45 | public function required($invalidValueMessage = null, $notFoundMessage = null) 46 | { 47 | if ($this->invalid) { 48 | if ($invalidValueMessage === null) { 49 | $invalidValueMessage = $this->config->getExceptionMessageFactory()->createInvalidValueMessage($this->name, $this->unparsedValue, $this->describe()); 50 | } 51 | 52 | throw $this->config->getExceptionFactory()->createInvalidValueException($invalidValueMessage); 53 | } elseif ($this->notFound) { 54 | if ($notFoundMessage === null) { 55 | $notFoundMessage = $this->config->getExceptionMessageFactory()->createNotFoundMessage($this->name); 56 | } 57 | 58 | throw $this->config->getExceptionFactory()->createNotFoundException($notFoundMessage); 59 | } 60 | 61 | return $this->value; 62 | } 63 | 64 | abstract protected function describe(); 65 | } 66 | -------------------------------------------------------------------------------- /src/BaseControllerHelperTrait.php: -------------------------------------------------------------------------------- 1 | createRequestParserFactory($request, $config); 21 | $this->queryParser = $requestParserFactory->createQueryParser(); 22 | $this->bodyParser = $requestParserFactory->createBodyParser(); 23 | } 24 | 25 | /** 26 | * Use this method to access the query parameters of the request. 27 | * 28 | * $page = $this->queryParameter('page')->int()->defaultsTo(0) 29 | * 30 | * @param string $name 31 | * @return TypeParser 32 | */ 33 | protected function queryParameter($name) 34 | { 35 | return $this->queryParser->get($name); 36 | } 37 | 38 | /** 39 | * Use this method to access the body parameters of the request (e.g. $_POST). 40 | * 41 | * $password = $this->bodyParameter('password')->string()->required() 42 | * 43 | * @param string $name 44 | * @return TypeParser 45 | */ 46 | protected function bodyParameter($name) 47 | { 48 | return $this->bodyParser->get($name); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/BooleanParser.php: -------------------------------------------------------------------------------- 1 | $item) { 16 | if (strtoupper($item) === 'TRUE' || $item === '1') { 17 | $booleanArr[$key] = true; 18 | continue; 19 | } 20 | if (strtoupper($item) === 'FALSE' || $item === '0') { 21 | $booleanArr[$key] = false; 22 | continue; 23 | } 24 | return null; 25 | } 26 | return $booleanArr; 27 | } 28 | 29 | /** 30 | * @param boolean[] $defaultValue 31 | * @return boolean[] 32 | */ 33 | public function defaultsTo($defaultValue) 34 | { 35 | return parent::defaultsTo($defaultValue); 36 | } 37 | 38 | /** 39 | * @throws \Exception 40 | * @return boolean[] 41 | */ 42 | public function required($invalidValueMessage = null, $notFoundMessage = null) 43 | { 44 | return parent::required($invalidValueMessage, $notFoundMessage); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/CommaSeparatedDateTimeParser.php: -------------------------------------------------------------------------------- 1 | $item) { 16 | try { 17 | $dateTimeArr[$key] = new \DateTime($item); 18 | } catch (\Exception $e) { 19 | return null; 20 | } 21 | } 22 | return $dateTimeArr; 23 | } 24 | 25 | /** 26 | * @param \DateTime[] $defaultValue 27 | * @return \DateTime[] 28 | */ 29 | public function defaultsTo($defaultValue) 30 | { 31 | return parent::defaultsTo($defaultValue); 32 | } 33 | 34 | /** 35 | * @throws \Exception 36 | * @return \DateTime[] 37 | */ 38 | public function required($invalidValueMessage = null, $notFoundMessage = null) 39 | { 40 | return parent::required($invalidValueMessage, $notFoundMessage); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/CommaSeparatedFloatParser.php: -------------------------------------------------------------------------------- 1 | config = $config; 14 | $this->value = $value; 15 | $this->name = $name; 16 | } 17 | 18 | public function int() 19 | { 20 | return new CommaSeparatedIntParser($this->config, $this->name, $this->value); 21 | } 22 | 23 | public function float() 24 | { 25 | return new CommaSeparatedFloatParser($this->config, $this->name, $this->value); 26 | } 27 | 28 | public function string() 29 | { 30 | return new CommaSeparatedStringParser($this->config, $this->name, $this->value); 31 | } 32 | 33 | public function dateTime() 34 | { 35 | return new CommaSeparatedDateTimeParser($this->config, $this->name, $this->value); 36 | } 37 | 38 | public function json() 39 | { 40 | return new CommaSeparatedJsonParser($this->config, $this->name, $this->value); 41 | } 42 | 43 | public function yesNoBoolean() 44 | { 45 | return new CommaSeparatedYesNoBooleanParser($this->config, $this->name, $this->value); 46 | } 47 | 48 | public function boolean() 49 | { 50 | return new CommaSeparatedBooleanParser($this->config, $this->name, $this->value); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/CommaSeparatedStringParser.php: -------------------------------------------------------------------------------- 1 | $item) { 16 | if (strtoupper($item) === 'YES' || $item === 'Y') { 17 | $booleanArr[$key] = true; 18 | continue; 19 | } 20 | if (strtoupper($item) === 'NO' || $item === 'N') { 21 | $booleanArr[$key] = false; 22 | continue; 23 | } 24 | return null; 25 | } 26 | return $booleanArr; 27 | } 28 | 29 | /** 30 | * @param boolean[] $defaultValue 31 | * @return boolean[] 32 | */ 33 | public function defaultsTo($defaultValue) 34 | { 35 | return parent::defaultsTo($defaultValue); 36 | } 37 | 38 | /** 39 | * @throws \Exception 40 | * @return boolean[] 41 | */ 42 | public function required($invalidValueMessage = null, $notFoundMessage = null) 43 | { 44 | return parent::required($invalidValueMessage, $notFoundMessage); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/Config.php: -------------------------------------------------------------------------------- 1 | exceptionFactory = null; 13 | $this->exceptionMessageFactory = null; 14 | } 15 | 16 | public function setExceptionFactory(ExceptionFactory $exceptionFactory) 17 | { 18 | $this->exceptionFactory = $exceptionFactory; 19 | } 20 | 21 | public function setExceptionMessageFactory(ExceptionMessageFactory $messageFactory) 22 | { 23 | $this->exceptionMessageFactory = $messageFactory; 24 | } 25 | 26 | public function getExceptionFactory() 27 | { 28 | if ($this->exceptionFactory === null) { 29 | $this->exceptionFactory = new ExceptionFactory(); 30 | } 31 | 32 | return $this->exceptionFactory; 33 | } 34 | 35 | public function getExceptionMessageFactory() 36 | { 37 | if ($this->exceptionMessageFactory === null) { 38 | $this->exceptionMessageFactory = new ExceptionMessageFactory(); 39 | } 40 | 41 | return $this->exceptionMessageFactory; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/DateTimeParser.php: -------------------------------------------------------------------------------- 1 | notFoundExceptionClass = $notFoundExceptionClass; 16 | $this->invalidValueExceptionClass = $invalidValueExceptionClass; 17 | } 18 | 19 | /** 20 | * @param string $message 21 | * @return NotFoundException|\Exception 22 | */ 23 | public function createNotFoundException($message) 24 | { 25 | return new $this->notFoundExceptionClass($message); 26 | } 27 | 28 | /* 29 | * @param string $message 30 | * @return InvalidValueException|\Exception 31 | */ 32 | public function createInvalidValueException($message) 33 | { 34 | return new $this->invalidValueExceptionClass($message); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/ExceptionMessageFactory.php: -------------------------------------------------------------------------------- 1 | config, $this->name, $this->value, $minValue, $maxValue); 49 | } 50 | 51 | /** 52 | * @param int $minValue 53 | * @return FloatLargerThanParser 54 | */ 55 | public function largerThan($minValue) 56 | { 57 | return new FloatLargerThanParser($this->config, $this->name, $this->value, $minValue); 58 | } 59 | 60 | /** 61 | * @param int $minValue 62 | * @return FloatLargerThanOrEqualToParser 63 | */ 64 | public function largerThanOrEqualTo($minValue) 65 | { 66 | return new FloatLargerThanOrEqualToParser($this->config, $this->name, $this->value, $minValue); 67 | } 68 | 69 | /** 70 | * @param int $maxValue 71 | * @return FloatSmallerThanParser 72 | */ 73 | public function smallerThan($maxValue) 74 | { 75 | return new FloatSmallerThanParser($this->config, $this->name, $this->value, $maxValue); 76 | } 77 | 78 | /** 79 | * @param int $maxValue 80 | * @return FloatSmallerThanOrEqualToParser 81 | */ 82 | public function smallerThanOrEqualTo($maxValue) 83 | { 84 | return new FloatSmallerThanOrEqualToParser($this->config, $this->name, $this->value, $maxValue); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/IntParser.php: -------------------------------------------------------------------------------- 1 | config, $this->name, $this->value, $minValue, $maxValue); 49 | } 50 | 51 | /** 52 | * @param int $minValue 53 | * @return IntLargerThanParser 54 | */ 55 | public function largerThan($minValue) 56 | { 57 | return new IntLargerThanParser($this->config, $this->name, $this->value, $minValue); 58 | } 59 | 60 | /** 61 | * @param int $minValue 62 | * @return IntLargerThanOrEqualToParser 63 | */ 64 | public function largerThanOrEqualTo($minValue) 65 | { 66 | return new IntLargerThanOrEqualToParser($this->config, $this->name, $this->value, $minValue); 67 | } 68 | 69 | /** 70 | * @param int $maxValue 71 | * @return IntSmallerThanParser 72 | */ 73 | public function smallerThan($maxValue) 74 | { 75 | return new IntSmallerThanParser($this->config, $this->name, $this->value, $maxValue); 76 | } 77 | 78 | /** 79 | * @param int $maxValue 80 | * @return IntSmallerThanOrEqualToParser 81 | */ 82 | public function smallerThanOrEqualTo($maxValue) 83 | { 84 | return new IntSmallerThanOrEqualToParser($this->config, $this->name, $this->value, $maxValue); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/InvalidValueException.php: -------------------------------------------------------------------------------- 1 | initRequestParser($request, function($parameter) { 17 | * throw new CustomException($message); 18 | * }); 19 | * } 20 | * } 21 | * 22 | * This class transforms such a closure into a `ExceptionFactory` to keep b.c. 23 | * 24 | * For b.c. reasons invalid values are handled like not found values, so for 25 | * an integer parameter with value "invalidInt" it just says "Parameter not found" 26 | * instead of "Invalid value for integer". 27 | */ 28 | class LegacyExceptionFactory extends ExceptionFactory 29 | { 30 | private $closure; 31 | 32 | public function __construct(callable $closure) 33 | { 34 | $this->closure = $closure; 35 | } 36 | 37 | public function createNotFoundException($message) 38 | { 39 | return call_user_func($this->closure, $message); 40 | } 41 | 42 | public function createInvalidValueException($message) 43 | { 44 | return call_user_func($this->closure, $message); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/LegacyExceptionMessageFactory.php: -------------------------------------------------------------------------------- 1 | request = $request; 17 | $this->config = $config; 18 | } 19 | 20 | public function createQueryParser() 21 | { 22 | $query = $this->request->getQueryParams(); 23 | 24 | $readParameter = function ($name) use ($query) { 25 | if (!isset($query[$name])) { 26 | return null; 27 | } 28 | 29 | return $query[$name]; 30 | }; 31 | 32 | return new RequestParser($readParameter, $this->config); 33 | } 34 | 35 | public function createBodyParser() 36 | { 37 | $body = $this->request->getParsedBody(); 38 | 39 | $readParameter = function ($name) use ($body) { 40 | if (!isset($body[$name])) { 41 | return null; 42 | } 43 | 44 | return $body[$name]; 45 | }; 46 | 47 | return new RequestParser($readParameter, $this->config); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/RequestParser.php: -------------------------------------------------------------------------------- 1 | setExceptionMessageFactory(new LegacyExceptionMessageFactory()); 30 | $config->setExceptionFactory(new LegacyExceptionFactory($exceptionFactory)); 31 | } 32 | 33 | $this->readParameter = $readParameter; 34 | $this->config = $config; 35 | } 36 | 37 | protected final function readValue($name) 38 | { 39 | return call_user_func($this->readParameter, $name); 40 | } 41 | 42 | public function get($name) 43 | { 44 | return new TypeParser($this->config, $name, $this->readValue($name)); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/RequestParserFactory.php: -------------------------------------------------------------------------------- 1 | value === '') { 52 | return $defaultValue; 53 | } 54 | 55 | return $this->defaultsTo($defaultValue); 56 | } 57 | 58 | public function url() 59 | { 60 | return new UrlParser($this->config, $this->name, $this->value); 61 | } 62 | 63 | public function email() 64 | { 65 | return new EmailParser($this->config, $this->name, $this->value); 66 | } 67 | 68 | public function trim() 69 | { 70 | return new TrimParser($this->config, $this->name, $this->value, TrimParser::TRIM); 71 | } 72 | 73 | public function leftTrim() 74 | { 75 | return new TrimParser($this->config, $this->name, $this->value, TrimParser::LEFT_TRIM); 76 | } 77 | 78 | public function rightTrim() 79 | { 80 | return new TrimParser($this->config, $this->name, $this->value, TrimParser::RIGHT_TRIM); 81 | } 82 | 83 | /** 84 | * @param int $minValue 85 | * @param int $maxValue 86 | * 87 | * @return StringLengthBetween 88 | */ 89 | public function lengthBetween($minValue, $maxValue) 90 | { 91 | return new StringLengthBetween($this->config, $this->name, $this->value, $minValue, $maxValue); 92 | } 93 | 94 | /** 95 | * @param int $minValue 96 | * 97 | * @return StringLengthLargerThanParser 98 | */ 99 | public function lengthLargerThan($minValue) 100 | { 101 | return new StringLengthLargerThanParser($this->config, $this->name, $this->value, $minValue); 102 | } 103 | 104 | /** 105 | * @param int $minValue 106 | * 107 | * @return StringLengthLargerThanOrEqualToParser 108 | */ 109 | public function lengthLargerThanOrEqualTo($minValue) 110 | { 111 | return new StringLengthLargerThanOrEqualToParser($this->config, $this->name, $this->value, $minValue); 112 | } 113 | 114 | /** 115 | * @param int $maxValue 116 | * 117 | * @return StringLengthSmallerThanParser 118 | */ 119 | public function lengthSmallerThan($maxValue) 120 | { 121 | return new StringLengthSmallerThanParser($this->config, $this->name, $this->value, $maxValue); 122 | } 123 | 124 | /** 125 | * @param int $maxValue 126 | * 127 | * @return StringLengthSmallerThanOrEqualToParser 128 | */ 129 | public function lengthSmallerThanOrEqualTo($maxValue) 130 | { 131 | return new StringLengthSmallerThanOrEqualToParser($this->config, $this->name, $this->value, $maxValue); 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /src/Symfony/ControllerHelperTrait.php: -------------------------------------------------------------------------------- 1 | request = $request; 17 | $this->config = $config; 18 | } 19 | 20 | public function createQueryParser() 21 | { 22 | $readParameter = function ($name) { 23 | return $this->request->query->get($name, null); 24 | }; 25 | 26 | return new RequestParser($readParameter, $this->config); 27 | } 28 | 29 | public function createBodyParser() 30 | { 31 | $readParameter = function ($name) { 32 | return $this->request->request->get($name, null); 33 | }; 34 | 35 | return new RequestParser($readParameter, $this->config); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/TrimParser.php: -------------------------------------------------------------------------------- 1 | trimType = $trimType; 16 | parent::__construct($config, $name, $value); 17 | } 18 | 19 | protected function describe() 20 | { 21 | return "a text string"; 22 | } 23 | 24 | protected function parse($value) 25 | { 26 | if ($this->trimType === self::TRIM) { 27 | return trim((string) $value); 28 | } elseif ($this->trimType === self::LEFT_TRIM) { 29 | return ltrim((string) $value); 30 | } elseif ($this->trimType === self::RIGHT_TRIM) { 31 | return rtrim((string) $value); 32 | } 33 | return (string) $value; 34 | } 35 | 36 | /** 37 | * @param string $defaultValue 38 | * @return string 39 | */ 40 | public function defaultsTo($defaultValue) 41 | { 42 | return parent::defaultsTo($defaultValue); 43 | } 44 | 45 | /** 46 | * @throws \Exception 47 | * @return string 48 | */ 49 | public function required($invalidValueMessage = null, $notFoundMessage = null) 50 | { 51 | return parent::required($invalidValueMessage, $notFoundMessage); 52 | } 53 | 54 | /** 55 | * @param string $defaultValue 56 | * @return string 57 | */ 58 | public function defaultsToIfEmpty($defaultValue) 59 | { 60 | if ($this->value === '') { 61 | return $defaultValue; 62 | } 63 | 64 | return $this->defaultsTo($defaultValue); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/TypeParser.php: -------------------------------------------------------------------------------- 1 | value = $value; 16 | $this->name = $name; 17 | $this->config = $config; 18 | } 19 | 20 | public function int() 21 | { 22 | return new IntParser($this->config, $this->name, $this->value); 23 | } 24 | 25 | public function float() 26 | { 27 | return new FloatParser($this->config, $this->name, $this->value); 28 | } 29 | 30 | public function string() 31 | { 32 | return new StringParser($this->config, $this->name, $this->value); 33 | } 34 | 35 | public function oneOf(array $validValues) 36 | { 37 | return new OneOfParser($this->config, $this->name, $this->value, $validValues); 38 | } 39 | 40 | public function dateTime() 41 | { 42 | return new DateTimeParser($this->config, $this->name, $this->value); 43 | } 44 | 45 | public function json() 46 | { 47 | return new JsonParser($this->config, $this->name, $this->value); 48 | } 49 | 50 | public function yesNoBoolean() 51 | { 52 | return new YesNoBooleanParser($this->config, $this->name, $this->value); 53 | } 54 | 55 | public function boolean() 56 | { 57 | return new BooleanParser($this->config, $this->name, $this->value); 58 | } 59 | 60 | public function commaSeparated() 61 | { 62 | return new CommaSeparatedParser($this->config, $this->name, $this->value); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/Validator/AbstractBetweenParser.php: -------------------------------------------------------------------------------- 1 | minValue = $minValue; 16 | $this->maxValue = $maxValue; 17 | parent::__construct($config, $name, $value); 18 | } 19 | 20 | protected function parse($value) 21 | { 22 | if ($value >= $this->minValue && $value <= $this->maxValue) { 23 | return $value; 24 | } 25 | return null; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Validator/AbstractLargerThanOrEqualToParser.php: -------------------------------------------------------------------------------- 1 | minValue = $minValue; 15 | parent::__construct($config, $name, $value); 16 | } 17 | 18 | protected function parse($value) 19 | { 20 | if ($value >= $this->minValue) { 21 | return $value; 22 | } 23 | return null; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Validator/AbstractLargerThanParser.php: -------------------------------------------------------------------------------- 1 | minValue = $minValue; 15 | parent::__construct($config, $name, $value); 16 | } 17 | 18 | protected function parse($value) 19 | { 20 | if ($value > $this->minValue) { 21 | return $value; 22 | } 23 | return null; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Validator/AbstractSmallerThanOrEqualToParser.php: -------------------------------------------------------------------------------- 1 | maxValue = $maxValue; 15 | parent::__construct($config, $name, $value); 16 | } 17 | 18 | protected function parse($value) 19 | { 20 | if ($value <= $this->maxValue) { 21 | return $value; 22 | } 23 | return null; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Validator/AbstractSmallerThanParser.php: -------------------------------------------------------------------------------- 1 | maxValue = $maxValue; 15 | parent::__construct($config, $name, $value); 16 | } 17 | 18 | protected function parse($value) 19 | { 20 | if ($value < $this->maxValue) { 21 | return $value; 22 | } 23 | return null; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Validator/EmailParser.php: -------------------------------------------------------------------------------- 1 | value === '') { 47 | return $defaultValue; 48 | } 49 | 50 | return $this->defaultsTo($defaultValue); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Validator/FloatBetweenParser.php: -------------------------------------------------------------------------------- 1 | minValue and $this->maxValue"; 10 | } 11 | 12 | /** 13 | * @param $value 14 | * @return float 15 | */ 16 | protected function parse($value) 17 | { 18 | if (!is_numeric($value)) { 19 | return null; 20 | } 21 | $value = (float) $value; 22 | return parent::parse($value); 23 | } 24 | 25 | /** 26 | * @param float $defaultValue 27 | * @return float 28 | */ 29 | public function defaultsTo($defaultValue) 30 | { 31 | return parent::defaultsTo($defaultValue); 32 | } 33 | 34 | /** 35 | * @throws \Exception 36 | * @param string $invalidValueMessage 37 | * @param string $notFoundMessage 38 | * @return float 39 | */ 40 | public function required($invalidValueMessage = null, $notFoundMessage = null) 41 | { 42 | return parent::required($invalidValueMessage, $notFoundMessage); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Validator/FloatLargerThanOrEqualToParser.php: -------------------------------------------------------------------------------- 1 | minValue"; 10 | } 11 | 12 | /** 13 | * @param $value 14 | * @return int 15 | */ 16 | protected function parse($value) 17 | { 18 | if (!is_numeric($value)) { 19 | return null; 20 | } 21 | $value = (float) $value; 22 | return parent::parse($value); 23 | } 24 | 25 | /** 26 | * @param float $defaultValue 27 | * @return float 28 | */ 29 | public function defaultsTo($defaultValue) 30 | { 31 | return parent::defaultsTo($defaultValue); 32 | } 33 | 34 | /** 35 | * @throws \Exception 36 | * @param string $invalidValueMessage 37 | * @param string $notFoundMessage 38 | * @return float 39 | */ 40 | public function required($invalidValueMessage = null, $notFoundMessage = null) 41 | { 42 | return parent::required($invalidValueMessage, $notFoundMessage); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Validator/FloatLargerThanParser.php: -------------------------------------------------------------------------------- 1 | minValue"; 10 | } 11 | 12 | /** 13 | * @param $value 14 | * @return int 15 | */ 16 | protected function parse($value) 17 | { 18 | if (!is_numeric($value)) { 19 | return null; 20 | } 21 | $value = (float) $value; 22 | return parent::parse($value); 23 | } 24 | 25 | /** 26 | * @param float $defaultValue 27 | * @return float 28 | */ 29 | public function defaultsTo($defaultValue) 30 | { 31 | return parent::defaultsTo($defaultValue); 32 | } 33 | 34 | /** 35 | * @throws \Exception 36 | * @param string $invalidValueMessage 37 | * @param string $notFoundMessage 38 | * @return float 39 | */ 40 | public function required($invalidValueMessage = null, $notFoundMessage = null) 41 | { 42 | return parent::required($invalidValueMessage, $notFoundMessage); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Validator/FloatSmallerThanOrEqualToParser.php: -------------------------------------------------------------------------------- 1 | maxValue"; 10 | } 11 | 12 | /** 13 | * @param $value 14 | * @return int 15 | */ 16 | protected function parse($value) 17 | { 18 | if (!is_numeric($value)) { 19 | return null; 20 | } 21 | $value = (float) $value; 22 | return parent::parse($value); 23 | } 24 | 25 | /** 26 | * @param float $defaultValue 27 | * @return float 28 | */ 29 | public function defaultsTo($defaultValue) 30 | { 31 | return parent::defaultsTo($defaultValue); 32 | } 33 | 34 | /** 35 | * @throws \Exception 36 | * @param string $invalidValueMessage 37 | * @param string $notFoundMessage 38 | * @return float 39 | */ 40 | public function required($invalidValueMessage = null, $notFoundMessage = null) 41 | { 42 | return parent::required($invalidValueMessage, $notFoundMessage); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Validator/FloatSmallerThanParser.php: -------------------------------------------------------------------------------- 1 | maxValue"; 10 | } 11 | 12 | /** 13 | * @param $value 14 | * @return int 15 | */ 16 | protected function parse($value) 17 | { 18 | if (!is_numeric($value)) { 19 | return null; 20 | } 21 | $value = (float) $value; 22 | return parent::parse($value); 23 | } 24 | 25 | /** 26 | * @param float $defaultValue 27 | * @return float 28 | */ 29 | public function defaultsTo($defaultValue) 30 | { 31 | return parent::defaultsTo($defaultValue); 32 | } 33 | 34 | /** 35 | * @throws \Exception 36 | * @param string $invalidValueMessage 37 | * @param string $notFoundMessage 38 | * @return float 39 | */ 40 | public function required($invalidValueMessage = null, $notFoundMessage = null) 41 | { 42 | return parent::required($invalidValueMessage, $notFoundMessage); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Validator/IntBetweenParser.php: -------------------------------------------------------------------------------- 1 | minValue and $this->maxValue"; 10 | } 11 | 12 | /** 13 | * @param $value 14 | * @return int 15 | */ 16 | protected function parse($value) 17 | { 18 | if (!is_numeric($value)) { 19 | return null; 20 | } 21 | $value = (int) $value; 22 | return parent::parse($value); 23 | } 24 | 25 | /** 26 | * @param int $defaultValue 27 | * @return int 28 | */ 29 | public function defaultsTo($defaultValue) 30 | { 31 | return parent::defaultsTo($defaultValue); 32 | } 33 | 34 | /** 35 | * @throws \Exception 36 | * @param string $invalidValueMessage 37 | * @param string $notFoundMessage 38 | * @return int 39 | */ 40 | public function required($invalidValueMessage = null, $notFoundMessage = null) 41 | { 42 | return parent::required($invalidValueMessage, $notFoundMessage); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Validator/IntLargerThanOrEqualToParser.php: -------------------------------------------------------------------------------- 1 | minValue"; 10 | } 11 | 12 | /** 13 | * @param $value 14 | * @return int 15 | */ 16 | protected function parse($value) 17 | { 18 | if (!is_numeric($value)) { 19 | return null; 20 | } 21 | $value = (int) $value; 22 | return parent::parse($value); 23 | } 24 | 25 | /** 26 | * @param int $defaultValue 27 | * @return int 28 | */ 29 | public function defaultsTo($defaultValue) 30 | { 31 | return parent::defaultsTo($defaultValue); 32 | } 33 | 34 | /** 35 | * @throws \Exception 36 | * @param string $invalidValueMessage 37 | * @param string $notFoundMessage 38 | * @return int 39 | */ 40 | public function required($invalidValueMessage = null, $notFoundMessage = null) 41 | { 42 | return parent::required($invalidValueMessage, $notFoundMessage); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Validator/IntLargerThanParser.php: -------------------------------------------------------------------------------- 1 | minValue"; 10 | } 11 | 12 | /** 13 | * @param $value 14 | * @return int 15 | */ 16 | protected function parse($value) 17 | { 18 | if (!is_numeric($value)) { 19 | return null; 20 | } 21 | $value = (int) $value; 22 | return parent::parse($value); 23 | } 24 | 25 | /** 26 | * @param int $defaultValue 27 | * @return int 28 | */ 29 | public function defaultsTo($defaultValue) 30 | { 31 | return parent::defaultsTo($defaultValue); 32 | } 33 | 34 | /** 35 | * @throws \Exception 36 | * @param string $invalidValueMessage 37 | * @param string $notFoundMessage 38 | * @return int 39 | */ 40 | public function required($invalidValueMessage = null, $notFoundMessage = null) 41 | { 42 | return parent::required($invalidValueMessage, $notFoundMessage); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Validator/IntSmallerThanOrEqualToParser.php: -------------------------------------------------------------------------------- 1 | maxValue"; 10 | } 11 | 12 | /** 13 | * @param $value 14 | * @return int 15 | */ 16 | protected function parse($value) 17 | { 18 | if (!is_numeric($value)) { 19 | return null; 20 | } 21 | $value = (int) $value; 22 | return parent::parse($value); 23 | } 24 | 25 | /** 26 | * @param int $defaultValue 27 | * @return int 28 | */ 29 | public function defaultsTo($defaultValue) 30 | { 31 | return parent::defaultsTo($defaultValue); 32 | } 33 | 34 | /** 35 | * @throws \Exception 36 | * @param string $invalidValueMessage 37 | * @param string $notFoundMessage 38 | * @return int 39 | */ 40 | public function required($invalidValueMessage = null, $notFoundMessage = null) 41 | { 42 | return parent::required($invalidValueMessage, $notFoundMessage); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Validator/IntSmallerThanParser.php: -------------------------------------------------------------------------------- 1 | maxValue"; 10 | } 11 | 12 | /** 13 | * @param $value 14 | * @return int 15 | */ 16 | protected function parse($value) 17 | { 18 | if (!is_numeric($value)) { 19 | return null; 20 | } 21 | $value = (int) $value; 22 | return parent::parse($value); 23 | } 24 | 25 | /** 26 | * @param int $defaultValue 27 | * @return int 28 | */ 29 | public function defaultsTo($defaultValue) 30 | { 31 | return parent::defaultsTo($defaultValue); 32 | } 33 | 34 | /** 35 | * @throws \Exception 36 | * @param string $invalidValueMessage 37 | * @param string $notFoundMessage 38 | * @return int 39 | */ 40 | public function required($invalidValueMessage = null, $notFoundMessage = null) 41 | { 42 | return parent::required($invalidValueMessage, $notFoundMessage); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Validator/OneOfParser.php: -------------------------------------------------------------------------------- 1 | validValues = $validValues; 15 | parent::__construct($config, $name, $value); 16 | } 17 | 18 | protected function describe() 19 | { 20 | return "one of " . implode(", ", $this->validValues); 21 | } 22 | 23 | protected function parse($value) 24 | { 25 | if (in_array($value, $this->validValues)) { 26 | return $value; 27 | } else { 28 | return null; 29 | } 30 | } 31 | 32 | /** 33 | * @param mixed $defaultValue 34 | * @return int 35 | */ 36 | public function defaultsTo($defaultValue) 37 | { 38 | return parent::defaultsTo($defaultValue); 39 | } 40 | 41 | /** 42 | * @throws \Exception 43 | * @return string 44 | */ 45 | public function required($invalidValueMessage = null, $notFoundMessage = null) 46 | { 47 | return parent::required($invalidValueMessage, $notFoundMessage); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Validator/StringLengthBetween.php: -------------------------------------------------------------------------------- 1 | minValue and $this->maxValue"; 10 | } 11 | 12 | /** 13 | * @param $value 14 | * @return int 15 | */ 16 | protected function parse($value) 17 | { 18 | if (strlen($value) >= $this->minValue && strlen($value) <= $this->maxValue) { 19 | return $value; 20 | } 21 | return null; 22 | } 23 | 24 | /** 25 | * @param string $defaultValue 26 | * @return string 27 | */ 28 | public function defaultsTo($defaultValue) 29 | { 30 | return parent::defaultsTo($defaultValue); 31 | } 32 | 33 | /** 34 | * @throws \Exception 35 | * @param string $invalidValueMessage 36 | * @param string $notFoundMessage 37 | * @return string 38 | */ 39 | public function required($invalidValueMessage = null, $notFoundMessage = null) 40 | { 41 | return parent::required($invalidValueMessage, $notFoundMessage); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Validator/StringLengthLargerThanOrEqualToParser.php: -------------------------------------------------------------------------------- 1 | minValue characters"; 10 | } 11 | 12 | /** 13 | * @param $value 14 | * @return int 15 | */ 16 | protected function parse($value) 17 | { 18 | if (strlen($value) >= $this->minValue) { 19 | return $value; 20 | } 21 | return null; 22 | } 23 | 24 | /** 25 | * @param string $defaultValue 26 | * @return string 27 | */ 28 | public function defaultsTo($defaultValue) 29 | { 30 | return parent::defaultsTo($defaultValue); 31 | } 32 | 33 | /** 34 | * @throws \Exception 35 | * @param string $invalidValueMessage 36 | * @param string $notFoundMessage 37 | * @return string 38 | */ 39 | public function required($invalidValueMessage = null, $notFoundMessage = null) 40 | { 41 | return parent::required($invalidValueMessage, $notFoundMessage); 42 | } 43 | } -------------------------------------------------------------------------------- /src/Validator/StringLengthLargerThanParser.php: -------------------------------------------------------------------------------- 1 | minValue characters"; 10 | } 11 | 12 | /** 13 | * @param $value 14 | * @return int 15 | */ 16 | protected function parse($value) 17 | { 18 | if (strlen($value) > $this->minValue) { 19 | return $value; 20 | } 21 | return null; 22 | } 23 | 24 | /** 25 | * @param string $defaultValue 26 | * @return string 27 | */ 28 | public function defaultsTo($defaultValue) 29 | { 30 | return parent::defaultsTo($defaultValue); 31 | } 32 | 33 | /** 34 | * @throws \Exception 35 | * @param string $invalidValueMessage 36 | * @param string $notFoundMessage 37 | * @return string 38 | */ 39 | public function required($invalidValueMessage = null, $notFoundMessage = null) 40 | { 41 | return parent::required($invalidValueMessage, $notFoundMessage); 42 | } 43 | } -------------------------------------------------------------------------------- /src/Validator/StringLengthSmallerThanOrEqualToParser.php: -------------------------------------------------------------------------------- 1 | maxValue characters"; 10 | } 11 | 12 | /** 13 | * @param $value 14 | * @return int 15 | */ 16 | protected function parse($value) 17 | { 18 | if (strlen($value) <= $this->maxValue) { 19 | return $value; 20 | } 21 | return null; 22 | } 23 | 24 | /** 25 | * @param string $defaultValue 26 | * @return string 27 | */ 28 | public function defaultsTo($defaultValue) 29 | { 30 | return parent::defaultsTo($defaultValue); 31 | } 32 | 33 | /** 34 | * @throws \Exception 35 | * @param string $invalidValueMessage 36 | * @param string $notFoundMessage 37 | * @return string 38 | */ 39 | public function required($invalidValueMessage = null, $notFoundMessage = null) 40 | { 41 | return parent::required($invalidValueMessage, $notFoundMessage); 42 | } 43 | } -------------------------------------------------------------------------------- /src/Validator/StringLengthSmallerThanParser.php: -------------------------------------------------------------------------------- 1 | maxValue characters"; 10 | } 11 | 12 | /** 13 | * @param $value 14 | * @return int 15 | */ 16 | protected function parse($value) 17 | { 18 | if (strlen($value) < $this->maxValue) { 19 | return $value; 20 | } 21 | return null; 22 | } 23 | 24 | /** 25 | * @param string $defaultValue 26 | * @return string 27 | */ 28 | public function defaultsTo($defaultValue) 29 | { 30 | return parent::defaultsTo($defaultValue); 31 | } 32 | 33 | /** 34 | * @throws \Exception 35 | * @param string $invalidValueMessage 36 | * @param string $notFoundMessage 37 | * @return string 38 | */ 39 | public function required($invalidValueMessage = null, $notFoundMessage = null) 40 | { 41 | return parent::required($invalidValueMessage, $notFoundMessage); 42 | } 43 | } -------------------------------------------------------------------------------- /src/Validator/UrlParser.php: -------------------------------------------------------------------------------- 1 | value === '') { 47 | return $defaultValue; 48 | } 49 | 50 | return $this->defaultsTo($defaultValue); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/YesNoBooleanParser.php: -------------------------------------------------------------------------------- 1 | required(); 23 | $this->assertEquals($expected, $result); 24 | } 25 | 26 | public function testCsvWithFloat() 27 | { 28 | $expected = [1.1, 2.99, 3.4, 4.13]; 29 | $result = (new CommaSeparatedFloatParser(new Config(), 'intArr', '1.1,2.99,3.4,4.13'))->required(); 30 | $this->assertEquals($expected, $result); 31 | } 32 | 33 | public function testCsvWithString() 34 | { 35 | $expected = ['apples', 'oranges', 'tomatoes']; 36 | $result = (new CommaSeparatedStringParser(new Config(), 'intArr', 'apples,oranges,tomatoes'))->required(); 37 | $this->assertEquals($expected, $result); 38 | } 39 | 40 | public function testCsvWithDateTime() 41 | { 42 | $expected = [ 43 | new \DateTime('2016-01-01'), 44 | new \DateTime('2016-01-02'), 45 | new \DateTime('2016-01-03') 46 | ]; 47 | $result = (new CommaSeparatedDateTimeParser(new Config(), 'intArr', '2016-01-01,2016-01-02,2016-01-03'))->required(); 48 | $this->assertEquals($expected, $result); 49 | } 50 | 51 | public function testCsvWithJson() 52 | { 53 | $expected = [ 54 | [ 55 | 'event' => 'page_view', 56 | 'deviceTimestamp' => '2016-01-01 08:10:00.151', 57 | 'url' => 'https://www.domain.com/' 58 | ], 59 | [ 60 | 'event' => 'add_to_basket', 61 | 'deviceTimestamp' => '2016-01-02 09:59:00.999', 62 | 'url' => 'https://www.domain.com/' 63 | ] 64 | ]; 65 | $value = '{"event":"page_view","deviceTimestamp":"2016-01-01 08:10:00.151","url":"https://www.domain.com/"},{"event":"add_to_basket","deviceTimestamp":"2016-01-02 09:59:00.999","url":"https://www.domain.com/"}'; 66 | $result = (new CommaSeparatedJsonParser(new Config(), 'intArr', $value))->required(); 67 | $this->assertEquals($expected, $result); 68 | } 69 | 70 | public function testCsvWithBoolean() 71 | { 72 | $expected = [false, true, true]; 73 | $result = (new CommaSeparatedBooleanParser(new Config(), 'boolArr', 'false,true,true'))->required(); 74 | $this->assertEquals($expected, $result); 75 | } 76 | 77 | public function testCsvWithYesNoBoolean() 78 | { 79 | $expected = [true, false, true]; 80 | $result = (new CommaSeparatedYesNoBooleanParser(new Config(), 'yesNoBoolArr', 'Y,N,Y'))->required(); 81 | $this->assertEquals($expected, $result); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /tests/ConfigTest.php: -------------------------------------------------------------------------------- 1 | assertInstanceOf(ExceptionFactory::class, $config->getExceptionFactory()); 13 | } 14 | 15 | public function testGetExceptionMessageFactory() 16 | { 17 | $config = new Config(); 18 | $this->assertInstanceOf(ExceptionMessageFactory::class, $config->getExceptionMessageFactory()); 19 | } 20 | 21 | public function testCustomExceptionFactory() 22 | { 23 | $customExceptionFactory = new ExceptionFactory(\Exception::class, \Exception::class); 24 | 25 | $config = new Config(); 26 | $config->setExceptionFactory($customExceptionFactory); 27 | 28 | $this->assertSame($customExceptionFactory, $config->getExceptionFactory()); 29 | } 30 | 31 | public function testCustomExceptionMessageFactory() 32 | { 33 | $exceptionMessageFactory = new ExceptionMessageFactory(); 34 | 35 | $config = new Config(); 36 | $config->setExceptionMessageFactory($exceptionMessageFactory); 37 | 38 | $this->assertSame($exceptionMessageFactory, $config->getExceptionMessageFactory()); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /tests/ExceptionFactoryTest.php: -------------------------------------------------------------------------------- 1 | factory = new ExceptionFactory(); 16 | } 17 | 18 | public function testCreateNotFoundException() 19 | { 20 | $exception = $this->factory->createNotFoundException('message'); 21 | 22 | $this->assertInstanceOf(NotFoundException::class, $exception); 23 | $this->assertEquals('message', $exception->getMessage()); 24 | } 25 | 26 | public function testCreateInvalidValueException() 27 | { 28 | $exception = $this->factory->createInvalidValueException('message'); 29 | 30 | $this->assertInstanceOf(NotFoundException::class, $exception); 31 | $this->assertEquals('message', $exception->getMessage()); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /tests/ExceptionMessageFactoryTest.php: -------------------------------------------------------------------------------- 1 | factory = new ExceptionMessageFactory(); 15 | } 16 | 17 | public function testCreateNotFoundException() 18 | { 19 | $message = $this->factory->createNotFoundMessage('id'); 20 | 21 | $this->assertEquals('Parameter "id" not found', $message); 22 | } 23 | 24 | public function testCreateInvalidValueException() 25 | { 26 | $message = $this->factory->createInvalidValueMessage('id', 'invalidinteger', 'an integer'); 27 | 28 | $this->assertEquals('Invalid value for parameter "id". Expected an integer, but got "invalidinteger"', $message); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /tests/Integration/Psr7IntegrationTest.php: -------------------------------------------------------------------------------- 1 | 'Test', 11 | 'int' => 1 12 | ]; 13 | 14 | $request = (new Zend\Diactoros\ServerRequest()); 15 | 16 | $getRequest = $request 17 | ->withMethod('GET') 18 | ->withQueryParams($parameters); 19 | 20 | $postRequest = $request 21 | ->withMethod('POST') 22 | ->withParsedBody($parameters); 23 | 24 | return [ 25 | [new Psr7Controller($getRequest)], 26 | [new Psr7Controller($postRequest)] 27 | ]; 28 | } 29 | } 30 | 31 | class Psr7Controller extends AbstractIntegrationTestController 32 | { 33 | use \MPScholten\RequestParser\Psr7\ControllerHelperTrait; 34 | } 35 | -------------------------------------------------------------------------------- /tests/Integration/SymfonyIntegrationTest.php: -------------------------------------------------------------------------------- 1 | 'Test', 11 | 'int' => 1 12 | ]; 13 | 14 | $getRequest = new \Symfony\Component\HttpFoundation\Request($parameters); 15 | $getRequest->setMethod('GET'); 16 | 17 | $postRequest = new \Symfony\Component\HttpFoundation\Request([], $parameters); 18 | $postRequest->setMethod('POST'); 19 | 20 | return [ 21 | [new SymfonyController($getRequest)], 22 | [new SymfonyController($postRequest)] 23 | ]; 24 | } 25 | } 26 | 27 | class SymfonyController extends AbstractIntegrationTestController 28 | { 29 | use \MPScholten\RequestParser\Symfony\ControllerHelperTrait; 30 | } 31 | -------------------------------------------------------------------------------- /tests/Integration/setup.php: -------------------------------------------------------------------------------- 1 | assertEquals('Test', $controller->testString()); 13 | } 14 | 15 | /** 16 | * @dataProvider controllersProvider 17 | */ 18 | public function testIntAction(AbstractIntegrationTestController $controller) 19 | { 20 | $this->assertEquals(1, $controller->testInt()); 21 | } 22 | 23 | /** 24 | * @dataProvider controllersProvider 25 | */ 26 | public function testNotFoundActionThrowsException(AbstractIntegrationTestController $controller) 27 | { 28 | $this->setExpectedException(\MPScholten\RequestParser\NotFoundException::class, 'Parameter "notFound" not found'); 29 | $controller->testNotFound(); 30 | } 31 | } 32 | 33 | abstract class AbstractIntegrationTestController 34 | { 35 | private $request; 36 | 37 | public function __construct($request) 38 | { 39 | $this->initRequestParser($request); 40 | $this->request = $request; 41 | } 42 | 43 | protected function parameter($name) 44 | { 45 | if ($this->request->getMethod() === 'GET') { 46 | return $this->queryParameter($name); 47 | } else { 48 | return $this->bodyParameter($name); 49 | } 50 | } 51 | 52 | public function testString() 53 | { 54 | return $this->parameter('string')->string()->required(); 55 | } 56 | 57 | public function testInt() 58 | { 59 | return $this->parameter('int')->int()->required(); 60 | } 61 | 62 | public function testNotFound() 63 | { 64 | return $this->parameter('notFound')->string()->required(); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /tests/LegacyExceptionFactoryTest.php: -------------------------------------------------------------------------------- 1 | factory = new LegacyExceptionFactory($closure); 19 | } 20 | 21 | public function testCreateNotFoundException() 22 | { 23 | $exception = $this->factory->createNotFoundException('id'); 24 | 25 | $this->assertInstanceOf(\Exception::class, $exception); 26 | $this->assertEquals('not found: id', $exception->getMessage()); 27 | } 28 | 29 | public function testCreateInvalidValueException() 30 | { 31 | $exception = $this->factory->createInvalidValueException('id', 'invalidinteger', 'an integer'); 32 | 33 | $this->assertInstanceOf(\Exception::class, $exception); 34 | $this->assertEquals('not found: id', $exception->getMessage()); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /tests/ParserSpecTest.php: -------------------------------------------------------------------------------- 1 | true]], 33 | [new YesNoBooleanParser(new Config(), 'isAwesome', null), true], 34 | [new BooleanParser(new Config(), 'isNice', null), true] 35 | ]; 36 | } 37 | 38 | public function specWithValueAndDefaultValue() 39 | { 40 | return [ 41 | // [spec, default-value, real-value] 42 | [new IntParser(new Config(), 'id', 1337), 1, 1337], 43 | [new FloatParser(new Config(), 'ratio', 0.91), 1.0, 0.91], 44 | [new YesNoBooleanParser(new Config(), 'isAwesome', 'yes'), true, true], 45 | [new BooleanParser(new Config(), 'isAwesome', 'true'), true, true], 46 | [new StringParser(new Config(), 'name', 'quintly'), '', 'quintly'], 47 | [new UrlParser(new Config(), 'referrer', 'https://www.quintly.com/'), 'https://www.quintly.com/blog/', 'https://www.quintly.com/'], 48 | [new EmailParser(new Config(), 'emailAddress', 'john@doe.com'), '', 'john@doe.com'], 49 | [new TrimParser(new Config(), 'emailAddress', ' john@doe.com ', TrimParser::TRIM), '', 'john@doe.com'], 50 | [new TrimParser(new Config(), 'emailAddress', ' john@doe.com', TrimParser::LEFT_TRIM), '', 'john@doe.com'], 51 | [new TrimParser(new Config(), 'emailAddress', 'john@doe.com ', TrimParser::RIGHT_TRIM), '', 'john@doe.com'], 52 | [new OneOfParser(new Config(), 'type', 'a', ['a', 'b']), 'b', 'a'], 53 | [new DateTimeParser(new Config(), 'createdAt', '2015-02-02'), new \DateTime('2015-01-01'), new \DateTime('2015-02-02')], 54 | [new JsonParser(new Config(), 'config', '{"value":false}'), ['value' => true], ['value' => false]] 55 | ]; 56 | } 57 | 58 | public function specWithInvalidValueAndDefaultValue() 59 | { 60 | return [ 61 | [new IntParser(new Config(), 'id', 'string instead of an int'), 1], 62 | [new FloatParser(new Config(), 'ration', 'string instead of a float'), 0.91], 63 | [new YesNoBooleanParser(new Config(), 'isAwesome', 'invalid'), false], 64 | [new BooleanParser(new Config(), 'isAwesome', 'invalid'), false], 65 | [new EmailParser(new Config(), 'emailAddress', 'invalid_email'), 'john@doe.com'], 66 | [new UrlParser(new Config(), 'referrer', 'https:://www.invalid.url/^'), 'https://www.quintly.com/'], 67 | // StringParser has no invalid data types 68 | [new OneOfParser(new Config(), 'type', 'x', ['a', 'b']), 'a'], 69 | [new DateTimeParser(new Config(), 'createdAt', ''), new \DateTime('2015-01-01')], 70 | [new JsonParser(new Config(), 'config', 'invalid json{'), ['value' => true]] 71 | ]; 72 | } 73 | 74 | /** 75 | * @dataProvider specWithoutValueAndDefaultValueProvider 76 | */ 77 | public function testDefaultsToReturnsDefaultValue(AbstractValueParser $spec, $defaultValue) 78 | { 79 | $this->assertEquals($defaultValue, $spec->defaultsTo($defaultValue)); 80 | } 81 | 82 | /** 83 | * @dataProvider specWithValueAndDefaultValue 84 | */ 85 | public function testDefaultsToReturnsParameterValue(AbstractValueParser $spec, $defaultValue, $expectedResult) 86 | { 87 | $this->assertEquals($expectedResult, $spec->defaultsTo($defaultValue)); 88 | } 89 | 90 | /** 91 | * @dataProvider specWithInvalidValueAndDefaultValue 92 | */ 93 | public function testDefaultsToReturnsDefaultValueOnInvalidValue(AbstractValueParser $spec, $defaultValue) 94 | { 95 | $this->assertEquals($defaultValue, $spec->defaultsTo($defaultValue)); 96 | } 97 | 98 | /** 99 | * @dataProvider specWithValueAndDefaultValue 100 | */ 101 | public function testRequiredReturnsValue(AbstractValueParser $spec, $defaultValue, $value) 102 | { 103 | $this->assertEquals($value, $spec->required()); 104 | } 105 | 106 | /** 107 | * @dataProvider specWithoutValueAndDefaultValueProvider 108 | */ 109 | public function testRequiredThrowsExceptionOnMissingValue(AbstractValueParser $spec) 110 | { 111 | $this->setExpectedException(NotFoundException::class); 112 | $spec->required(); 113 | } 114 | 115 | /** 116 | * @dataProvider specWithoutValueAndDefaultValueProvider 117 | */ 118 | public function testRequiredThrowsExceptionWithCustomMessageOnMissingValue(AbstractValueParser $spec) 119 | { 120 | $this->setExpectedException(NotFoundException::class, "custom not found message"); 121 | $spec->required(null, "custom not found message"); 122 | } 123 | 124 | /** 125 | * @dataProvider specWithInvalidValueAndDefaultValue 126 | */ 127 | public function testRequiredThrowsExceptionOnInvalidValue(AbstractValueParser $spec) 128 | { 129 | $this->setExpectedException(InvalidValueException::class); 130 | $spec->required(); 131 | } 132 | 133 | # 134 | /** 135 | * @dataProvider specWithInvalidValueAndDefaultValue 136 | */ 137 | public function testRequiredThrowsExceptionWithCustomMessageOnInvalidValue(AbstractValueParser $spec) 138 | { 139 | $this->setExpectedException(InvalidValueException::class, "custom invalid value message"); 140 | $spec->required("custom invalid value message"); 141 | } 142 | 143 | public function testStringSpecific() 144 | { 145 | $parser = new StringParser(new Config(), 'name', ''); 146 | $this->assertEquals('default', $parser->defaultsToIfEmpty('default')); 147 | 148 | $parser = new StringParser(new Config(), 'name', 'test'); 149 | $this->assertEquals('test', $parser->defaultsToIfEmpty('default')); 150 | } 151 | 152 | public function testBetweenValidatorWithValidValues() 153 | { 154 | $parser = new IntParser(new Config(), 'groupId', 1); 155 | $parser->between(1, 6); 156 | $this->assertEquals(1, $parser->required()); 157 | $parser = new IntParser(new Config(), 'groupId', 6); 158 | $parser->between(1, 6); 159 | $this->assertEquals(6, $parser->required()); 160 | 161 | $parser = new FloatParser(new Config(), 'precipitation', 60.99); 162 | $parser->between(60.99, 101.12); 163 | $this->assertEquals(60.99, $parser->required()); 164 | $parser = new FloatParser(new Config(), 'precipitation', 101.12); 165 | $parser->between(60.99, 101.12); 166 | $this->assertEquals(101.12, $parser->required()); 167 | 168 | $parser = new StringParser(new Config(), 'name', ''); 169 | $parser->lengthBetween(0, 1); 170 | $this->assertEquals('', $parser->required()); 171 | $parser = new StringParser(new Config(), 'groupId', 'A'); 172 | $parser->lengthBetween(0, 1); 173 | $this->assertEquals('A', $parser->required()); 174 | } 175 | 176 | public function testLargerThanValidatorWithValidValues() 177 | { 178 | $parser = new IntParser(new Config(), 'groupId', 1); 179 | $parser->largerThan(0); 180 | $this->assertEquals(1, $parser->required()); 181 | 182 | $parser = new IntParser(new Config(), 'groupId', 1); 183 | $parser->largerThanOrEqualTo(1); 184 | $this->assertEquals(1, $parser->required()); 185 | 186 | $parser = new FloatParser(new Config(), 'precipitation', 1.01); 187 | $parser->largerThan(1.001); 188 | $this->assertEquals(1.01, $parser->required()); 189 | 190 | $parser = new FloatParser(new Config(), 'precipitation', 1.01); 191 | $parser->largerThanOrEqualTo(1.01); 192 | $this->assertEquals(1.01, $parser->required()); 193 | 194 | $parser = new StringParser(new Config(), 'name', 'A'); 195 | $parser->lengthLargerThan(0); 196 | $this->assertEquals('A', $parser->required()); 197 | 198 | $parser = new StringParser(new Config(), 'groupId', 'A'); 199 | $parser->lengthLargerThanOrEqualTo(1); 200 | $this->assertEquals('A', $parser->required()); 201 | } 202 | 203 | public function testSmallerThanValidatorWithValidValues() 204 | { 205 | $parser = new IntParser(new Config(), 'groupId', -1); 206 | $parser->smallerThan(0); 207 | $this->assertEquals(-1, $parser->required()); 208 | 209 | $parser = new IntParser(new Config(), 'groupId', -1); 210 | $parser->largerThanOrEqualTo(-1); 211 | $this->assertEquals(-1, $parser->required()); 212 | 213 | $parser = new FloatParser(new Config(), 'precipitation', -2.01); 214 | $parser->largerThan(-3.01); 215 | $this->assertEquals(-2.01, $parser->required()); 216 | 217 | $parser = new FloatParser(new Config(), 'precipitation', -2.01); 218 | $parser->largerThanOrEqualTo(-2.01); 219 | $this->assertEquals(-2.01, $parser->required()); 220 | 221 | $parser = new StringParser(new Config(), 'groupId', 'A'); 222 | $parser->lengthSmallerThan(2); 223 | $this->assertEquals('A', $parser->required()); 224 | 225 | $parser = new StringParser(new Config(), 'groupId', 'A'); 226 | $parser->lengthLargerThanOrEqualTo(1); 227 | $this->assertEquals('A', $parser->required()); 228 | } 229 | 230 | public function testIntBetweenValidatorWithValuesOutOfRange() 231 | { 232 | $this->setExpectedException(InvalidValueException::class, 'Invalid value for parameter "groupId". Expected an integer between 1 and 6, but got "7"'); 233 | $parser = new IntParser(new Config(), 'groupId', 7); 234 | $groupId = $parser->between(1, 6)->required(); 235 | } 236 | 237 | public function testFloatBetweenValidatorWithValuesOutOfRange() 238 | { 239 | $this->setExpectedException(InvalidValueException::class, 'Invalid value for parameter "precipitation". Expected a float between 60.99 and 101.12, but got "101.13"'); 240 | $parser = new FloatParser(new Config(), 'precipitation', 101.13); 241 | $precipitation = $parser->between(60.99, 101.12)->required(); 242 | } 243 | 244 | public function testStringBetweenValidatorWithValuesOutOfRange() 245 | { 246 | $this->setExpectedException(InvalidValueException::class, 'Invalid value for parameter "name". Expected a string with character length between 0 and 1, but got "AB"'); 247 | $parser = new StringParser(new Config(), 'name', 'AB'); 248 | $parser->lengthBetween(0, 1)->required(); 249 | } 250 | 251 | public function testIntLargerThanValidatorWithValuesOutOfRange() 252 | { 253 | $this->setExpectedException(InvalidValueException::class, 'Invalid value for parameter "groupId". Expected an integer larger than 1, but got "0"'); 254 | $parser = new IntParser(new Config(), 'groupId', 0); 255 | $groupId = $parser->largerThan(1)->required(); 256 | } 257 | 258 | public function testIntLargerThanOrEqualToValidatorWithValuesOutOfRange() 259 | { 260 | $this->setExpectedException(InvalidValueException::class, 'Invalid value for parameter "groupId". Expected an integer larger than or equal to 1, but got "0"'); 261 | $parser = new IntParser(new Config(), 'groupId', 0); 262 | $groupId = $parser->largerThanOrEqualTo(1)->required(); 263 | } 264 | 265 | public function testFloatLargerThanValidatorWithValuesOutOfRange() 266 | { 267 | $this->setExpectedException(InvalidValueException::class, 'Invalid value for parameter "precipitation". Expected a float larger than 1.01, but got "0.01"'); 268 | $parser = new FloatParser(new Config(), 'precipitation', 0.01); 269 | $precipitation = $parser->largerThan(1.01)->required(); 270 | } 271 | 272 | public function testFloatLargerThanOrEqualToValidatorWithValuesOutOfRange() 273 | { 274 | $this->setExpectedException(InvalidValueException::class, 'Invalid value for parameter "precipitation". Expected a float larger than or equal to 1.01, but got "0.01"'); 275 | $parser = new FloatParser(new Config(), 'precipitation', 0.01); 276 | $precipitation = $parser->largerThanOrEqualTo(1.01)->required(); 277 | } 278 | 279 | public function testStringLargerThanValidatorWithValuesOutOfRange() 280 | { 281 | $this->setExpectedException(InvalidValueException::class, 'Invalid value for parameter "name". Expected a string longer than 0 characters, but got ""'); 282 | $parser = new StringParser(new Config(), 'name', ''); 283 | $parser->lengthLargerThan(0)->required(); 284 | } 285 | 286 | public function testStringLargerThanOrEqualToValidatorWithValuesOutOfRange() 287 | { 288 | $this->setExpectedException(InvalidValueException::class, 'Invalid value for parameter "name". Expected a string longer than or equal to 2 characters, but got "A"'); 289 | $parser = new StringParser(new Config(), 'name', 'A'); 290 | $parser->lengthLargerThanOrEqualTo(2)->required(); 291 | } 292 | 293 | public function testIntSmallerThanValidatorWithValuesOutOfRange() 294 | { 295 | $this->setExpectedException(InvalidValueException::class, 'Invalid value for parameter "groupId". Expected an integer smaller than 0, but got "1"'); 296 | $parser = new IntParser(new Config(), 'groupId', 1); 297 | $groupId = $parser->smallerThan(0)->required(); 298 | } 299 | 300 | public function testIntSmallerThanOrEqualToValidatorWithValuesOutOfRange() 301 | { 302 | $this->setExpectedException(InvalidValueException::class, 'Invalid value for parameter "groupId". Expected an integer smaller than or equal to 0, but got "1"'); 303 | $parser = new IntParser(new Config(), 'groupId', 1); 304 | $groupId = $parser->smallerThanOrEqualTo(0)->required(); 305 | } 306 | 307 | public function testFloatSmallerThanValidatorWithValuesOutOfRange() 308 | { 309 | $this->setExpectedException(InvalidValueException::class, 'Invalid value for parameter "precipitation". Expected a float smaller than 0.01, but got "1.01"'); 310 | $parser = new FloatParser(new Config(), 'precipitation', 1.01); 311 | $precipitation = $parser->smallerThan(0.01)->required(); 312 | } 313 | 314 | public function testFloatSmallerThanOrEqualToValidatorWithValuesOutOfRange() 315 | { 316 | $this->setExpectedException(InvalidValueException::class, 'Invalid value for parameter "precipitation". Expected a float smaller than or equal to 0.01, but got "1.01"'); 317 | $parser = new FloatParser(new Config(), 'precipitation', 1.01); 318 | $precipitation = $parser->smallerThanOrEqualTo(0.01)->required(); 319 | } 320 | 321 | public function testStringSmallerThanValidatorWithValuesOutOfRange() 322 | { 323 | $this->setExpectedException(InvalidValueException::class, 'Invalid value for parameter "name". Expected a string shorter than 1 characters, but got "A"'); 324 | $parser = new StringParser(new Config(), 'name', 'A'); 325 | $parser->lengthSmallerThan(1)->required(); 326 | } 327 | 328 | public function testStringSmallerThanOrEqualToValidatorWithValuesOutOfRange() 329 | { 330 | $this->setExpectedException(InvalidValueException::class, 'Invalid value for parameter "name". Expected a string shorter than or equal to 1 characters, but got "AB"'); 331 | $parser = new StringParser(new Config(), 'name', 'AB'); 332 | $parser->lengthSmallerThanOrEqualTo(1)->required(); 333 | } 334 | } 335 | -------------------------------------------------------------------------------- /tests/TypeSpecTest.php: -------------------------------------------------------------------------------- 1 | assertInstanceOf(IntParser::class, $spec->int()); 47 | } 48 | 49 | public function testFloat() 50 | { 51 | $spec = new TypeParser(new Config(), 'ratio', '0.91'); 52 | $this->assertInstanceOf(FloatParser::class, $spec->float()); 53 | } 54 | 55 | public function testString() 56 | { 57 | $spec = new TypeParser(new Config(), 'name', 'quintly'); 58 | $this->assertInstanceOf(StringParser::class, $spec->string()); 59 | } 60 | 61 | public function testUrl() 62 | { 63 | $spec = new TypeParser(new Config(), 'referrer', 'https://www.quintly.com/'); 64 | $this->assertInstanceOf(UrlParser::class, $spec->string()->url()); 65 | } 66 | 67 | public function testEmail() 68 | { 69 | $spec = new TypeParser(new Config(), 'emailAddress', 'john@doe.com'); 70 | $this->assertInstanceOf(EmailParser::class, $spec->string()->email()); 71 | } 72 | 73 | public function testIntBetween() 74 | { 75 | $spec = new TypeParser(new Config(), 'groupId', '1'); 76 | $this->assertInstanceOf(IntBetweenParser::class, $spec->int()->between(0, 100)); 77 | } 78 | 79 | public function testIntLargerThan() 80 | { 81 | $spec = new TypeParser(new Config(), 'groupId', '1'); 82 | $this->assertInstanceOf(IntLargerThanParser::class, $spec->int()->largerThan(0)); 83 | } 84 | 85 | public function testIntLargerThanOrEqualTo() 86 | { 87 | $spec = new TypeParser(new Config(), 'groupId', '1'); 88 | $this->assertInstanceOf(IntLargerThanOrEqualToParser::class, $spec->int()->largerThanOrEqualTo(1)); 89 | } 90 | 91 | public function testIntSmallerThan() 92 | { 93 | $spec = new TypeParser(new Config(), 'groupId', '-1'); 94 | $this->assertInstanceOf(IntSmallerThanParser::class, $spec->int()->smallerThan(0)); 95 | } 96 | 97 | public function testIntSmallerThanOrEqualTo() 98 | { 99 | $spec = new TypeParser(new Config(), 'groupId', '1'); 100 | $this->assertInstanceOf(IntSmallerThanOrEqualToParser::class, $spec->int()->smallerThanOrEqualTo(1)); 101 | } 102 | 103 | public function testFloatLargerThan() 104 | { 105 | $spec = new TypeParser(new Config(), 'precipitation', '1.01'); 106 | $this->assertInstanceOf(FloatLargerThanParser::class, $spec->float()->largerThan(0)); 107 | } 108 | 109 | public function testFloatLargerThanOrEqualTo() 110 | { 111 | $spec = new TypeParser(new Config(), 'precipitation', '1.01'); 112 | $this->assertInstanceOf(FloatLargerThanOrEqualToParser::class, $spec->float()->largerThanOrEqualTo(1.01)); 113 | } 114 | 115 | public function testFloatSmallerThan() 116 | { 117 | $spec = new TypeParser(new Config(), 'precipitation', '-1.19'); 118 | $this->assertInstanceOf(FloatSmallerThanParser::class, $spec->float()->smallerThan(-1)); 119 | } 120 | 121 | public function testFloatSmallerThanOrEqualTo() 122 | { 123 | $spec = new TypeParser(new Config(), 'precipitation', '-1.19'); 124 | $this->assertInstanceOf(FloatSmallerThanOrEqualToParser::class, $spec->float()->smallerThanOrEqualTo(-1.19)); 125 | } 126 | 127 | public function testFloatBetween() 128 | { 129 | $spec = new TypeParser(new Config(), 'precipitation', '101.39'); 130 | $this->assertInstanceOf(FloatBetweenParser::class, $spec->float()->between(0.01, 1000.09)); 131 | } 132 | 133 | public function testTrim() 134 | { 135 | $spec = new TypeParser(new Config(), 'emailAddress', ' john@doe.com '); 136 | $this->assertInstanceOf(TrimParser::class, $spec->string()->trim()); 137 | } 138 | 139 | public function testLeftTrim() 140 | { 141 | $spec = new TypeParser(new Config(), 'emailAddress', ' john@doe.com'); 142 | $this->assertInstanceOf(TrimParser::class, $spec->string()->leftTrim()); 143 | } 144 | 145 | public function testRightTrim() 146 | { 147 | $spec = new TypeParser(new Config(), 'emailAddress', 'john@doe.com '); 148 | $this->assertInstanceOf(TrimParser::class, $spec->string()->rightTrim()); 149 | } 150 | 151 | public function testOneOf() 152 | { 153 | $spec = new TypeParser(new Config(), 'type', 'b'); 154 | $this->assertInstanceOf(OneOfParser::class, $spec->oneOf(['a', 'b'])); 155 | } 156 | 157 | public function testDateTime() 158 | { 159 | $spec = new TypeParser(new Config(), 'createdAt', '01-01-2016'); 160 | $this->assertInstanceOf(DateTimeParser::class, $spec->dateTime()); 161 | } 162 | 163 | public function testJson() 164 | { 165 | $spec = new TypeParser(new Config(), 'payload', '{}'); 166 | $this->assertInstanceOf(JsonParser::class, $spec->json()); 167 | } 168 | 169 | public function testYesNoBoolean() 170 | { 171 | $spec = new TypeParser(new Config(), 'isAwesome', 'yes'); 172 | $this->assertInstanceOf(YesNoBooleanParser::class, $spec->yesNoBoolean()); 173 | } 174 | 175 | public function testBoolean() 176 | { 177 | $spec = new TypeParser(new Config(), 'isAwesome', 'true'); 178 | $this->assertInstanceOf(BooleanParser::class, $spec->boolean()); 179 | } 180 | 181 | // CSV type spec tests: 182 | public function testCommaSeparatedInt() 183 | { 184 | $spec = new TypeParser(new Config(), 'hundreds', '100,200,300'); 185 | $this->assertInstanceOf(CommaSeparatedIntParser::class, $spec->commaSeparated()->int()); 186 | } 187 | 188 | public function testCommaSeparatedFloat() 189 | { 190 | $spec = new TypeParser(new Config(), 'precipitation', '0.91,1.22,4.50'); 191 | $this->assertInstanceOf(CommaSeparatedFloatParser::class, $spec->commaSeparated()->float()); 192 | } 193 | 194 | public function testCommaSeparatedString() 195 | { 196 | $spec = new TypeParser(new Config(), 'tags', 'quintly,social,media,analytics'); 197 | $this->assertInstanceOf(CommaSeparatedStringParser::class, $spec->commaSeparated()->string()); 198 | } 199 | 200 | public function testCommaSeparatedDateTime() 201 | { 202 | $spec = new TypeParser(new Config(), 'eventsAt', '2016-01-01,2016-01-02'); 203 | $this->assertInstanceOf(CommaSeparatedDateTimeParser::class, $spec->commaSeparated()->dateTime()); 204 | } 205 | 206 | public function testCommaSeparatedJson() 207 | { 208 | $spec = new TypeParser(new Config(), 'payload', '{"a":5},{"a":6}'); 209 | $this->assertInstanceOf(CommaSeparatedJsonParser::class, $spec->commaSeparated()->json()); 210 | } 211 | 212 | public function testCommaSeparatedYesNoBoolean() 213 | { 214 | $spec = new TypeParser(new Config(), 'answers', 'yes,no,yes'); 215 | $this->assertInstanceOf(CommaSeparatedYesNoBooleanParser::class, $spec->commaSeparated()->yesNoBoolean()); 216 | } 217 | 218 | public function testCommaSeparatedBoolean() 219 | { 220 | $spec = new TypeParser(new Config(), 'answers', 'true,false,true'); 221 | $this->assertInstanceOf(CommaSeparatedBooleanParser::class, $spec->commaSeparated()->boolean()); 222 | } 223 | 224 | public function testStringBetween() 225 | { 226 | $spec = new TypeParser(new Config(), 'groupId', 'A'); 227 | $this->assertInstanceOf(StringLengthBetween::class, $spec->string()->lengthBetween(0, 1)); 228 | } 229 | 230 | public function testStringLargerThan() 231 | { 232 | $spec = new TypeParser(new Config(), 'groupId', 'A'); 233 | $this->assertInstanceOf(StringLengthLargerThanParser::class, $spec->string()->lengthLargerThan(0)); 234 | } 235 | 236 | public function testStringLargerThanOrEqualTo() 237 | { 238 | $spec = new TypeParser(new Config(), 'groupId', 'A'); 239 | $this->assertInstanceOf(StringLengthLargerThanOrEqualToParser::class, $spec->string()->lengthLargerThanOrEqualTo(1)); 240 | } 241 | 242 | public function testStringSmallerThan() 243 | { 244 | $spec = new TypeParser(new Config(), 'groupId', 'A'); 245 | $this->assertInstanceOf(StringLengthSmallerThanParser::class, $spec->string()->lengthSmallerThan(2)); 246 | } 247 | 248 | public function testStringSmallerThanOrEqualTo() 249 | { 250 | $spec = new TypeParser(new Config(), 'groupId', 'A'); 251 | $this->assertInstanceOf(StringLengthSmallerThanOrEqualToParser::class, $spec->string()->lengthSmallerThanOrEqualTo(1)); 252 | } 253 | } 254 | --------------------------------------------------------------------------------