diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..c451dda
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,18 @@
+; This file is for unifying the coding style for different editors and IDEs.
+; More information at http://editorconfig.org
+
+root = true
+
+[*]
+charset = utf-8
+indent_size = 4
+indent_style = space
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[*.md]
+trim_trailing_whitespace = false
+
+[*.yml]
+indent_size = 2
diff --git a/.github/ISSUE_TEMPLATE/Bug.md b/.github/ISSUE_TEMPLATE/Bug.md
new file mode 100644
index 0000000..f563f05
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/Bug.md
@@ -0,0 +1,24 @@
+---
+name: 🐛 Bug
+about: Did you encounter a bug?
+---
+
+### Bug Report
+
+
+
+| Q | A
+|------------ | ------
+| BC Break | yes/no
+| Version | x.y.z
+
+#### Summary
+
+
+
+#### How to reproduce
+
+
diff --git a/.github/ISSUE_TEMPLATE/Feature_Request.md b/.github/ISSUE_TEMPLATE/Feature_Request.md
new file mode 100644
index 0000000..de0f669
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/Feature_Request.md
@@ -0,0 +1,21 @@
+---
+name: 🎉 Feature Request
+about: Do you have a new feature in mind?
+---
+
+### Feature Request
+
+
+
+| Q | A
+|------------ | ------
+| New Feature | yes/no
+| BC Break | yes/no
+
+#### Scenario / Use-case
+
+
+
+#### Summary
+
+
diff --git a/.github/ISSUE_TEMPLATE/Question.md b/.github/ISSUE_TEMPLATE/Question.md
new file mode 100644
index 0000000..fa8e763
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/Question.md
@@ -0,0 +1,8 @@
+---
+name: ❓ Question
+about: Are you unsure about something?
+---
+
+### Question
+
+
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..3fa51b5
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,51 @@
+name: CI
+
+on:
+ push:
+ branches: [ master ]
+ pull_request:
+ branches: [ master ]
+
+jobs:
+ build:
+ strategy:
+ matrix:
+ php: ['8.1', '8.2', '8.3']
+ include:
+ - php: '8.1'
+ send-to-scrutinizer: 'yes'
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v2
+ - name: Setup PHP with fail-fast
+ uses: shivammathur/setup-php@v2
+ with:
+ send-to-scrutinizer: 'no'
+ phpunit-flags: '--no-coverage'
+ php-version: ${{ matrix.php }}
+ coverage: xdebug
+ env:
+ fail-fast: true
+ - name: Validate composer.json and composer.lock
+ run: composer validate
+
+ - name: Cache Composer packages
+ id: composer-cache
+ uses: actions/cache@v2
+ with:
+ path: vendor
+ key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }}
+ restore-keys: |
+ ${{ runner.os }}-php-
+
+ - name: Install dependencies
+ if: steps.composer-cache.outputs.cache-hit != 'true'
+ run: composer install --prefer-dist --no-progress --no-suggest
+
+ - name: Run test suite
+ run: |
+ mkdir -p build/logs
+ composer run stan
+ composer run test
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
new file mode 100644
index 0000000..dfb2eff
--- /dev/null
+++ b/.github/workflows/docs.yml
@@ -0,0 +1,28 @@
+name: Publish docs
+
+on:
+ push:
+ tags:
+ - '*.*.*'
+jobs:
+ docs:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v1
+
+ - name: Build docs
+ run: |
+ curl -OS https://couscous.io/couscous.phar
+ php couscous.phar generate --target=build/docs/ ./docs
+
+ - name: FTP Deployer
+ uses: sand4rt/ftp-deployer@v1.1
+ with:
+ host: ${{ secrets.DOCS_FTP_HOST }}
+ username: ${{ secrets.DOCS_FTP_USER }}
+ password: ${{ secrets.DOCS_FTP_PASSWORD }}
+ remote_folder: validation
+ # The local folder location
+ local_folder: build/docs/
+ # Remove existing files inside FTP remote folder
+ cleanup: false # optional
diff --git a/.gitignore b/.gitignore
index c5048e4..8c1a9f2 100755
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,9 @@ composer.lock
website/
docs/.couscous
docs/couscous.phar
+php-cs-fixer.phar
+phpcbf.phar
+phpcs.phar
+phpmd.phar
+.phpunit.result.cache
+.php_cs.cache
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100755
index 37fecbf..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,26 +0,0 @@
-language: php
-
-php:
- - 5.3
- - 5.4
- - 5.5
- - 5.6
- - hhvm
- - '7'
-
-matrix:
- allow_failures:
- - php: 5.3
-
-before_script:
- - composer self-update
- - composer install --prefer-source
-
-script:
- - mkdir -p build/logs
- - cd tests
- - phpunit
-
-after_script:
- - wget https://scrutinizer-ci.com/ocular.phar
- - php ocular.phar code-coverage:upload --format=php-clover ../build/logs/clover.xml
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 40416ca..c1cc350 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,7 +1,23 @@
+#### 3.0.0
+
+- Simplified the API (ie: less options to create rules)
+- Expanded the ability to set custom error messages per selector (eg: "address.city.required")
+
+#### 2.3.0
+
+- Removed 5.* support
+
+#### 2.2.0
+
+- added `Upload\Required` rule
+- fixed upload validators when the upload was not successful
+
#### 2.0.0
-- added the `data_key:label` feature
+- added the `data_selector:label` feature
- implemented default rule messages in the `RuleFactory` class. This way, if you have a custom error message for the `required` fields, you don't have to provide it to all the required fields, just set it up once in the `RuleFactory`
+- implemented a way to allow validation rule options to be passed as CSV (eg: '100,200' instead of 'min=200&max=200')
+
#### 1.2.4
diff --git a/composer.json b/composer.json
index bd4d042..e902d5d 100755
--- a/composer.json
+++ b/composer.json
@@ -17,15 +17,32 @@
}
],
"require": {
- "php": ">=5.3"
- },
- "require-dev": {
- "phpunit/phpunit": "3.7",
- "satooshi/php-coveralls": "dev-master"
+ "php": ">=8.0"
},
"autoload": {
- "files": [
- "autoload.php"
+ "psr-4": {
+ "Sirius\\Validation\\": "src/"
+ }
+ },
+ "scripts": {
+ "stan": [
+ "php vendor/bin/phpstan analyse"
+ ],
+ "csfix": [
+ "tools/php-cs-fixer/vendor/bin/php-cs-fixer fix --standard=PSR-2 src"
+ ],
+ "test": [
+ "php vendor/bin/pest"
]
+ },
+ "require-dev": {
+ "pestphp/pest": "*",
+ "phpstan/phpstan": "^1.10",
+ "pestphp/pest-plugin-drift": "^2.5"
+ },
+ "config": {
+ "allow-plugins": {
+ "pestphp/pest-plugin": true
+ }
}
}
diff --git a/docs/complex_validators.md b/docs/complex_validators.md
index 838f2fb..716f7b6 100644
--- a/docs/complex_validators.md
+++ b/docs/complex_validators.md
@@ -50,7 +50,7 @@ $UniqueUsername = $dependencyInjectionContainer->get('UniqueUsername');
$validator = new Validator($ruleFactory);
// the second parameter for the add() can be the name of a rule or a callback
-$validator->add('username', array($UniqueUsername, 'validate'));
+$validator->add('username', [$UniqueUsername, 'validate'];);
```
###2. Pass the dependencies as options
@@ -76,9 +76,9 @@ and in your validator you do something like
```
$dbConn = $serviceLocator->get('dbconnection');
-$validator->add('username', 'MyApp\Validation\Rule\UniqueUsername', array(
+$validator->add('username', 'MyApp\Validation\Rule\UniqueUsername', [
'db_connection' => $dbConn
-));
+];);
```
###3. Extend the `RuleFactory` class
@@ -100,7 +100,7 @@ class RuleFactory extends \Sirius\Validation\RuleFactory {
protected function constructValidatorByNameAndOptions($name, $options) {
$validatorClass = $this->validatorsMap[$name];
- $validator = $this->dic->createInstanceWithParams($validatorClass, array($options));
+ $validator = $this->dic->createInstanceWithParams($validatorClass, [$options];);
return $validator;
}
}
@@ -136,4 +136,4 @@ use Sirius\Validation\Validator;
$validator = new Validator($container->get('RuleFactory'));
$validator->add('username', 'MyApp\Validation\Rule\UniqueUsername');
-```
\ No newline at end of file
+```
diff --git a/docs/couscous.yml b/docs/couscous.yml
index 3055226..38aa5c7 100644
--- a/docs/couscous.yml
+++ b/docs/couscous.yml
@@ -12,7 +12,9 @@ exclude:
# Base URL of the published website (no "/" at the end!)
# You are advised to set and use this variable to write your links in the HTML layouts
-baseUrl: http://www.sirius.ro/php/validation
+baseUrl: //www.sirius.ro/php/sirius/validation
+paypal: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=SGXDKNJCXFPJU
+gacode: UA-535999-18
projectName: Sirius\Validation
title: Sirius\Validation
@@ -83,4 +85,4 @@ menu:
relativeUrl: custom_rule.html
translate_messages:
text: Translating the error messages
- relativeUrl: translate_messages.html
\ No newline at end of file
+ relativeUrl: translate_messages.html
diff --git a/docs/custom_rule.md b/docs/custom_rule.md
index f10ef51..953707a 100644
--- a/docs/custom_rule.md
+++ b/docs/custom_rule.md
@@ -21,18 +21,18 @@ class ThisOrThat extends AbstractRule {
const OPTION_THAT = 'that';
// specify default options if you want
- protected $options = array(
+ protected $options = [
'this' => 'a',
'that' => 'b'
- );
+ ];;
// if you want to let the user pass the options as a CSV (eg: 'this,that')
// you need to provide a `optionsIndexMap` property which will convert the options list
// into an associative array of options
- protected $optionsIndexMap = array(
+ protected $optionsIndexMap = [
0 => self::OPTION_THIS,
1 => self::OPTION_THAT
- );
+ ];;
function validate($value, $valueIdentifier = null) {
return $value == $this->options[self::OPTION_THIS] || $value == $this->options[self::OPTION_THAT];
@@ -50,11 +50,12 @@ use Sirius\Validation\Validator;
use MyApp\Validation\Rule\ThisOrThat;
$validator = new Validator();
-$validator->add('key', 'MyApp\Validation\Rule\ThisOrThat', array(
+$validator->add('key', 'MyApp\Validation\Rule\ThisOrThat', [
ThisOrThat::OPTION_THIS => 'c',
ThisOrThat::OPTION_THAT => 'd'
-));
+];);
// or less verbose
+$validator->add('key', 'MyApp\Validation\Rule\ThisOrThat(this=c&that=d)');
$validator->add('key', 'MyApp\Validation\Rule\ThisOrThat(c,d)');
-```
\ No newline at end of file
+```
diff --git a/docs/index.md b/docs/index.md
index a796e83..f15d166 100755
--- a/docs/index.md
+++ b/docs/index.md
@@ -12,7 +12,7 @@ Sirius Validation is a library for data validation. It offers:
1. [validator object](validator.md)
2. [45 build-in validation rules](validation_rules.md). There are validators for strings, array, numbers, emails, URLs, files and uploads
-3. [validation helper](helper.md) to simplify the validation of single values
+3. [validation helper](validation_helper.md) to simplify the validation of single values
Out-of-the-box, the library can handle `array`s, `ArrayObject`s and objects that have implemented the `toArray` method.
In order to validate other data containers you must create a [`DataWrapper`](https://github.com/siriusphp/validation/blob/master/src/Validation/DataWrapper/WrapperInterface.php) so that the validator be able to extract data from your object.
@@ -24,20 +24,29 @@ $validation = new \Sirius\Validation\Validator;
// let's validate an invoice form
$validator->add(array(
- 'date:Date' => 'required | date',
- 'client_id:Client' => 'required | clientexists', // clientexists is an app-specific rule
- 'notify_recipients[*]:Send invoice to' => 'email', // same rule for an array of items
+ // :Date specifies the label for the field. It will be used in the error messages
+ 'order_date:Date' => 'required | date',
+ // `clientexists` is an app-specific rule
+ 'client_id:Client' => 'required | clientexists',
+ // apply the same rule for an array of items
+ 'notify_recipients[*]:Send invoice to' => 'email',
+ // apply a rule to a specific item in the array
'shipping_address[line_1]:Address' => 'required'
'shipping_address[city]:City' => 'required'
'shipping_address[state]:State' => 'required'
'shipping_address[country]:Country' => 'required',
- 'lines[*]price:Price' => array(
- 'requiredWith(item=lines[*]product_id', // the price is required only if a product was selected
- 'MyApp\Validator\Rule\InvoiceItemPrice' // another app-specific rule, specified as a class
- ),
- 'lines[*]quantity:Quantity' => array(
- 'requiredWith(item=lines[*]product_id',
- ('invoice_item_quantity', 'The quantity is not valid') // here we have a custom error message
+ 'lines[*]price:Price' => [
+ // the price is required only if a product was selected
+ 'requiredWith(item=lines[*]product_id)',
+ // another app-specific rule applied to the price, specified as a class
+ 'MyApp\Validator\Rule\InvoiceItemPrice'
+ ];,
+ 'lines[*]quantity:Quantity' => [
+ // the price is required only if a product was selected
+ 'requiredWith(item=lines[*]product_id)',
+ // here we have a custom validation rule with no parameters AND a custom error message
+ 'quantity_in_stock()(The quantity is not valid)'
+ ;
)
));
```
@@ -56,7 +65,7 @@ This may seem counter-productive but remember that your forms' input fields may
```
2. Because, If I am to do server side validation I can receive a JSON
-```javascript
+```json
{
"errors": {
"recipients[0]": "Field must be a valid email",
@@ -82,4 +91,4 @@ $clientSideRules = $helperThatCompilesTheClientSideValidation->getValidationRule
?>
$('#myForm').validate();
-```
\ No newline at end of file
+```
diff --git a/docs/installation.md b/docs/installation.md
index 86f9f0b..7dc2d9c 100644
--- a/docs/installation.md
+++ b/docs/installation.md
@@ -8,7 +8,7 @@ title: Installating Sirius\Validation
Sirius\Validation is available on [Packagist](https://packagist.org/packages/siriusphp/validation) so you can use
```
-composer require sirius/validation
+composer require siriusphp/validation
```
Make sure to include the Composer autoload file in your project
@@ -18,4 +18,4 @@ require 'vendor/autoload.php';
## Downloading a `.zip` file
-This project is also available for download as a `.zip` file on GitHub. Visit the [releases page](https://github.com/siriusphp/validation/releases), select the version you want, and click the "Source code (zip)" download button.
\ No newline at end of file
+This project is also available for download as a `.zip` file on GitHub. Visit the [releases page](https://github.com/siriusphp/validation/releases), select the version you want, and click the "Source code (zip)" download button.
diff --git a/docs/simple_example.md b/docs/simple_example.md
index 1f45e6b..2464d6d 100644
--- a/docs/simple_example.md
+++ b/docs/simple_example.md
@@ -13,7 +13,7 @@ use Sirius\Validation\Validator;
$validator = new Validator();
$validator->add(
- array(
+ [
// the key is in the form [field]:[label]
'name:Name' => 'required',
@@ -22,7 +22,7 @@ $validator->add(
'email:Your email' => 'required | email',
// validators can have options
- 'message:Your message' => 'required | minlength(10)'
+ 'message:Your message' => 'required | minlength(10];',
// and you can overwrite the default error message
'phone:Phone' => 'regex(/your_regex_here/)(This field must be a valid US phone number)'
@@ -47,4 +47,4 @@ if ($validator->validate($_POST)) {
}
```
-Easy-peasy, right?
\ No newline at end of file
+Easy-peasy, right?
diff --git a/docs/syntactic_sugar.md b/docs/syntactic_sugar.md
index 55b36db..d487766 100644
--- a/docs/syntactic_sugar.md
+++ b/docs/syntactic_sugar.md
@@ -18,7 +18,7 @@ $validator->add('name', 'minlength({"min":2})({label} must have at least {min} c
$validator->add('name', 'minlength(min=2)({label} must have at least {min} characters)(Name)');
// the above examples are similar to
-$validator->add('name', 'minlength', array('min' => 2), '{label} must have at least {min} characters', 'Name');
+$validator->add('name', 'minlength', ['min' => 2];, '{label} must have at least {min} characters', 'Name');
```
##### 3. Mix and match 1 and 2
@@ -33,11 +33,11 @@ Of course this means the error message cannot contain the ` | ` sequence
$validator->add(
// add the label after the selector so you don't have to pass the label to every rule
'email:Email',
- array(
+ [
// only using the name of the validation rule
'email',
- // or with all parameters (here passed as CSV)
- array('length', '2,100', '{label} must have between {min} and {max} characters'),
+ // or with all parameters (here passed as CSV];
+ ['length', '2,100', '{label} must have between {min} and {max} characters'];,
)
);
```
diff --git a/docs/translate_messages.md b/docs/translate_messages.md
index 687725b..062bd47 100644
--- a/docs/translate_messages.md
+++ b/docs/translate_messages.md
@@ -4,11 +4,10 @@ title: Translating the error messages
# Translating the error messages
-There are a couple of ways to translate the error messages, each having it's pros and cons:
+There are a couple of ways to translate the error messages, each having its pros and cons:
1. Postpone the translation until display
2. Use a translatable error message class
-3. Use translated string for the message templates
### 1.Postpone the translation until display
@@ -34,15 +33,6 @@ class TranslatableErrorMessage extends Sirius\Validation\ErrorMessage {
}
// later when constructing your validators
-$validator = new Sirius\Validation\Validator(null, new TranslatableErrorMessage);
-```
-
-### 3.Use translated string for the message templates
-
-```php
-// in the validator
-$validator->add('title:' . __('Title'), 'maxlength', 'max=100', __('{label} must have less than {max} characters'));
-
-// or the rule factory
-$ruleFactoryInstance->setErrorMessages('maxlength', __('This field must have less than {max} characters'), __('{label} must have less than {max} characters'));
+$translator = new MyTranslator();
+$validator = new Sirius\Validation\Validator(null, new TranslatableErrorMessage($translator));
```
diff --git a/docs/validation_rules.md b/docs/validation_rules.md
index bb0eaeb..e4e270d 100644
--- a/docs/validation_rules.md
+++ b/docs/validation_rules.md
@@ -22,14 +22,16 @@ title: Built-in validation rules
### Array validators
1. `ArrayLength`: values which are arrays must contain a specific number of items. Rule options: `min` and `max`
2. `ArrayMinlength`: array must contain at least a specific number of items: Rule options: `min`
-3. `ArrayMinlength`: array must contain at most a specific number of items: Rule options: `max`
-4. `InList: the value must be in a list of acceptable values. Rule options: `list`
-5. `NotInList: the value must not be in a list of forbidden values: Rule options: `list`
+3. `ArrayMaxlength`: array must contain at most a specific number of items: Rule options: `max`
+4. `InList`: the value must be in a list of acceptable values. Rule options: `list`
+5. `NotInList`: the value must not be in a list of forbidden values: Rule options: `list`
### Number validators
-7. `Between`: value must be a number between 2 limits: Rule options: `min` and `max`
-8. `LessThan`: value must be less than a number. Rule options: `max` and `inclusive` (to determine if the comparator is < or <=, defaults to TRUE)
-9. `GreaterThan`: value must be greater than a number. Rule options: `min` and `inclusive` (to determine if the comparator is > or >=, defaults to TRUE)
+1. `Number`: value must be a valid number
+2. `Integer`: value must be a valid integer
+3. `LessThan`: value must be less than a number. Rule options: `max` and `inclusive` (to determine if the comparator is < or <=, defaults to TRUE)
+4. `GreaterThan`: value must be greater than a number. Rule options: `min` and `inclusive` (to determine if the comparator is > or >=, defaults to TRUE)
+5. `Between`: value must be a number between 2 limits: Rule options: `min` and `max`. The same as `GreaterThan` and `LessThan`, both inclusive.
### Email/URLs validators
1. `Email`: value must be an email address. Uses a regular expression for validation
@@ -47,10 +49,13 @@ title: Built-in validation rules
2. `NotRegex`: value must NOT match a regular expression pattern. Rule options: `pattern`
3. `Callback`: checks if a value is valid using a custom callback (a function, an object's method, a class' static method). Rule options: `callback` and `arguments` (additional paramters for the callback)
4. `Match`: the value must match the value of another item in the context. Rule options: `item` (eg: if `auth[password_confirm]` must match `auth[password]` the `item` is `auth[password]`
-5. `Equal`: the value must be the same as predefined value. Rule options: `value`
+5. `NotMatch': the value must not match the value of another item in the context. Rule options: `item` (eg: if `auth[password]` must not match `auth[username]` the `item` is `auth[username]`
+6. `Equal`: the value must be the same as predefined value. Rule options: `value`
+7. `NotEqual`: the value must not be the same as predefined value. Rule options: `value`
### File validators
File validators work only with local files and they fail if the file does not exist
+
1. `File\Extension`. Checks if the file has a certain extension. Rule options: `allowed` which can be an array or a comma separated string.
2. `File\Image`. Checks if the file is an image of a certain type. Rule options: `allowed` which can be an array or a comma separated string (default: `jpg,png,gif`)
3. `File\ImageRatio`. Checks if the image has a certain ratio. Rule options: `ratio` which can be a number or a string like `4:3`, `error_margin` - how much the file's ratio can deviate from the target (default: 0)
@@ -60,11 +65,13 @@ File validators work only with local files and they fail if the file does not ex
### Upload validators
Upload validators work only uploaded files (each file is an upload-like array) and they fail if the temporary file does not exist.
-1. `Upload\Extension`. Checks if the uploaded file has a certain extension. Rule options: `allowed` which can be an array or a comma separated string.
-2. `Upload\Image`. Checks if the uploaded file is an image of a certain type. Rule options: `allowed` which can be an array or a comma separated string (default: `jpg,png,gif`)
-3. `Upload\ImageRatio`. Checks if the uploaded image has a certain ratio. Rule options: `ratio` which can be a number or a string like `4:3`, `error_margin` - how much the file's ratio can deviate from the target (default: 0)
-4. `Upload\ImageWidth`. Checks if the uploaded image's width is between certain limits. Rule options: `min` (default: 0) and `max` (default: 1 million)
-5. `Upload\ImageHeight`. Checks if the uploaded image's height is between certain limits. Rule options: `min` (default: 0) and `max` (default: 1 million)
-6. `Upload\Size`. Checks if the uploaded file' size is bellow a certain limit. Rule options: `size` which can be a number or a string like '10K', '0.5M' or '1.3G` (default: 2M)
-*Note!* The upload validators use only the `tmp_name` and `name` values to perform the validation
\ No newline at end of file
+1. `Upload\Required`. Checks if the uploaded file was uploaded and there are no errors.
+2. `Upload\Extension`. Checks if the uploaded file has a certain extension. Rule options: `allowed` which can be an array or a comma separated string.
+3. `Upload\Image`. Checks if the uploaded file is an image of a certain type. Rule options: `allowed` which can be an array or a comma separated string (default: `jpg,png,gif`)
+4. `Upload\ImageRatio`. Checks if the uploaded image has a certain ratio. Rule options: `ratio` which can be a number or a string like `4:3`, `error_margin` - how much the file's ratio can deviate from the target (default: 0)
+5. `Upload\ImageWidth`. Checks if the uploaded image's width is between certain limits. Rule options: `min` (default: 0) and `max` (default: 1 million)
+6. `Upload\ImageHeight`. Checks if the uploaded image's height is between certain limits. Rule options: `min` (default: 0) and `max` (default: 1 million)
+7. `Upload\Size`. Checks if the uploaded file' size is bellow a certain limit. Rule options: `size` which can be a number or a string like '10K', '0.5M' or '1.3G` (default: 2M)
+
+*Note!* The upload validators use only the `tmp_name` and `name` values to perform the validation
diff --git a/docs/validator.md b/docs/validator.md
index ab03f46..3ec881f 100755
--- a/docs/validator.md
+++ b/docs/validator.md
@@ -29,7 +29,7 @@ $validator->add($selector, $name = null, $options = null, $messageTemplate = nul
// examples
$validator->add('username', 'required');
-$validator->add('password', 'minLength', array('min' => 6), '{label} must have at least {min} characters', 'Password');
+$validator->add('password', 'minLength', ['min' => 6];, '{label} must have at least {min} characters', 'Password');
$validator->add('additional_emails[*]', 'email', array(), 'Email address is not valid');
```
diff --git a/phpmd.xml b/phpmd.xml
new file mode 100644
index 0000000..9294e77
--- /dev/null
+++ b/phpmd.xml
@@ -0,0 +1,28 @@
+
+
+ Sirius PMD ruleset
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/phpstan.neon b/phpstan.neon
new file mode 100644
index 0000000..6615f46
--- /dev/null
+++ b/phpstan.neon
@@ -0,0 +1,5 @@
+parameters:
+ level: 8
+ checkGenericClassInNonGenericObjectType: false
+ paths:
+ - src
diff --git a/phpunit.xml b/phpunit.xml
new file mode 100644
index 0000000..7d0904f
--- /dev/null
+++ b/phpunit.xml
@@ -0,0 +1,18 @@
+
+
+
+
+ ./tests
+
+
+
+
+ ./app
+ ./src
+
+
+
diff --git a/readme.md b/readme.md
index 5dabd7c..88c66e9 100755
--- a/readme.md
+++ b/readme.md
@@ -1,12 +1,12 @@
-#Sirius Validation
+# Sirius Validation
-[](https://github.com/siriusphp/validation)
-[](https://github.com/siriusphp/validation/releases)
-[](https://github.com/siriusphp/validation/blob/master/LICENSE)
-[](https://travis-ci.org/siriusphp/validation)
-[](https://scrutinizer-ci.com/g/siriusphp/validation/code-structure)
-[](https://scrutinizer-ci.com/g/siriusphp/validation)
-[](https://packagist.org/packages/siriusphp/validation)
+[](https://github.com/siriusphp/validation)
+[](https://github.com/siriusphp/validation/releases)
+[](https://github.com/siriusphp/validation/blob/master/LICENSE)
+[](https://github.com/siriusphp/validation/actions)
+[](https://scrutinizer-ci.com/g/siriusphp/validation/code-structure)
+[](https://scrutinizer-ci.com/g/siriusphp/validation)
+[](https://packagist.org/packages/siriusphp/validation)
Sirius Validation is a library for data validation. It offers:
@@ -17,10 +17,10 @@ Sirius Validation is a library for data validation. It offers:
Out-of-the-box, the library can handle `array`s, `ArrayObject`s and objects that have implemented the `toArray` method.
In order to validate other data containers you must create a [`DataWrapper`](https://github.com/siriusphp/validation/blob/master/src/Validation/DataWrapper/WrapperInterface.php) so that the validator be able to extract data from your object.
-##Elevator pitch
+## Elevator pitch
```php
-$validation = new \Sirius\Validation\Validator;
+$validator = new \Sirius\Validation\Validator;
// add a validation rule
$validator->add('title', 'required');
@@ -40,18 +40,17 @@ $validator->add('title', 'maxlength', 'max=100', 'Article title must have less t
// add a rule with a custom message and a label (very handy with forms)
$validator->add('title:Title', 'maxlength', 'max=100', '{label} must have less than {max} characters');
-// add all of rule's configuration in a string (you'll see later why it's handy')
-$validator->add('title:Title', 'maxlength(max=255)({label} must have less than {max} characters)');
-
// add multiple rules at once (separate using [space][pipe][space])
$validator->add('title:Title', 'required | maxlength(255) | minlength(min=10)');
// add all your rules at once
-$validator->add(array(
- 'title:Title' => 'required | maxlength(100)({label} must have less than {max} characters)',
- 'content:Content' => 'required',
- 'source:Source' => 'website'
-));
+$validator->add([
+ 'title:Title' => 'required | maxlength(100)',
+ 'content:Content' => 'required',
+ 'source:Source' => 'website'
+ ], [
+ 'content.required' => 'The content field should have a velue'
+ ]);
// add nested rules
$validator->add('recipients[*]:Recipients', 'email'); //all recipients must be valid email addresses
@@ -59,13 +58,8 @@ $validator->add('shipping_address[city]:City', 'MyApp\Validator\City'); // uses
```
-##Links
+## Links
-- [documentation](http://www.sirius.ro/php/sirius/validation)
+- [documentation](http://sirius.ro/php/sirius/validation/)
- [changelog](CHANGELOG.md)
-##Known issues
-
-In PHP 5.3 there is some problem with the SplObject storage that prevents the library to remove validation rules.
-This means that in PHP 5.3, you cannot remove a validation rule from a `Validator` or `ValueValidator` object
-
diff --git a/src/DataWrapper/ArrayWrapper.php b/src/DataWrapper/ArrayWrapper.php
index e473fec..42985e6 100644
--- a/src/DataWrapper/ArrayWrapper.php
+++ b/src/DataWrapper/ArrayWrapper.php
@@ -1,23 +1,24 @@
*/
- protected $data = array();
+ protected array $data = [];
/**
- * @param array|\ArrayObject|object $data
+ * @param array|\ArrayObject|object $data
+ *
* @throws \InvalidArgumentException
*/
- public function __construct($data = array())
+ public function __construct(mixed $data)
{
if (is_object($data)) {
if ($data instanceof \ArrayObject) {
@@ -32,12 +33,15 @@ public function __construct($data = array())
$this->data = $data;
}
- public function getItemValue($item)
+ public function getItemValue(string $item): mixed
{
return Arr::getByPath($this->data, $item);
}
- public function getItemsBySelector($selector)
+ /**
+ * @return array
+ */
+ public function getItemsBySelector(string $selector): array
{
return Arr::getBySelector($this->data, $selector);
}
diff --git a/src/DataWrapper/WrapperInterface.php b/src/DataWrapper/WrapperInterface.php
index 331201b..1ccdb93 100644
--- a/src/DataWrapper/WrapperInterface.php
+++ b/src/DataWrapper/WrapperInterface.php
@@ -1,4 +1,5 @@
*/
- public function getItemsBySelector($selector);
-
+ public function getItemsBySelector(string $selector): array;
}
diff --git a/src/ErrorMessage.php b/src/ErrorMessage.php
index 57da774..967cb1d 100755
--- a/src/ErrorMessage.php
+++ b/src/ErrorMessage.php
@@ -1,29 +1,45 @@
+ */
+ protected array $variables = [];
+
+ /**
+ * @param array $variables
+ */
+ public function __construct(string $template = '', array $variables = [])
{
$this->setTemplate($template)
->setVariables($variables);
}
- public function setTemplate($template)
+ public function setTemplate(string $template): self
{
- $template = trim((string)$template);
+ $template = trim($template);
if ($template) {
- $this->template = (string)$template;
+ $this->template = $template;
}
return $this;
}
- public function setVariables($variables = array())
+ public function getTemplate(): string
+ {
+ return $this->template;
+ }
+
+ /**
+ * @param array $variables
+ */
+ public function setVariables(array $variables = []): self
{
foreach ($variables as $k => $v) {
$this->variables[$k] = $v;
@@ -32,12 +48,20 @@ public function setVariables($variables = array())
return $this;
}
+ /**
+ * @return array
+ */
+ public function getVariables(): array
+ {
+ return $this->variables;
+ }
+
public function __toString()
{
$result = $this->template;
foreach ($this->variables as $k => $v) {
if (strpos($result, "{{$k}}") !== false) {
- $result = str_replace("{{$k}}", $v, $result);
+ $result = str_replace("{{$k}}", (string)$v, (string)$result);
}
}
diff --git a/src/Helper.php b/src/Helper.php
index 12c2cad..45eefe1 100755
--- a/src/Helper.php
+++ b/src/Helper.php
@@ -1,30 +1,39 @@
+ */
+ protected static array $methods = [];
- protected static $methods = array();
-
- public static function addMethod($ruleName, $callback)
+ /**
+ * @param callable|\Closure $callback
+ */
+ public static function addMethod(string $ruleName, mixed $callback): void
{
if (is_callable($callback)) {
self::$methods[$ruleName] = $callback;
-
- return true;
+ return;
}
- return false;
+ throw new \InvalidArgumentException(sprintf('Validation method "%s" is not callable', $ruleName)); // @phpstan-ignore-line
}
- public static function methodExists($name)
+ public static function methodExists(string $name): bool
{
return method_exists(__CLASS__, $name) || array_key_exists($name, self::$methods);
}
- public static function __callStatic($name, $arguments)
+ /**
+ * @param array $arguments
+ */
+ public static function __callStatic(string $name, array $arguments = []): mixed
{
if (array_key_exists($name, self::$methods)) {
return call_user_func_array(self::$methods[$name], $arguments);
@@ -32,7 +41,10 @@ public static function __callStatic($name, $arguments)
throw new \InvalidArgumentException(sprintf('Validation method "%s" does not exist', $name));
}
- public static function callback($value, $callback, $context = array())
+ /**
+ * @param array $context
+ */
+ public static function callback(mixed $value, callable $callback, array $context = []): bool
{
$validator = new Rule\Callback();
$validator->setOption('callback', $callback);
@@ -41,209 +53,181 @@ public static function callback($value, $callback, $context = array())
return $validator->validate($value);
}
- public static function required($value)
+ public static function required(mixed $value): bool
{
- return $value !== null && trim($value) !== '';
+ return $value !== null && (!is_string($value) || trim($value) !== '');
}
- public static function truthy($value)
+ public static function truthy(mixed $value): bool
{
return (bool)$value;
}
- public static function falsy($value)
+ public static function falsy(mixed $value): bool
{
return !static::truthy($value);
}
- public static function number($value)
+ public static function number(mixed $value): bool
{
return $value == '0' || is_numeric($value);
}
- public static function integer($value)
+ public static function integer(mixed $value): bool
{
return $value == '0' || (int)$value == $value;
}
- public static function lessThan($value, $max)
+ public static function lessThan(mixed $value, int|float $max): bool
{
- $validator = new Rule\LessThan(
- array(
- 'max' => $max
- )
- );
+ $validator = new Rule\LessThan(['max' => $max]);
return $validator->validate($value);
}
- public static function greaterThan($value, $min)
+ public static function greaterThan(mixed $value, int|float $min): bool
{
- $validator = new Rule\GreaterThan(
- array(
- 'min' => $min
- )
- );
+ $validator = new Rule\GreaterThan(['min' => $min]);
return $validator->validate($value);
}
- public static function between($value, $min, $max)
+ public static function between(mixed $value, int|float $min, int|float $max): bool
{
- $validator = new Rule\Between(
- array(
- 'min' => $min,
- 'max' => $max
- )
- );
+ $validator = new Rule\Between([
+ 'min' => $min,
+ 'max' => $max
+ ]);
return $validator->validate($value);
}
- public static function exactly($value, $otherValue)
+ public static function exactly(mixed $value, mixed $otherValue): bool
{
return $value == $otherValue;
}
- public static function not($value, $otherValue)
+ public static function not(mixed $value, mixed $otherValue): bool
{
return !self::exactly($value, $otherValue);
}
- public static function alpha($value)
+ public static function alpha(mixed $value): bool
{
$validator = new Rule\Alpha();
return $validator->validate($value);
}
- public static function alphanumeric($value)
+ public static function alphanumeric(mixed $value): bool
{
$validator = new Rule\AlphaNumeric();
return $validator->validate($value);
}
- public static function alphanumhyphen($value)
+ public static function alphanumhyphen(mixed $value): bool
{
$validator = new Rule\AlphaNumHyphen();
return $validator->validate($value);
}
- public static function minLength($value, $min)
+ public static function minLength(string $value, int $min): bool
{
- $validator = new Rule\MinLength(
- array(
- 'min' => $min
- )
- );
+ $validator = new Rule\MinLength(['min' => $min]);
return $validator->validate($value);
}
- public static function maxLength($value, $max)
+ public static function maxLength(string $value, int $max): bool
{
- $validator = new Rule\MaxLength(
- array(
- 'max' => $max
- )
- );
+ $validator = new Rule\MaxLength(['max' => $max]);
return $validator->validate($value);
}
- public static function length($value, $min, $max)
+ public static function length(string $value, int $min, int $max): bool
{
- $validator = new Rule\Length(
- array(
- 'min' => $min,
- 'max' => $max
- )
- );
+ $validator = new Rule\Length([
+ 'min' => $min,
+ 'max' => $max
+ ]);
return $validator->validate($value);
}
- public static function setMinSize($value, $min)
+ /**
+ * @param array $value
+ */
+ public static function setMinSize(array $value, int $min): bool
{
- $validator = new Rule\ArrayMinLength(
- array(
- 'min' => $min
- )
- );
+ $validator = new Rule\ArrayMinLength(['min' => $min]);
return $validator->validate($value);
}
- public static function setMaxSize($value, $max)
+ /**
+ * @param array $value
+ */
+ public static function setMaxSize(array $value, int $max): bool
{
- $validator = new Rule\ArrayMaxLength(
- array(
- 'max' => $max
- )
- );
+ $validator = new Rule\ArrayMaxLength(['max' => $max]);
return $validator->validate($value);
}
- public static function setSize($value, $min, $max)
+ /**
+ * @param array $value
+ */
+ public static function setSize(array $value, int $min, int $max): bool
{
- $validator = new Rule\ArrayLength(
- array(
- 'min' => $min,
- 'max' => $max
- )
- );
+ $validator = new Rule\ArrayLength([
+ 'min' => $min,
+ 'max' => $max
+ ]);
return $validator->validate($value);
}
- public static function in($value, $values)
+ /**
+ * @param list $values
+ */
+ public static function inList(mixed $value, array $values): bool
{
- $validator = new Rule\InList(
- array(
- 'list' => $values
- )
- );
+ $validator = new Rule\InList(['list' => $values]);
return $validator->validate($value);
}
- public static function notIn($value, $values)
+ /**
+ * @param list $values
+ */
+ public static function notInList(mixed $value, array $values): bool
{
- $validator = new Rule\NotInList(
- array(
- 'list' => $values
- )
- );
+ $validator = new Rule\NotInList(['list' => $values]);
return $validator->validate($value);
}
- public static function regex($value, $pattern)
+ public static function regex(mixed $value, string $pattern): bool
{
- $validator = new Rule\Regex(
- array(
- 'pattern' => $pattern
- )
- );
+ $validator = new Rule\Regex(['pattern' => $pattern]);
return $validator->validate($value);
}
- public static function notRegex($value, $pattern)
+ public static function notRegex(mixed $value, string $pattern): bool
{
- $validator = new Rule\NotRegex(
- array(
- 'pattern' => $pattern
- )
- );
+ $validator = new Rule\NotRegex(['pattern' => $pattern]);
return $validator->validate($value);
}
- public static function equalTo($value, $otherElementOrValue, $context = null)
+ /**
+ * @param array $context
+ */
+ public static function equalTo(mixed $value, mixed $otherElementOrValue, array $context = []): bool
{
if (func_num_args() == 2) {
return $value == $otherElementOrValue;
@@ -252,67 +236,61 @@ public static function equalTo($value, $otherElementOrValue, $context = null)
return $value == Arr::getByPath($context, $otherElementOrValue);
}
- public static function date($value, $format = 'Y-m-d')
+ /**
+ * @param array $context
+ */
+ public static function notEqualTo(mixed $value, mixed $otherElementOrValue, array $context = []): bool
+ {
+ if (func_num_args() == 2) {
+ return $value != $otherElementOrValue;
+ }
+
+ return $value != Arr::getByPath($context, $otherElementOrValue);
+ }
+
+ public static function date(mixed $value, string $format = 'Y-m-d'): bool
{
- $validator = new Rule\Date(
- array(
- 'format' => $format
- )
- );
+ $validator = new Rule\Date(['format' => $format]);
return $validator->validate($value);
}
- public static function dateTime($value, $format = 'Y-m-d H:i:s')
+ public static function dateTime(mixed $value, string $format = 'Y-m-d H:i:s'): bool
{
- $validator = new Rule\DateTime(
- array(
- 'format' => $format
- )
- );
+ $validator = new Rule\DateTime(['format' => $format]);
return $validator->validate($value);
}
- public static function time($value, $format = 'H:i:s')
+ public static function time(mixed $value, string $format = 'H:i:s'): bool
{
- $validator = new Rule\Time(
- array(
- 'format' => $format
- )
- );
+ $validator = new Rule\Time(['format' => $format]);
return $validator->validate($value);
}
- public static function website($value)
+ public static function website(mixed $value): bool
{
$validator = new Rule\Website();
return $validator->validate($value);
}
- public static function url($value)
+ public static function url(mixed $value): bool
{
$validator = new Rule\Url();
return $validator->validate($value);
}
- /**
- * Test if a variable is a valid IP address
- *
- * @param string $value
- * @return bool
- */
- public static function ip($value)
+ public static function ipAddress(mixed $value): bool
{
$validator = new Rule\IpAddress();
return $validator->validate($value);
}
- public static function email($value)
+ public static function email(mixed $value): bool
{
$validator = new Rule\Email();
@@ -322,11 +300,8 @@ public static function email($value)
/**
* Test if a variable is a full name
* Criterias: at least 6 characters, 2 words
- *
- * @param mixed $value
- * @return bool
*/
- public static function fullName($value)
+ public static function fullName(mixed $value): bool
{
$validator = new Rule\FullName();
@@ -335,11 +310,8 @@ public static function fullName($value)
/**
* Test if the domain of an email address is available
- *
- * @param string $value
- * @return bool
*/
- public static function emailDomain($value)
+ public static function emailDomain(mixed $value): bool
{
$validator = new Rule\EmailDomain();
diff --git a/src/Rule/AbstractRule.php b/src/Rule/AbstractRule.php
index 8a67074..a61fd4d 100644
--- a/src/Rule/AbstractRule.php
+++ b/src/Rule/AbstractRule.php
@@ -1,9 +1,12 @@
*/
- protected $options = array();
+ protected array $options = [];
/**
* Custom error message template for the validator instance
* If you don't agree with the default messages that were provided
- *
- * @var string
*/
- protected $messageTemplate;
+ protected string $messageTemplate;
/**
* Result of the last validation
- *
- * @var boolean
*/
- protected $success = false;
+ protected bool $success = false;
/**
* Last value validated with the validator.
* Stored in order to be passed to the errorMessage so that you get error
* messages like '"abc" is not a valid email'
- *
- * @var mixed
*/
- protected $value;
+ protected mixed $value = null;
/**
* The error message prototype that will be used to generate the error message
- *
- * @var ErrorMessage
*/
- protected $errorMessagePrototype;
-
- public function __construct($options = array())
- {
- $options = $this->normalizeOptions($options);
- if (is_array($options) && !empty($options)) {
- foreach ($options as $k => $v) {
- $this->setOption($k, $v);
- }
- }
- }
-
- /**
- * Method that parses the option variable and converts it into an array
- * You can pass anything to a validator like:
- * - a query string: 'min=3&max=5'
- * - a JSON string: '{"min":3,"max":5}'
- * - a CSV string: '5,true' (for this scenario the 'optionsIndexMap' property is required)
- *
- * @param mixed $options
- *
- * @return array
- * @throws \InvalidArgumentException
- */
- protected function normalizeOptions($options)
- {
- if (!$options) {
- return array();
- }
-
- if (is_array($options) && $this->arrayIsAssoc($options)) {
- return $options;
- }
-
- $result = $options;
- if ($options && is_string($options)) {
- $startChar = substr($options, 0, 1);
- if ($startChar == '{') {
- $result = json_decode($options, true);
- } elseif (strpos($options, '=') !== false) {
- $result = $this->parseHttpQueryString($options);
- } else {
- $result = $this->parseCsvString($options);
- }
- }
-
- if (!is_array($result)) {
- throw new \InvalidArgumentException('Validator options should be an array, JSON string or query string');
- }
-
- return $result;
- }
+ protected ?ErrorMessage $errorMessagePrototype = null;
/**
- * Converts a HTTP query string to an array
+ * Options map in case the options are passed as list instead of associative array
*
- * @param $str
- * @return array
+ * @var array
*/
- protected function parseHttpQueryString($str) {
- parse_str($str, $arr);
- return $this->convertBooleanStrings($arr);
- }
+ protected array $optionsIndexMap = [];
/**
- * Converts 'true' and 'false' strings to TRUE and FALSE
- *
- * @param $v
- * @return bool
+ * @param array|string|null $options
*/
- protected function convertBooleanStrings($v) {
- if (is_array($v)) {
- return array_map(array($this, 'convertBooleanStrings'), $v);
- }
- if ($v === 'true') {
- return true;
- }
- if ($v === 'false') {
- return false;
- }
- return $v;
- }
-
- /**
- * Parses a CSV string and converts the result into an "options" array
- * (an associative array that contains the options for the validation rule)
- *
- * @param $str
- * @return array
- */
- protected function parseCsvString($str) {
- if (!isset($this->optionsIndexMap) || !is_array($this->optionsIndexMap) || empty($this->optionsIndexMap)) {
- throw new \InvalidArgumentException(sprintf('Class %s is missing the `optionsIndexMap` property', get_class($this)));
- }
-
- $options = explode(',', $str);
- $result = array();
- foreach ($options as $k => $v) {
- if (!isset($this->optionsIndexMap[$k])) {
- throw new \InvalidArgumentException(sprintf('Class %s does not have the index %d configured in the `optionsIndexMap` property', get_class($this), $k));
+ public function __construct(mixed $options = null)
+ {
+ $options = RuleHelper::normalizeOptions($options, $this->optionsIndexMap);
+ if (is_array($options) && !empty($options)) {
+ foreach ($options as $k => $v) {
+ $this->setOption((string) $k, $v);
}
- $result[$this->optionsIndexMap[$k]] = $v;
}
- return $this->convertBooleanStrings($result);
}
- /**
- * Checks if an array is associative (ie: the keys are not numbers in sequence)
- *
- * @param array $arr
- * @return bool
- */
- protected function arrayIsAssoc($arr)
- {
- return array_keys($arr) !== range(0, count($arr));
- }
-
-
/**
* Generates a unique string to identify the validator.
* It is used to compare 2 validators so you don't add the same rule twice in a validator object
- *
- * @return string
*/
- public function getUniqueId()
+ public function getUniqueId(): string
{
return get_called_class() . '|' . json_encode(ksort($this->options));
}
@@ -190,29 +87,39 @@ public function getUniqueId()
* Set an option for the validator.
*
* The options are also be passed to the error message.
- *
- * @param string $name
- * @param mixed $value
- * @return \Sirius\Validation\Rule\AbstractRule
*/
- public function setOption($name, $value)
+ public function setOption(string $name, mixed $value): static
{
$this->options[$name] = $value;
return $this;
}
+ /**
+ * Get an option for the validator.
+ *
+ * @return mixed
+ */
+ public function getOption(string $name)
+ {
+ if (isset($this->options[$name])) {
+ return $this->options[$name];
+ } else {
+ return null;
+ }
+ }
+
/**
* The context of the validator can be used when the validator depends on other values
* that are not known at the moment the validator is constructed
* For example, when you need to validate an email field matches another email field,
* to confirm the email address
*
- * @param array|object $context
+ * @param array|WrapperInterface $context
+ *
* @throws \InvalidArgumentException
- * @return \Sirius\Validation\Rule\AbstractRule
*/
- public function setContext($context = null)
+ public function setContext(mixed $context = null): self
{
if ($context === null) {
return $this;
@@ -220,9 +127,10 @@ public function setContext($context = null)
if (is_array($context)) {
$context = new ArrayWrapper($context);
}
- if (!is_object($context) || !$context instanceof WrapperInterface) {
+ if (!$context instanceof WrapperInterface) {
throw new \InvalidArgumentException(
- 'Validator context must be either an array or an instance of Sirius\Validator\DataWrapper\WrapperInterface'
+ 'Validator context must be either an array or an instance
+ of ' . WrapperInterface::class
);
}
$this->context = $context;
@@ -234,7 +142,8 @@ public function setContext($context = null)
* Custom message for this validator to used instead of the the default one
*
* @param string $messageTemplate
- * @return \Sirius\Validation\Rule\AbstractRule
+ *
+ * @return AbstractRule
*/
public function setMessageTemplate($messageTemplate)
{
@@ -248,9 +157,9 @@ public function setMessageTemplate($messageTemplate)
*
* @return string
*/
- public function getMessageTemplate()
+ public function getMessageTemplate(): string
{
- if ($this->messageTemplate) {
+ if (isset($this->messageTemplate)) {
return $this->messageTemplate;
}
if (isset($this->options['label'])) {
@@ -262,23 +171,15 @@ public function getMessageTemplate()
/**
* Validates a value
- *
- * @param mixed $value
- * @param null|mixed $valueIdentifier
- * @return mixed
*/
- abstract function validate($value, $valueIdentifier = null);
+ abstract public function validate(mixed $value, string $valueIdentifier = null): bool;
/**
- * Sets the error message prototype that will be used when returning the error message
- * when validation fails.
+ * Sets the error message prototype that will be used when
+ * returning the error message if validation fails.
* This option can be used when you need translation
- *
- * @param ErrorMessage $errorMessagePrototype
- * @throws \InvalidArgumentException
- * @return \Sirius\Validation\Rule\AbstractRule
*/
- public function setErrorMessagePrototype(ErrorMessage $errorMessagePrototype)
+ public function setErrorMessagePrototype(ErrorMessage $errorMessagePrototype): self
{
$this->errorMessagePrototype = $errorMessagePrototype;
@@ -291,7 +192,7 @@ public function setErrorMessagePrototype(ErrorMessage $errorMessagePrototype)
*
* @return ErrorMessage
*/
- public function getErrorMessagePrototype()
+ public function getErrorMessagePrototype(): ErrorMessage
{
if (!$this->errorMessagePrototype) {
$this->errorMessagePrototype = new ErrorMessage();
@@ -302,20 +203,16 @@ public function getErrorMessagePrototype()
/**
* Retrieve the error message if validation failed
- *
- * @return NULL|\Sirius\Validation\ErrorMessage
*/
- public function getMessage()
+ public function getMessage(): ?ErrorMessage
{
if ($this->success) {
return null;
}
$message = $this->getPotentialMessage();
- $message->setVariables(
- array(
- 'value' => $this->value
- )
- );
+ $message->setVariables([
+ 'value' => $this->value
+ ]);
return $message;
}
@@ -326,9 +223,9 @@ public function getMessage()
*
* @return ErrorMessage
*/
- public function getPotentialMessage()
+ public function getPotentialMessage(): ErrorMessage
{
- $message = clone ($this->getErrorMessagePrototype());
+ $message = clone $this->getErrorMessagePrototype();
$message->setTemplate($this->getMessageTemplate());
$message->setVariables($this->options);
@@ -339,15 +236,11 @@ public function getPotentialMessage()
* Method for determining the path to a related item.
* Eg: for `lines[5][price]` the related item `lines[*][quantity]`
* has the value identifier as `lines[5][quantity]`
- *
- * @param $valueIdentifier
- * @param $relatedItem
- * @return string|null
*/
- protected function getRelatedValueIdentifier($valueIdentifier, $relatedItem)
+ protected function getRelatedValueIdentifier(string $valueIdentifier, string $relatedItem): string|null
{
// in case we don't have a related path
- if (strpos($relatedItem, '*') === false) {
+ if (!str_contains($relatedItem, '*')) {
return $relatedItem;
}
@@ -361,7 +254,7 @@ protected function getRelatedValueIdentifier($valueIdentifier, $relatedItem)
}
// the result should be ['lines', '5', 'quantity']
- $relatedValueIdentifierParts = array();
+ $relatedValueIdentifierParts = [];
foreach ($relatedItemParts as $index => $part) {
if ($part === '*' && isset($valueIdentifierParts[$index])) {
$relatedValueIdentifierParts[] = $valueIdentifierParts[$index];
@@ -371,9 +264,10 @@ protected function getRelatedValueIdentifier($valueIdentifier, $relatedItem)
}
$relatedValueIdentifier = implode('][', $relatedValueIdentifierParts) . ']';
- $relatedValueIdentifier = str_replace($relatedValueIdentifierParts[0] . ']', $relatedValueIdentifierParts[0],
- $relatedValueIdentifier);
-
- return $relatedValueIdentifier;
+ return str_replace(
+ $relatedValueIdentifierParts[0] . ']',
+ $relatedValueIdentifierParts[0],
+ $relatedValueIdentifier
+ );
}
}
diff --git a/src/Rule/AbstractStringRule.php b/src/Rule/AbstractStringRule.php
new file mode 100644
index 0000000..67fca90
--- /dev/null
+++ b/src/Rule/AbstractStringRule.php
@@ -0,0 +1,19 @@
+options['encoding'] ?? mb_internal_encoding()
+ );
+ }
+
+ return strlen($str);
+ }
+}
diff --git a/src/Rule/Alpha.php b/src/Rule/Alpha.php
index 7445581..76f216c 100755
--- a/src/Rule/Alpha.php
+++ b/src/Rule/Alpha.php
@@ -1,16 +1,17 @@
value = $value;
- $this->success = (bool)ctype_alpha((string)str_replace(' ', '', $value));
+ $this->success = (bool)ctype_alpha((string)str_replace(' ', '', (string)$value));
return $this->success;
}
diff --git a/src/Rule/AlphaNumHyphen.php b/src/Rule/AlphaNumHyphen.php
index 4d94e3f..a9a8423 100755
--- a/src/Rule/AlphaNumHyphen.php
+++ b/src/Rule/AlphaNumHyphen.php
@@ -1,24 +1,25 @@
value = $value;
$this->success = (bool)ctype_alnum(
- (string)str_replace(
- array(
+ str_replace(
+ [
' ',
'_',
'-'
- ),
+ ],
'',
- $value
+ (string) $value
)
);
diff --git a/src/Rule/AlphaNumeric.php b/src/Rule/AlphaNumeric.php
index 925c64b..a8ef000 100755
--- a/src/Rule/AlphaNumeric.php
+++ b/src/Rule/AlphaNumeric.php
@@ -1,14 +1,15 @@
value = $value;
$this->success = (bool)ctype_alnum((string)str_replace(' ', '', $value));
diff --git a/src/Rule/ArrayLength.php b/src/Rule/ArrayLength.php
index 373223d..5934a8f 100755
--- a/src/Rule/ArrayLength.php
+++ b/src/Rule/ArrayLength.php
@@ -1,23 +1,22 @@
self::OPTION_MIN,
1 => self::OPTION_MAX
- );
+ ];
- public function validate($value, $valueIdentifier = null)
+ public function validate(mixed $value, string $valueIdentifier = null): bool
{
$this->value = $value;
$maxValidator = new ArrayMaxLength();
diff --git a/src/Rule/ArrayMaxLength.php b/src/Rule/ArrayMaxLength.php
index 82cb763..d4f7df9 100755
--- a/src/Rule/ArrayMaxLength.php
+++ b/src/Rule/ArrayMaxLength.php
@@ -1,22 +1,21 @@
value = $value;
if (!isset($this->options['max'])) {
diff --git a/src/Rule/ArrayMinLength.php b/src/Rule/ArrayMinLength.php
index 609ab68..efb8495 100755
--- a/src/Rule/ArrayMinLength.php
+++ b/src/Rule/ArrayMinLength.php
@@ -1,21 +1,20 @@
self::OPTION_MIN
- );
+ ];
- public function validate($value, $valueIdentifier = null)
+ public function validate(mixed $value, string $valueIdentifier = null): bool
{
$this->value = $value;
if (!isset($this->options['min'])) {
diff --git a/src/Rule/Between.php b/src/Rule/Between.php
index 285f6ea..fd1b1cc 100755
--- a/src/Rule/Between.php
+++ b/src/Rule/Between.php
@@ -1,23 +1,22 @@
self::OPTION_MIN,
1 => self::OPTION_MAX
- );
+ ];
- public function validate($value, $valueIdentifier = null)
+ public function validate(mixed $value, string $valueIdentifier = null): bool
{
$this->value = $value;
$minValidator = new LessThan();
diff --git a/src/Rule/Callback.php b/src/Rule/Callback.php
index 3ec24e3..7b873f8 100755
--- a/src/Rule/Callback.php
+++ b/src/Rule/Callback.php
@@ -1,9 +1,10 @@
options['callback'])) {
$uniqueId .= '|' . $this->options['callback'];
} elseif (is_array($this->options['callback'])) {
- // the callback is an array that points to a static class method (eg: array('MyClass', 'method'))
+ // the callback is an array that points to a static class method (eg: ['MyClass', 'method'])
if (is_string($this->options['callback'][0])) {
$uniqueId .= '|' . implode('::', $this->options['callback']);
} elseif (is_object($this->options['callback'][0])) {
@@ -39,13 +40,13 @@ public function getUniqueId()
return $uniqueId;
}
- public function validate($value, $valueIdentifier = null)
+ public function validate(mixed $value, string $valueIdentifier = null): bool
{
$this->value = $value;
if (!isset($this->options['callback']) || !is_callable($this->options['callback'])) {
$this->success = true;
} else {
- $args = (isset($this->options['arguments'])) ? (array)$this->options['arguments'] : array();
+ $args = (isset($this->options['arguments'])) ? (array)$this->options['arguments'] : [];
array_unshift($args, $value);
array_push($args, $valueIdentifier, $this->context);
$this->success = (bool)call_user_func_array($this->options['callback'], $args);
diff --git a/src/Rule/Date.php b/src/Rule/Date.php
index 0e4a9f1..303ff48 100644
--- a/src/Rule/Date.php
+++ b/src/Rule/Date.php
@@ -1,37 +1,46 @@
'Y-m-d'
- );
+ ];
- protected $optionsIndexMap = array(
+ protected array $optionsIndexMap = [
0 => self::OPTION_FORMAT
- );
+ ];
- public function validate($value, $valueIdentifier = null)
+ public function validate(mixed $value, string $valueIdentifier = null): bool
{
$this->value = $value;
- $this->success = $value == date($this->options['format'],
- $this->getTimestampFromFormatedString($value, $this->options['format']));
+ $this->success = $value == date(
+ (string) $this->options['format'],
+ $this->getTimestampFromFormatedString($value, $this->options['format'])
+ );
return $this->success;
}
- protected function getTimestampFromFormatedString($string, $format)
+ protected function getTimestampFromFormatedString(mixed $string, mixed $format): ?int
{
$result = date_parse_from_format($format, $string);
- return mktime((int)$result['hour'], (int)$result['minute'], (int)$result['second'], (int)$result['month'],
- (int)$result['day'], (int)$result['year']);
+ return mktime(
+ (int)$result['hour'],
+ (int)$result['minute'],
+ (int)$result['second'],
+ (int)$result['month'],
+ (int)$result['day'],
+ (int)$result['year']
+ ) ?: null;
}
}
diff --git a/src/Rule/DateTime.php b/src/Rule/DateTime.php
index a48e7f7..c6d63f6 100644
--- a/src/Rule/DateTime.php
+++ b/src/Rule/DateTime.php
@@ -1,14 +1,15 @@
'Y-m-d H:i:s'
- );
+ ];
}
diff --git a/src/Rule/Email.php b/src/Rule/Email.php
index be8005f..77d7b43 100755
--- a/src/Rule/Email.php
+++ b/src/Rule/Email.php
@@ -1,14 +1,15 @@
value = $value;
$this->success = (filter_var((string)$value, FILTER_VALIDATE_EMAIL) !== false);
diff --git a/src/Rule/EmailDomain.php b/src/Rule/EmailDomain.php
index 5d3ed6c..a7cf903 100755
--- a/src/Rule/EmailDomain.php
+++ b/src/Rule/EmailDomain.php
@@ -1,18 +1,24 @@
value = $value;
// Check if the email domain has a valid MX record
- $this->success = (bool)checkdnsrr(preg_replace('/^[^@]+@/', '', $value), 'MX');
+ $host = preg_replace('/^[^@]+@/', '', $value);
+ if ($host) {
+ $this->success = (bool)checkdnsrr($host, 'MX');
+ } else {
+ $this->success = false;
+ }
return $this->success;
}
diff --git a/src/Rule/Equal.php b/src/Rule/Equal.php
index d931162..f6adc57 100644
--- a/src/Rule/Equal.php
+++ b/src/Rule/Equal.php
@@ -1,19 +1,20 @@
self::OPTION_VALUE
- );
+ ];
- public function validate($value, $valueIdentifier = null)
+ public function validate(mixed $value, string $valueIdentifier = null): bool
{
$this->value = $value;
if (isset($this->options[self::OPTION_VALUE])) {
diff --git a/src/Rule/File/Extension.php b/src/Rule/File/Extension.php
index dc7e140..69c1c80 100644
--- a/src/Rule/File/Extension.php
+++ b/src/Rule/File/Extension.php
@@ -1,23 +1,24 @@
array()
- );
+ protected array $options = [
+ self::OPTION_ALLOWED_EXTENSIONS => []
+ ];
- public function setOption($name, $value)
+ public function setOption(string $name, mixed $value): static
{
if ($name == self::OPTION_ALLOWED_EXTENSIONS) {
if (is_string($value)) {
@@ -30,7 +31,7 @@ public function setOption($name, $value)
return parent::setOption($name, $value);
}
- public function validate($value, $valueIdentifier = null)
+ public function validate(mixed $value, string $valueIdentifier = null): bool
{
$this->value = $value;
if (!file_exists($value)) {
@@ -46,15 +47,13 @@ public function validate($value, $valueIdentifier = null)
return $this->success;
}
- public function getPotentialMessage()
+ public function getPotentialMessage(): ErrorMessage
{
$message = parent::getPotentialMessage();
$fileExtensions = array_map('strtoupper', $this->options[self::OPTION_ALLOWED_EXTENSIONS]);
- $message->setVariables(
- array(
- 'file_extensions' => implode(', ', $fileExtensions)
- )
- );
+ $message->setVariables([
+ 'file_extensions' => implode(', ', $fileExtensions)
+ ]);
return $message;
}
diff --git a/src/Rule/File/Image.php b/src/Rule/File/Image.php
index 00abe80..0454609 100644
--- a/src/Rule/File/Image.php
+++ b/src/Rule/File/Image.php
@@ -1,33 +1,38 @@
array('jpg', 'png', 'gif')
- );
+ protected array $options = [
+ self::OPTION_ALLOWED_IMAGES => ['jpg', 'png', 'gif']
+ ];
- protected $imageTypesMap = array(
- IMAGETYPE_GIF => 'gif',
- IMAGETYPE_JPEG => 'jpg',
+ /**
+ * @var array
+ */
+ protected array $imageTypesMap = [
+ IMAGETYPE_GIF => 'gif',
+ IMAGETYPE_JPEG => 'jpg',
IMAGETYPE_JPEG2000 => 'jpg',
- IMAGETYPE_PNG => 'png',
- IMAGETYPE_PSD => 'psd',
- IMAGETYPE_BMP => 'bmp',
- IMAGETYPE_ICO => 'ico',
- );
+ IMAGETYPE_PNG => 'png',
+ IMAGETYPE_PSD => 'psd',
+ IMAGETYPE_BMP => 'bmp',
+ IMAGETYPE_ICO => 'ico',
+ IMAGETYPE_WEBP => 'webp',
+ ];
- public function setOption($name, $value)
+ public function setOption(string $name, mixed $value): static
{
if ($name == self::OPTION_ALLOWED_IMAGES) {
if (is_string($value)) {
@@ -40,29 +45,31 @@ public function setOption($name, $value)
return parent::setOption($name, $value);
}
- public function validate($value, $valueIdentifier = null)
+ public function validate(mixed $value, string $valueIdentifier = null): bool
{
$this->value = $value;
if (!file_exists($value)) {
$this->success = false;
} else {
$imageInfo = getimagesize($value);
- $extension = isset($this->imageTypesMap[$imageInfo[2]]) ? $this->imageTypesMap[$imageInfo[2]] : false;
- $this->success = ($extension && in_array($extension, $this->options[self::OPTION_ALLOWED_IMAGES]));
+ if (!is_array($imageInfo)) {
+ $this->success = false;
+ } else {
+ $extension = $this->imageTypesMap[$imageInfo[2]] ?? false;
+ $this->success = ($extension && in_array($extension, $this->options[self::OPTION_ALLOWED_IMAGES]));
+ }
}
return $this->success;
}
- public function getPotentialMessage()
+ public function getPotentialMessage(): ErrorMessage
{
$message = parent::getPotentialMessage();
$imageTypes = array_map('strtoupper', $this->options[self::OPTION_ALLOWED_IMAGES]);
- $message->setVariables(
- array(
- 'image_types' => implode(', ', $imageTypes)
- )
- );
+ $message->setVariables([
+ 'image_types' => implode(', ', $imageTypes)
+ ]);
return $message;
}
diff --git a/src/Rule/File/ImageHeight.php b/src/Rule/File/ImageHeight.php
index 610a5e7..1675bfc 100644
--- a/src/Rule/File/ImageHeight.php
+++ b/src/Rule/File/ImageHeight.php
@@ -1,4 +1,6 @@
1000000,
self::OPTION_MIN => 0,
- );
+ ];
- public function validate($value, $valueIdentifier = null)
+ public function validate(mixed $value, string $valueIdentifier = null): bool
{
$this->value = $value;
if (!file_exists($value)) {
@@ -25,7 +27,9 @@ public function validate($value, $valueIdentifier = null)
} else {
$imageInfo = getimagesize($value);
$height = isset($imageInfo[1]) ? $imageInfo[1] : 0;
- $this->success = $height && $height <= $this->options[self::OPTION_MAX] && $height >= $this->options[self::OPTION_MIN];
+ $this->success = $height &&
+ $height <= $this->options[self::OPTION_MAX] &&
+ $height >= $this->options[self::OPTION_MIN];
}
return $this->success;
diff --git a/src/Rule/File/ImageRatio.php b/src/Rule/File/ImageRatio.php
index dd89169..706b865 100644
--- a/src/Rule/File/ImageRatio.php
+++ b/src/Rule/File/ImageRatio.php
@@ -1,7 +1,10 @@
0,
+ protected array $options = [
+ self::OPTION_RATIO => 0,
self::OPTION_ERROR_MARGIN => 0,
- );
+ ];
- protected function normalizeRatio($ratio)
+ protected function normalizeRatio(mixed $ratio): float
{
if (is_numeric($ratio) || $ratio == filter_var($ratio, FILTER_SANITIZE_NUMBER_FLOAT)) {
return floatval($ratio);
@@ -28,24 +31,30 @@ protected function normalizeRatio($ratio)
if (strpos($ratio, ':') !== false) {
list($width, $height) = explode(':', $ratio);
- return $width / $height;
+ return (float) $width / (float) $height;
}
return 0;
}
- public function validate($value, $valueIdentifier = null)
+ public function validate(mixed $value, string $valueIdentifier = null): bool
{
$this->value = $value;
- $ratio = $this->normalizeRatio($this->options[self::OPTION_RATIO]);
+ $ratio = RuleHelper::normalizeImageRatio($this->options[self::OPTION_RATIO]);
if (!file_exists($value)) {
$this->success = false;
} elseif ($ratio == 0) {
$this->success = true;
} else {
$imageInfo = getimagesize($value);
- $actualRatio = $imageInfo[0] / $imageInfo[1];
- $this->success = abs($actualRatio - $ratio) <= $this->options[self::OPTION_ERROR_MARGIN];
+
+ if (is_array($imageInfo)) {
+ $actualRatio = $imageInfo[0] / $imageInfo[1];
+ $this->success = abs($actualRatio - $ratio) <= $this->options[self::OPTION_ERROR_MARGIN];
+ } else {
+ // no image size computed => no valid image
+ return $this->success = false;
+ }
}
return $this->success;
diff --git a/src/Rule/File/ImageWidth.php b/src/Rule/File/ImageWidth.php
index dadb32a..b44b592 100644
--- a/src/Rule/File/ImageWidth.php
+++ b/src/Rule/File/ImageWidth.php
@@ -1,4 +1,6 @@
1000000,
self::OPTION_MIN => 0,
- );
+ ];
- public function validate($value, $valueIdentifier = null)
+ public function validate(mixed $value, string $valueIdentifier = null): bool
{
$this->value = $value;
if (!file_exists($value)) {
@@ -25,7 +27,9 @@ public function validate($value, $valueIdentifier = null)
} else {
$imageInfo = getimagesize($value);
$width = isset($imageInfo[0]) ? $imageInfo[0] : 0;
- $this->success = $width && $width <= $this->options[self::OPTION_MAX] && $width >= $this->options[self::OPTION_MIN];
+ $this->success = $width &&
+ $width <= $this->options[self::OPTION_MAX] &&
+ $width >= $this->options[self::OPTION_MIN];
}
return $this->success;
diff --git a/src/Rule/File/Size.php b/src/Rule/File/Size.php
index b61ed0d..f53bd83 100644
--- a/src/Rule/File/Size.php
+++ b/src/Rule/File/Size.php
@@ -1,7 +1,10 @@
'2M'
- );
-
- protected function normalizeSize($size)
- {
- $units = array('B' => 0, 'K' => 1, 'M' => 2, 'G' => 3);
- $unit = strtoupper(substr($size, strlen($size) - 1, 1));
- if (!isset($units[$unit])) {
- $normalizedSize = filter_var($size, FILTER_SANITIZE_NUMBER_INT);
- } else {
- $size = filter_var(substr($size, 0, strlen($size) - 1), FILTER_SANITIZE_NUMBER_FLOAT);
- $normalizedSize = $size * pow(1024, $units[$unit]);
- }
-
- return $normalizedSize;
- }
+ ];
- public function validate($value, $valueIdentifier = null)
+ public function validate(mixed $value, string $valueIdentifier = null): bool
{
$this->value = $value;
if (!file_exists($value)) {
$this->success = false;
} else {
$fileSize = @filesize($value);
- $limit = $this->normalizeSize($this->options[self::OPTION_SIZE]);
+ $limit = RuleHelper::normalizeFileSize($this->options[self::OPTION_SIZE]);
$this->success = $fileSize && $fileSize <= $limit;
}
diff --git a/src/Rule/FullName.php b/src/Rule/FullName.php
index 95d0b1b..b93905d 100755
--- a/src/Rule/FullName.php
+++ b/src/Rule/FullName.php
@@ -1,16 +1,17 @@
value = $value;
diff --git a/src/Rule/GreaterThan.php b/src/Rule/GreaterThan.php
index b57c5de..62b77ab 100755
--- a/src/Rule/GreaterThan.php
+++ b/src/Rule/GreaterThan.php
@@ -1,25 +1,26 @@
true
- );
+ ];
- protected $optionsIndexMap = array(
+ protected array $optionsIndexMap = [
0 => self::OPTION_MIN,
1 => self::OPTION_INCLUSIVE
- );
+ ];
- public function validate($value, $valueIdentifier = null)
+ public function validate(mixed $value, string $valueIdentifier = null): bool
{
$this->value = $value;
if (!isset($this->options['min'])) {
diff --git a/src/Rule/InList.php b/src/Rule/InList.php
index a25940c..6fe8772 100755
--- a/src/Rule/InList.php
+++ b/src/Rule/InList.php
@@ -1,20 +1,20 @@
self::OPTION_LIST
- );
+ ];
- public function validate($value, $valueIdentifier = null)
+ public function validate(mixed $value, string $valueIdentifier = null): bool
{
$this->value = $value;
if (!isset($this->options['list'])) {
diff --git a/src/Rule/Integer.php b/src/Rule/Integer.php
index 8c99723..58dc2b5 100644
--- a/src/Rule/Integer.php
+++ b/src/Rule/Integer.php
@@ -1,16 +1,17 @@
value = $value;
- $this->success = (bool)filter_var($value, FILTER_VALIDATE_INT) || (string)$value === '0';
+ $this->success = (bool)filter_var($value, FILTER_VALIDATE_INT) || $value === '0';
return $this->success;
}
diff --git a/src/Rule/IpAddress.php b/src/Rule/IpAddress.php
index d477d42..648dea6 100755
--- a/src/Rule/IpAddress.php
+++ b/src/Rule/IpAddress.php
@@ -1,21 +1,22 @@
value = $value;
// Do not allow private and reserved range IPs
$flags = FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE;
if (strpos($value, ':') !== false) {
- $this->success = (bool)filter_var($value, FILTER_VALIDATE_IP, $flags | FILTER_FLAG_IPV6);
+ $this->success = (bool)filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE | FILTER_FLAG_IPV6);
} else {
- $this->success = (bool)filter_var($value, FILTER_VALIDATE_IP, $flags | FILTER_FLAG_IPV4);
+ $this->success = (bool)filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE | FILTER_FLAG_IPV4);
}
return $this->success;
diff --git a/src/Rule/Length.php b/src/Rule/Length.php
index 60f919e..b963f9c 100755
--- a/src/Rule/Length.php
+++ b/src/Rule/Length.php
@@ -1,30 +1,31 @@
self::OPTION_MIN,
- 1 => self::OPTION_MAX
- );
+ 1 => self::OPTION_MAX,
+ 2 => self::OPTION_ENCODING
+ ];
- public function validate($value, $valueIdentifier = null)
+ public function validate(mixed $value, string $valueIdentifier = null): bool
{
$this->value = $value;
- $maxValidator = new MinLength();
+ $maxValidator = new MaxLength();
if (isset($this->options['max'])) {
$maxValidator->setOption('max', $this->options['max']);
}
- $minValidator = new MaxLength();
+ $minValidator = new MinLength();
if (isset($this->options['min'])) {
$minValidator->setOption('min', $this->options['min']);
}
diff --git a/src/Rule/LessThan.php b/src/Rule/LessThan.php
index 5d2c149..08d14aa 100755
--- a/src/Rule/LessThan.php
+++ b/src/Rule/LessThan.php
@@ -1,25 +1,26 @@
true
- );
+ ];
- protected $optionsIndexMap = array(
+ protected array $optionsIndexMap = [
0 => self::OPTION_MAX,
1 => self::OPTION_INCLUSIVE
- );
+ ];
- public function validate($value, $valueIdentifier = null)
+ public function validate(mixed $value, string $valueIdentifier = null): bool
{
$this->value = $value;
if (!isset($this->options['max'])) {
diff --git a/src/Rule/Match.php b/src/Rule/Matching.php
similarity index 57%
rename from src/Rule/Match.php
rename to src/Rule/Matching.php
index 3360efe..4df3900 100644
--- a/src/Rule/Match.php
+++ b/src/Rule/Matching.php
@@ -1,23 +1,24 @@
self::OPTION_ITEM
- );
+ ];
- public function validate($value, $valueIdentifier = null)
+ public function validate(mixed $value, string $valueIdentifier = null): bool
{
$this->value = $value;
if (isset($this->options[self::OPTION_ITEM])) {
- $this->success = ($value == $this->context->getItemValue($this->options[self::OPTION_ITEM]));
+ $this->success = $this->context && ($value == $this->context->getItemValue($this->options[self::OPTION_ITEM]));
} else {
$this->success = true;
}
diff --git a/src/Rule/MaxLength.php b/src/Rule/MaxLength.php
index 7a60d2d..90ecbc6 100755
--- a/src/Rule/MaxLength.php
+++ b/src/Rule/MaxLength.php
@@ -1,27 +1,28 @@
self::OPTION_MAX
- );
+ protected array $optionsIndexMap = [
+ 0 => self::OPTION_MAX,
+ 1 => self::OPTION_ENCODING
+ ];
- public function validate($value, $valueIdentifier = null)
+ public function validate(mixed $value, string $valueIdentifier = null): bool
{
$this->value = $value;
if (!isset($this->options['max'])) {
$this->success = true;
} else {
- $this->success = strlen($value) <= $this->options['max'];
+ $this->success = $this->getStringLength($value) <= $this->options['max'];
}
return $this->success;
diff --git a/src/Rule/MinLength.php b/src/Rule/MinLength.php
index 2c95f8a..9c58134 100755
--- a/src/Rule/MinLength.php
+++ b/src/Rule/MinLength.php
@@ -1,27 +1,28 @@
self::OPTION_MIN
- );
+ protected array $optionsIndexMap = [
+ 0 => self::OPTION_MIN,
+ 1 => self::OPTION_ENCODING
+ ];
- public function validate($value, $valueIdentifier = null)
+ public function validate(mixed $value, string $valueIdentifier = null): bool
{
$this->value = $value;
if (!isset($this->options['min'])) {
$this->success = true;
} else {
- $this->success = strlen($value) >= $this->options['min'];
+ $this->success = $this->getStringLength($value) >= $this->options['min'];
}
return $this->success;
diff --git a/src/Rule/NotEqual.php b/src/Rule/NotEqual.php
new file mode 100644
index 0000000..436898e
--- /dev/null
+++ b/src/Rule/NotEqual.php
@@ -0,0 +1,18 @@
+success = !$this->success;
+
+ return $this->success;
+ }
+}
diff --git a/src/Rule/NotInList.php b/src/Rule/NotInList.php
index b1bf8d9..165b5c1 100755
--- a/src/Rule/NotInList.php
+++ b/src/Rule/NotInList.php
@@ -1,19 +1,20 @@
self::OPTION_LIST
- );
+ ];
- public function validate($value, $valueIdentifier = null)
+ public function validate(mixed $value, string $valueIdentifier = null): bool
{
$this->value = $value;
if (!isset($this->options['list'])) {
diff --git a/src/Rule/NotMatch.php b/src/Rule/NotMatch.php
new file mode 100644
index 0000000..207ef71
--- /dev/null
+++ b/src/Rule/NotMatch.php
@@ -0,0 +1,18 @@
+success = !$this->success;
+
+ return $this->success;
+ }
+}
diff --git a/src/Rule/NotRegex.php b/src/Rule/NotRegex.php
index 25c2a42..6197e65 100755
--- a/src/Rule/NotRegex.php
+++ b/src/Rule/NotRegex.php
@@ -1,13 +1,14 @@
success = !$this->success;
diff --git a/src/Rule/Number.php b/src/Rule/Number.php
index e6029b0..04b7dcf 100644
--- a/src/Rule/Number.php
+++ b/src/Rule/Number.php
@@ -1,13 +1,14 @@
value = $value;
$this->success = (bool)filter_var($value, FILTER_VALIDATE_FLOAT) || (string)$value === '0';
diff --git a/src/Rule/Regex.php b/src/Rule/Regex.php
index 0333b35..eb4d9c9 100755
--- a/src/Rule/Regex.php
+++ b/src/Rule/Regex.php
@@ -1,19 +1,20 @@
self::OPTION_PATTERN
- );
+ ];
- public function validate($value, $valueIdentifier = null)
+ public function validate(mixed $value, string $valueIdentifier = null): bool
{
$this->value = $value;
if (isset($this->options['pattern'])) {
diff --git a/src/Rule/Required.php b/src/Rule/Required.php
index f8c1679..e84f07e 100755
--- a/src/Rule/Required.php
+++ b/src/Rule/Required.php
@@ -1,13 +1,14 @@
value = $value;
$this->success = ($value !== null && $value !== '');
diff --git a/src/Rule/RequiredWhen.php b/src/Rule/RequiredWhen.php
index b806ec7..58a8c93 100644
--- a/src/Rule/RequiredWhen.php
+++ b/src/Rule/RequiredWhen.php
@@ -1,4 +1,6 @@
options[self::OPTION_RULE_OPTIONS])) ? (array)$this->options[self::OPTION_RULE_OPTIONS] : array();
+ $ruleOptions = (isset($this->options[self::OPTION_RULE_OPTIONS])) ?
+ (array)$this->options[self::OPTION_RULE_OPTIONS] :
+ [];
if (is_string($this->options[self::OPTION_RULE])) {
$ruleClass = $this->options[self::OPTION_RULE];
@@ -34,26 +37,25 @@ public function getItemRule()
'Validator for the other item is not valid or cannot be constructed based on the data provided'
);
}
- $context = $this->context ? $this->context : array();
- $rule->setContext($context);
+ /* @var $rule AbstractRule */
+ $rule->setContext($this->context ?? []); // @phpstan-ignore-line
- return $rule;
+ return $rule; // @phpstan-ignore-line
}
- public function validate($value, $valueIdentifier = null)
+ public function validate(mixed $value, string $valueIdentifier = null): bool
{
$this->value = $value;
if (!isset($this->options[self::OPTION_ITEM])) {
$this->success = true;
} else {
-
- $relatedItemPath = $this->getRelatedValueIdentifier($valueIdentifier, $this->options[self::OPTION_ITEM]);
- $relatedItemValue = $relatedItemPath !== null ? $this->context->getItemValue($relatedItemPath) : null;
+ $relatedItemPath = $this->getRelatedValueIdentifier((string)$valueIdentifier, $this->options[self::OPTION_ITEM]);
+ $relatedItemValue = $this->context && $relatedItemPath !== null ? $this->context->getItemValue($relatedItemPath) : null;
$itemRule = $this->getItemRule();
- if ($itemRule->validate($relatedItemValue, $relatedItemPath)) {
- $this->success = ($value !== null || trim($value) !== '');
+ if ($itemRule && $itemRule->validate($relatedItemValue, $relatedItemPath)) {
+ $this->success = ($value !== null && (!is_string($value) || trim($value) !== ''));
} else {
$this->success = true;
}
diff --git a/src/Rule/RequiredWith.php b/src/Rule/RequiredWith.php
index 18d82d1..bb5cd27 100644
--- a/src/Rule/RequiredWith.php
+++ b/src/Rule/RequiredWith.php
@@ -1,4 +1,6 @@
self::OPTION_ITEM
- );
+ ];
- public function validate($value, $valueIdentifier = null)
+ public function validate(mixed $value, string $valueIdentifier = null): bool
{
$this->value = $value;
- $relatedItemPath = $this->getRelatedValueIdentifier($valueIdentifier, $this->options[self::OPTION_ITEM]);
- $relatedItemValue = $relatedItemPath !== null ? $this->context->getItemValue($relatedItemPath) : null;
+ $relatedItemPath = $this->getRelatedValueIdentifier((string) $valueIdentifier, $this->options[self::OPTION_ITEM]);
+ $relatedItemValue = $this->context && $relatedItemPath !== null ? $this->context->getItemValue($relatedItemPath) : null;
if (isset($this->options[self::OPTION_ITEM]) && $relatedItemValue !== null) {
- $this->success = ($value !== null || trim($value) !== '');
+ $this->success = ($value !== null && (!is_string($value) || trim($value) !== ''));
} else {
$this->success = true;
}
diff --git a/src/Rule/RequiredWithout.php b/src/Rule/RequiredWithout.php
index 2832e72..384e0b6 100644
--- a/src/Rule/RequiredWithout.php
+++ b/src/Rule/RequiredWithout.php
@@ -1,4 +1,6 @@
self::OPTION_ITEM
- );
+ ];
- public function validate($value, $valueIdentifier = null)
+ public function validate(mixed $value, string $valueIdentifier = null): bool
{
$this->value = $value;
- $relatedItemPath = $this->getRelatedValueIdentifier($valueIdentifier, $this->options[self::OPTION_ITEM]);
- $relatedItemValue = $relatedItemPath !== null ? $this->context->getItemValue($relatedItemPath) : null;
+ $relatedItemPath = $this->getRelatedValueIdentifier((string) $valueIdentifier, $this->options[self::OPTION_ITEM]);
+ $relatedItemValue = $this->context && $relatedItemPath !== null ? $this->context->getItemValue($relatedItemPath) : null;
if (isset($this->options[self::OPTION_ITEM]) && $relatedItemValue === null) {
- $this->success = ($value !== null || trim($value) !== '');
+ $this->success = ($value !== null && (!is_string($value) || trim($value) !== ''));
} else {
$this->success = true;
}
diff --git a/src/Rule/Time.php b/src/Rule/Time.php
index de8ad09..0439f3c 100644
--- a/src/Rule/Time.php
+++ b/src/Rule/Time.php
@@ -1,15 +1,14 @@
'H:i:s'
- );
-
+ ];
}
diff --git a/src/Rule/Upload/Extension.php b/src/Rule/Upload/Extension.php
index 5809c1d..34b99ce 100644
--- a/src/Rule/Upload/Extension.php
+++ b/src/Rule/Upload/Extension.php
@@ -1,23 +1,24 @@
array()
- );
+ protected array $options = [
+ self::OPTION_ALLOWED_EXTENSIONS => []
+ ];
- public function setOption($name, $value)
+ public function setOption(string $name, mixed $value): static
{
if ($name == self::OPTION_ALLOWED_EXTENSIONS) {
if (is_string($value)) {
@@ -30,11 +31,13 @@ public function setOption($name, $value)
return parent::setOption($name, $value);
}
- public function validate($value, $valueIdentifier = null)
+ public function validate(mixed $value, string $valueIdentifier = null): bool
{
$this->value = $value;
- if (!is_array($value) || !isset($value['tmp_name']) || !file_exists($value['tmp_name'])) {
+ if (!is_array($value) || !isset($value['tmp_name'])) {
$this->success = false;
+ } elseif (!file_exists($value['tmp_name'])) {
+ $this->success = $value['error'] === UPLOAD_ERR_NO_FILE;
} else {
$extension = strtolower(substr($value['name'], strrpos($value['name'], '.') + 1, 10));
$this->success = is_array($this->options[self::OPTION_ALLOWED_EXTENSIONS]) && in_array(
@@ -46,15 +49,13 @@ public function validate($value, $valueIdentifier = null)
return $this->success;
}
- public function getPotentialMessage()
+ public function getPotentialMessage(): ErrorMessage
{
$message = parent::getPotentialMessage();
$fileExtensions = array_map('strtoupper', $this->options[self::OPTION_ALLOWED_EXTENSIONS]);
- $message->setVariables(
- array(
- 'file_extensions' => implode(', ', $fileExtensions)
- )
- );
+ $message->setVariables([
+ 'file_extensions' => implode(', ', $fileExtensions)
+ ]);
return $message;
}
diff --git a/src/Rule/Upload/Image.php b/src/Rule/Upload/Image.php
index f68947b..99ae24c 100644
--- a/src/Rule/Upload/Image.php
+++ b/src/Rule/Upload/Image.php
@@ -1,33 +1,38 @@
array('jpg', 'png', 'gif')
- );
+ protected array $options = [
+ self::OPTION_ALLOWED_IMAGES => ['jpg', 'png', 'gif']
+ ];
- protected $imageTypesMap = array(
- IMAGETYPE_GIF => 'gif',
- IMAGETYPE_JPEG => 'jpg',
+ /**
+ * @var array
+ */
+ protected $imageTypesMap = [
+ IMAGETYPE_GIF => 'gif',
+ IMAGETYPE_JPEG => 'jpg',
IMAGETYPE_JPEG2000 => 'jpg',
- IMAGETYPE_PNG => 'png',
- IMAGETYPE_PSD => 'psd',
- IMAGETYPE_BMP => 'bmp',
- IMAGETYPE_ICO => 'ico',
- );
+ IMAGETYPE_PNG => 'png',
+ IMAGETYPE_PSD => 'psd',
+ IMAGETYPE_BMP => 'bmp',
+ IMAGETYPE_ICO => 'ico',
+ IMAGETYPE_WEBP => 'webp',
+ ];
- public function setOption($name, $value)
+ public function setOption(string $name, mixed $value): static
{
if ($name == self::OPTION_ALLOWED_IMAGES) {
if (is_string($value)) {
@@ -40,29 +45,33 @@ public function setOption($name, $value)
return parent::setOption($name, $value);
}
- public function validate($value, $valueIdentifier = null)
+ public function validate(mixed $value, string $valueIdentifier = null): bool
{
$this->value = $value;
- if (!is_array($value) || !isset($value['tmp_name']) || !file_exists($value['tmp_name'])) {
+ if (!is_array($value) || !isset($value['tmp_name'])) {
$this->success = false;
+ } elseif (!file_exists($value['tmp_name'])) {
+ $this->success = $value['error'] === UPLOAD_ERR_NO_FILE;
} else {
$imageInfo = getimagesize($value['tmp_name']);
- $extension = isset($this->imageTypesMap[$imageInfo[2]]) ? $this->imageTypesMap[$imageInfo[2]] : false;
- $this->success = ($extension && in_array($extension, $this->options[self::OPTION_ALLOWED_IMAGES]));
+ if (!is_array($imageInfo)) {
+ $this->success = false;
+ } else {
+ $extension = $this->imageTypesMap[$imageInfo[2]] ?? false;
+ $this->success = ($extension && in_array($extension, $this->options[self::OPTION_ALLOWED_IMAGES]));
+ }
}
return $this->success;
}
- public function getPotentialMessage()
+ public function getPotentialMessage(): ErrorMessage
{
$message = parent::getPotentialMessage();
$imageTypes = array_map('strtoupper', $this->options[self::OPTION_ALLOWED_IMAGES]);
- $message->setVariables(
- array(
- 'image_types' => implode(', ', $imageTypes)
- )
- );
+ $message->setVariables([
+ 'image_types' => implode(', ', $imageTypes)
+ ]);
return $message;
}
diff --git a/src/Rule/Upload/ImageHeight.php b/src/Rule/Upload/ImageHeight.php
index e933ecd..ba28835 100644
--- a/src/Rule/Upload/ImageHeight.php
+++ b/src/Rule/Upload/ImageHeight.php
@@ -1,4 +1,6 @@
1000000,
self::OPTION_MIN => 0,
- );
+ ];
- public function validate($value, $valueIdentifier = null)
+ public function validate(mixed $value, string $valueIdentifier = null): bool
{
$this->value = $value;
- if (!is_array($value) || !isset($value['tmp_name']) || !file_exists($value['tmp_name'])) {
+ if (!is_array($value) || !isset($value['tmp_name'])) {
$this->success = false;
+ } elseif (!file_exists($value['tmp_name'])) {
+ $this->success = $value['error'] === UPLOAD_ERR_NO_FILE;
} else {
$imageInfo = getimagesize($value['tmp_name']);
$height = isset($imageInfo[1]) ? $imageInfo[1] : 0;
- $this->success = $height && $height <= $this->options[self::OPTION_MAX] && $height >= $this->options[self::OPTION_MIN];
+ $this->success = $height &&
+ $height <= $this->options[self::OPTION_MAX] &&
+ $height >= $this->options[self::OPTION_MIN];
}
return $this->success;
diff --git a/src/Rule/Upload/ImageRatio.php b/src/Rule/Upload/ImageRatio.php
index 2fd1b0b..865c260 100644
--- a/src/Rule/Upload/ImageRatio.php
+++ b/src/Rule/Upload/ImageRatio.php
@@ -1,7 +1,10 @@
0,
+ protected array $options = [
+ self::OPTION_RATIO => 0,
self::OPTION_ERROR_MARGIN => 0,
- );
+ ];
- protected function normalizeRatio($ratio)
- {
- if (is_numeric($ratio) || $ratio == filter_var($ratio, FILTER_SANITIZE_NUMBER_FLOAT)) {
- return floatval($ratio);
- }
- if (strpos($ratio, ':') !== false) {
- list($width, $height) = explode(':', $ratio);
-
- return $width / $height;
- }
-
- return 0;
- }
-
- public function validate($value, $valueIdentifier = null)
+ public function validate(mixed $value, string $valueIdentifier = null): bool
{
$this->value = $value;
- $ratio = $this->normalizeRatio($this->options[self::OPTION_RATIO]);
- if (!is_array($value) || !isset($value['tmp_name']) || !file_exists($value['tmp_name'])) {
+ $ratio = RuleHelper::normalizeImageRatio($this->options[self::OPTION_RATIO]);
+ if (!is_array($value) || !isset($value['tmp_name'])) {
$this->success = false;
+ } elseif (!file_exists($value['tmp_name'])) {
+ $this->success = $value['error'] === UPLOAD_ERR_NO_FILE;
} elseif ($ratio == 0) {
$this->success = true;
} else {
$imageInfo = getimagesize($value['tmp_name']);
- $actualRatio = $imageInfo[0] / $imageInfo[1];
- $this->success = abs($actualRatio - $ratio) <= $this->options[self::OPTION_ERROR_MARGIN];
+
+ if (is_array($imageInfo)) {
+ $actualRatio = $imageInfo[0] / $imageInfo[1];
+ $this->success = abs($actualRatio - $ratio) <= $this->options[self::OPTION_ERROR_MARGIN];
+ } else {
+ // no image size computed => no valid image
+ return $this->success = false;
+ }
}
return $this->success;
diff --git a/src/Rule/Upload/ImageWidth.php b/src/Rule/Upload/ImageWidth.php
index 03439b0..753d495 100644
--- a/src/Rule/Upload/ImageWidth.php
+++ b/src/Rule/Upload/ImageWidth.php
@@ -1,4 +1,6 @@
1000000,
self::OPTION_MIN => 0,
- );
+ ];
- public function validate($value, $valueIdentifier = null)
+ public function validate(mixed $value, string $valueIdentifier = null): bool
{
$this->value = $value;
- if (!is_array($value) || !isset($value['tmp_name']) || !file_exists($value['tmp_name'])) {
+ if (!is_array($value) || !isset($value['tmp_name'])) {
$this->success = false;
+ } elseif (!file_exists($value['tmp_name'])) {
+ $this->success = $value['error'] === UPLOAD_ERR_NO_FILE;
} else {
$imageInfo = getimagesize($value['tmp_name']);
$width = isset($imageInfo[0]) ? $imageInfo[0] : 0;
- $this->success = $width && $width <= $this->options[self::OPTION_MAX] && $width >= $this->options[self::OPTION_MIN];
+ $this->success = $width &&
+ $width <= $this->options[self::OPTION_MAX] &&
+ $width >= $this->options[self::OPTION_MIN];
}
return $this->success;
diff --git a/src/Rule/Upload/Required.php b/src/Rule/Upload/Required.php
new file mode 100644
index 0000000..253b820
--- /dev/null
+++ b/src/Rule/Upload/Required.php
@@ -0,0 +1,32 @@
+value = $value;
+ if (!is_array($value) || !isset($value['tmp_name']) ||
+ !file_exists($value['tmp_name']) || $value['error'] !== UPLOAD_ERR_OK) {
+ $this->success = false;
+ } else {
+ $this->success = true;
+ }
+
+ return $this->success;
+ }
+}
diff --git a/src/Rule/Upload/Size.php b/src/Rule/Upload/Size.php
index 9b49182..b9fc0a6 100644
--- a/src/Rule/Upload/Size.php
+++ b/src/Rule/Upload/Size.php
@@ -1,7 +1,10 @@
'2M'
- );
-
- protected function normalizeSize($size)
- {
- $units = array('B' => 0, 'K' => 1, 'M' => 2, 'G' => 3);
- $unit = strtoupper(substr($size, strlen($size) - 1, 1));
- if (!isset($units[$unit])) {
- $normalizedSize = filter_var($size, FILTER_SANITIZE_NUMBER_INT);
- } else {
- $size = filter_var(substr($size, 0, strlen($size) - 1), FILTER_SANITIZE_NUMBER_FLOAT);
- $normalizedSize = $size * pow(1024, $units[$unit]);
- }
-
- return $normalizedSize;
- }
+ ];
- public function validate($value, $valueIdentifier = null)
+ public function validate(mixed $value, string $valueIdentifier = null): bool
{
$this->value = $value;
- if (!is_array($value) || !isset($value['tmp_name']) || !file_exists($value['tmp_name'])) {
+ if (!is_array($value) || !isset($value['tmp_name'])) {
$this->success = false;
+ } elseif (!file_exists($value['tmp_name'])) {
+ $this->success = $value['error'] === UPLOAD_ERR_NO_FILE;
} else {
$fileSize = @filesize($value['tmp_name']);
- $limit = $this->normalizeSize($this->options[self::OPTION_SIZE]);
+ $limit = RuleHelper::normalizeFileSize($this->options[self::OPTION_SIZE]);
$this->success = $fileSize && $fileSize <= $limit;
}
diff --git a/src/Rule/Url.php b/src/Rule/Url.php
index 6179de7..ce9bd8f 100755
--- a/src/Rule/Url.php
+++ b/src/Rule/Url.php
@@ -1,16 +1,17 @@
value = $value;
- $this->success = (bool)filter_var($value, FILTER_VALIDATE_URL, FILTER_FLAG_HOST_REQUIRED);
+ $this->success = (bool)filter_var($value, FILTER_VALIDATE_URL);
return $this->success;
}
diff --git a/src/Rule/Website.php b/src/Rule/Website.php
index e15210d..591ac86 100755
--- a/src/Rule/Website.php
+++ b/src/Rule/Website.php
@@ -1,22 +1,22 @@
value = $value;
$this->success = (substr($value, 0, 2) == '//')
|| (preg_match(static::WEBSITE_REGEX, $value) && filter_var(
$value,
- FILTER_VALIDATE_URL,
- FILTER_FLAG_HOST_REQUIRED
+ FILTER_VALIDATE_URL
));
return $this->success;
diff --git a/src/RuleCollection.php b/src/RuleCollection.php
index 42dfd53..a7109ec 100644
--- a/src/RuleCollection.php
+++ b/src/RuleCollection.php
@@ -1,18 +1,23 @@
contains($rule)) {
return;
}
if ($rule instanceof Rule\Required) {
- $rules = array();
+ $rules = [];
foreach ($this as $r) {
$rules[] = $r;
$this->detach($r);
@@ -25,13 +30,13 @@ public function attach($rule, $data = null)
return;
}
- return parent::attach($rule);
+ parent::attach($rule);
}
- public function getHash($rule)
+ #[ReturnTypeWillChange]
+ public function getHash($rule): string
{
- /* @var $rule Rule\AbstractValidator */
+ /** @var AbstractRule $rule */
return $rule->getUniqueId();
}
-
}
diff --git a/src/RuleFactory.php b/src/RuleFactory.php
index 262a2c6..2cb5360 100644
--- a/src/RuleFactory.php
+++ b/src/RuleFactory.php
@@ -1,8 +1,11 @@
*/
- protected $validatorsMap = array();
+ protected array $validatorsMap = [];
- protected $errorMessages = array();
+ /**
+ * @var array
+ */
+ protected array $errorMessages = [];
- protected $labeledErrorMessages = array();
+ /**
+ * @var array
+ */
+ protected array $labeledErrorMessages = [];
- function __construct()
+ /**
+ * Constructor
+ */
+ public function __construct()
{
$this->registerDefaultRules();
}
- protected function registerDefaultRules()
+ /**
+ * Set up the default rules that come with the library
+ */
+ protected function registerDefaultRules(): void
{
- $rulesClasses = array(
+ $rulesClasses = [
'Alpha',
'AlphaNumeric',
'AlphaNumHyphen',
@@ -47,10 +62,11 @@ protected function registerDefaultRules()
'IpAddress',
'Length',
'LessThan',
- 'Match',
'MaxLength',
'MinLength',
+ 'NotEqual',
'NotInList',
+ 'NotMatch',
'NotRegex',
'Number',
'Regex',
@@ -67,13 +83,14 @@ protected function registerDefaultRules()
'File\ImageRatio',
'File\ImageWidth',
'File\Size',
+ 'Upload\Required',
'Upload\Extension',
'Upload\Image',
'Upload\ImageHeight',
'Upload\ImageRatio',
'Upload\ImageWidth',
'Upload\Size',
- );
+ ];
foreach ($rulesClasses as $class) {
$fullClassName = '\\' . __NAMESPACE__ . '\Rule\\' . $class;
$name = strtolower(str_replace('\\', '', $class));
@@ -81,6 +98,7 @@ protected function registerDefaultRules()
$labeledErrorMessage = constant($fullClassName . '::LABELED_MESSAGE');
$this->register($name, $fullClassName, $errorMessage, $labeledErrorMessage);
}
+ $this->register('match', Matching::class, Matching::MESSAGE, Matching::LABELED_MESSAGE);
}
@@ -88,10 +106,11 @@ protected function registerDefaultRules()
* Register a class to be used when creating validation rules
*
* @param string $name
- * @param string $class
- * @return \Sirius\Validation\RuleFactory
+ * @param string|class-string $class
+ *
+ * @return $this
*/
- public function register($name, $class, $errorMessage = '', $labeledErrorMessage = '')
+ public function register(string $name, string $class, string $errorMessage = '', string $labeledErrorMessage = ''): self
{
if (is_subclass_of($class, '\Sirius\Validation\Rule\AbstractRule')) {
$this->validatorsMap[$name] = $class;
@@ -109,18 +128,15 @@ public function register($name, $class, $errorMessage = '', $labeledErrorMessage
/**
* Factory method to construct a validator based on options that are used most of the times
*
- * @param string|callable $name
+ * @param string|callable|mixed $name
* name of a validator class or a callable object/function
- * @param string|array $options
+ * @param string|array|null $options
* validator options (an array, JSON string or QUERY string)
- * @param string $messageTemplate
- * error message template
- * @param string $label
- * label of the form input field or model attribute
+ *
+ * @return AbstractRule
* @throws \InvalidArgumentException
- * @return \Sirius\Validation\Rule\AbstractValidator
*/
- public function createRule($name, $options = null, $messageTemplate = null, $label = null)
+ public function createRule(mixed $name, mixed $options = null, string $messageTemplate = null, string $label = null): AbstractRule
{
$validator = $this->construcRuleByNameAndOptions($name, $options);
@@ -139,47 +155,59 @@ public function createRule($name, $options = null, $messageTemplate = null, $lab
return $validator;
}
+ /**
+ * Set default error message for a rule
+ *
+ * @return $this
+ */
+ public function setMessages(string $rule, string $messageWithoutLabel = null, string $messageWithLabel = null)
+ {
+ if ($messageWithoutLabel) {
+ $this->errorMessages[$rule] = $messageWithoutLabel;
+ }
+ if ($messageWithLabel) {
+ $this->labeledErrorMessages[$rule] = $messageWithLabel;
+ }
+
+ return $this;
+ }
+
/**
* Get the error message saved in the registry for a rule, where the message
* is with or without a the label
- *
- * @param string $name name of the rule
- * @param bool $withLabel
- * @return string|NULL
*/
- protected function getSuggestedMessageTemplate($name, $withLabel)
+ protected function getSuggestedMessageTemplate(string $name, bool $withLabel): ?string
{
$noLabelMessage = is_string($name) && isset($this->errorMessages[$name]) ? $this->errorMessages[$name] : null;
if ($withLabel) {
- return is_string($name) && isset($this->labeledErrorMessages[$name]) ? $this->labeledErrorMessages[$name] : $noLabelMessage;
+ return is_string($name) && isset($this->labeledErrorMessages[$name]) ?
+ $this->labeledErrorMessages[$name] :
+ $noLabelMessage;
}
return $noLabelMessage;
}
/**
- * @param $name
- * @param $options
+ * @param string|array|null $options
*
- * @return CallbackRule
+ * @return CallbackRule|AbstractRule
*/
- protected function construcRuleByNameAndOptions($name, $options)
+ protected function construcRuleByNameAndOptions(string $name, mixed $options = null)
{
if (is_callable($name)) {
- $validator = new CallbackRule(
- array(
- 'callback' => $name,
- 'arguments' => $options
- )
- );
- } else {
+ $validator = new CallbackRule([
+ 'callback' => $name,
+ 'arguments' => $options
+ ]);
+ } elseif (is_string($name)) {
$name = trim($name);
// use the validator map
if (isset($this->validatorsMap[strtolower($name)])) {
$name = $this->validatorsMap[strtolower($name)];
}
// try if the validator is the name of a class in the package
- if (class_exists('\Sirius\Validation\Rule\\' . $name)) {
+ if (class_exists('\Sirius\Validation\Rule\\' . $name, false)) {
$name = '\Sirius\Validation\Rule\\' . $name;
}
// at this point we should have a class that can be instanciated
@@ -196,5 +224,4 @@ protected function construcRuleByNameAndOptions($name, $options)
return $validator;
}
-
}
diff --git a/src/Util/Arr.php b/src/Util/Arr.php
index f11d09c..62876e5 100644
--- a/src/Util/Arr.php
+++ b/src/Util/Arr.php
@@ -1,4 +1,5 @@
*/
- protected static function getSelectorParts($selector)
+ protected static function getSelectorParts(string $selector): array
{
$firstOpen = strpos($selector, '[');
if ($firstOpen === false) {
- return array($selector, '');
+ return [$selector, ''];
}
$firstClose = strpos($selector, ']');
$container = substr($selector, 0, $firstOpen);
@@ -27,7 +27,7 @@ protected static function getSelectorParts($selector)
$firstClose + 1
);
- return array($container, $subselector);
+ return [$container, $subselector];
}
/**
@@ -37,51 +37,45 @@ protected static function getSelectorParts($selector)
* key[subkey]
* key[0][subkey]
*
- * @param array $array
- * @param string $path
+ * @param array $array
+ *
* @return mixed
*/
- public static function getByPath($array, $path = self::PATH_ROOT)
+ public static function getByPath(array $array, string $path = self::PATH_ROOT)
{
$path = trim($path);
- if (!$path || $path == self::PATH_ROOT) {
+ if (!$path || $path === self::PATH_ROOT) {
return $array;
}
// fix the path in case it was provided as `[item][subitem]`
- if (strpos($path, '[') === 0) {
+ if (str_starts_with($path, '[')) {
$path = preg_replace('/]/', '', ltrim($path, '['), 1);
}
- list($container, $subpath) = self::getSelectorParts($path);
+ list($container, $subpath) = self::getSelectorParts($path ?? '');
+ $subarray = $array[$container] ?? null;
if ($subpath === '') {
- return array_key_exists($container, $array) ? $array[$container] : null;
+ return $subarray;
}
- return array_key_exists($container, $array) ? self::getByPath($array[$container], $subpath) : null;
+ return is_array($subarray) ? self::getByPath($subarray, $subpath) : null;
}
/**
* Set values in the array by selector
*
+ * @param array $array
+ * @param bool $overwrite true if the $value should overwrite the existing value
+ *
+ * @return array
* @example
* Arr::setBySelector($data, 'email', 'my@domain.com');
* Arr::setBySelector($data, 'addresses[0][line]', null);
* Arr::setBySelector($data, 'addresses[*][line]', null);
*
- * @param array $array
- * @param string $selector
- * @param mixed $value
- * @param bool $overwrite true if the $value should overwrite the existing value
- * @return array
*/
- public static function setBySelector($array, $selector, $value, $overwrite = false)
+ public static function setBySelector(array $array, string $selector, mixed $value, bool $overwrite = false): array
{
- // make sure the array is an array in case we got here through a subsequent call
- // so arraySetElementBySelector(array(), 'item[subitem]', 'value');
- // will call arraySetElementBySelector(null, 'subitem', 'value');
- if (!is_array($array)) {
- $array = array();
- }
list($container, $subselector) = self::getSelectorParts($selector);
if (!$subselector) {
if ($container !== '*') {
@@ -95,7 +89,7 @@ public static function setBySelector($array, $selector, $value, $overwrite = fal
// if we have a subselector the $array[$container] must be an array
if ($container !== '*' && !array_key_exists($container, $array)) {
- $array[$container] = array();
+ $array[$container] = [];
}
// we got here through something like *[subitem]
if ($container === '*') {
@@ -112,28 +106,25 @@ public static function setBySelector($array, $selector, $value, $overwrite = fal
/**
* Get values in the array by selector
*
+ * @param array $array
+ * @return array
* @example
* Arr::getBySelector($data, 'email');
* Arr::getBySelector($data, 'addresses[0][line]');
* Arr::getBySelector($data, 'addresses[*][line]');
*
- * @param $array
- * @param $selector
- * @return array
*/
- public static function getBySelector($array, $selector)
+ public static function getBySelector(array $array, string $selector): array
{
- if (strpos($selector, '[*]') === false) {
- return array(
- $selector => self::getByPath($array, $selector)
- );
+ if (!str_contains($selector, '[*]')) {
+ return [$selector => self::getByPath($array, $selector)];
}
- $result = array();
+ $result = [];
list($preffix, $suffix) = explode('[*]', $selector, 2);
$base = self::getByPath($array, $preffix);
if (!is_array($base)) {
- $base = array();
+ $base = [];
}
// we don't have a suffix, the selector was something like path[subpath][*]
if (!$suffix) {
diff --git a/src/Util/RuleHelper.php b/src/Util/RuleHelper.php
new file mode 100644
index 0000000..9a0bca5
--- /dev/null
+++ b/src/Util/RuleHelper.php
@@ -0,0 +1,160 @@
+ $optionsIndexMap
+ *
+ * @return array
+ * @throws \InvalidArgumentException
+ */
+ public static function normalizeOptions(mixed $options, array $optionsIndexMap = []): array
+ {
+ if ('0' === $options && count($optionsIndexMap) > 0) {
+ $options = [$optionsIndexMap[0] => '0'];
+ }
+ if (!$options) {
+ return [];
+ }
+
+ if (is_array($options) && static::arrayIsAssoc($options)) {
+ return $options;
+ }
+
+ $result = $options;
+ if ($options && is_string($options)) {
+ $startChar = substr($options, 0, 1);
+ if ($startChar == '{') {
+ $result = json_decode($options, true);
+ } elseif (strpos($options, '=') !== false) {
+ $result = static::parseHttpQueryString($options);
+ } else {
+ $result = static::parseCsvString($options, $optionsIndexMap);
+ }
+ }
+
+ if (!is_array($result)) {
+ throw new \InvalidArgumentException('Validator options should be an array, JSON string or query string');
+ }
+
+ return $result;
+ }
+
+ /**
+ * Converts a HTTP query string to an array
+ *
+ * @return array|bool
+ */
+ public static function parseHttpQueryString(string $str): array|bool
+ {
+ parse_str($str, $arr);
+
+ return static::convertBooleanStrings($arr);
+ }
+
+ /**
+ * Converts 'true' and 'false' strings to TRUE and FALSE
+ *
+ * @param $arr
+ *
+ * @return bool|array|mixed
+ */
+ public static function convertBooleanStrings(mixed $arr): mixed
+ {
+ if (is_array($arr)) {
+ return array_map([__CLASS__, 'convertBooleanStrings'], $arr);
+ }
+ if ($arr === 'true') {
+ return true;
+ }
+ if ($arr === 'false') {
+ return false;
+ }
+
+ return $arr;
+ }
+
+
+ /**
+ * Parses a CSV string and converts the result into an "options" array
+ * (an associative array that contains the options for the validation rule)
+ *
+ * @param array $optionsIndexMap
+ *
+ * @return array|bool
+ */
+ public static function parseCsvString(string $str, array $optionsIndexMap = []): array|bool
+ {
+ if (empty($optionsIndexMap)) {
+ throw new \InvalidArgumentException(
+ '`$optionsIndexMap` argument must be provided for CSV-type parameters'
+ );
+ }
+
+ $options = explode(',', $str);
+ $result = [];
+ foreach ($options as $k => $v) {
+ if (!isset($optionsIndexMap[$k])) {
+ throw new \InvalidArgumentException(sprintf(
+ '`$optionsIndexMap` for the validator is missing the %s index',
+ $k
+ ));
+ }
+ $result[$optionsIndexMap[$k]] = $v;
+ }
+
+ return static::convertBooleanStrings($result);
+ }
+
+ /**
+ * Checks if an array is associative (ie: the keys are not numbers in sequence)
+ *
+ * @param array $arr
+ *
+ * @return bool
+ */
+ public static function arrayIsAssoc(array $arr): bool
+ {
+ return array_keys($arr) !== range(0, count($arr));
+ }
+
+ public static function normalizeFileSize(string|int|float $size): int
+ {
+ $size = (string)$size;
+ $units = ['B' => 0, 'K' => 1, 'M' => 2, 'G' => 3];
+ $unit = strtoupper(substr($size, strlen($size) - 1, 1));
+ if (!isset($units[$unit])) {
+ $normalizedSize = filter_var($size, FILTER_SANITIZE_NUMBER_INT);
+ } else {
+ $size = (float) filter_var(substr($size, 0, strlen($size) - 1), FILTER_SANITIZE_NUMBER_FLOAT);
+ $normalizedSize = $size * pow(1024, $units[$unit]);
+ }
+
+ return (int) $normalizedSize;
+ }
+
+
+ public static function normalizeImageRatio(mixed $ratio): float
+ {
+ if (is_numeric($ratio) || $ratio == filter_var($ratio, FILTER_SANITIZE_NUMBER_FLOAT)) {
+ return floatval($ratio);
+ }
+ if (strpos($ratio, ':') !== false) {
+ list($width, $height) = explode(':', $ratio);
+
+ return (float) $width / (float) $height;
+ }
+
+ return 0;
+ }
+}
diff --git a/src/Validator.php b/src/Validator.php
index edba6c3..6441a01 100755
--- a/src/Validator.php
+++ b/src/Validator.php
@@ -1,11 +1,12 @@
*/
- protected $rules = array();
+ protected array $rules = [];
/**
- * @var array
+ * @var array
*/
- protected $messages = array();
+ protected array $messages = [];
- /**
- * @var \Sirius\Validation\RuleFactory
- */
- protected $ruleFactory;
+ protected ?RuleFactory $ruleFactory = null;
- /**
- * @var ErrorMessage
- */
- protected $errorMessagePrototype;
+ protected ?ErrorMessage $errorMessagePrototype = null;
/**
* The object that will contain the data
- *
- * @var \Sirius\Validation\DataWrapper\WrapperInterface
*/
- protected $dataWrapper;
+ protected ?WrapperInterface $dataWrapper = null;
public function __construct(RuleFactory $ruleFactory = null, ErrorMessage $errorMessagePrototype = null)
{
@@ -139,66 +137,46 @@ public function __construct(RuleFactory $ruleFactory = null, ErrorMessage $error
/**
* Retrieve the rule factory
- *
- * @return \Sirius\Validation\RuleFactory
*/
- public function getRuleFactory()
+ public function getRuleFactory(): ?RuleFactory
{
return $this->ruleFactory;
}
- /**
- * @param ErrorMessage $errorMessagePrototype
- *
- * @throws \InvalidArgumentException
- *
- * @return \Sirius\Validation\Rule\AbstractValidator
- */
- public function setErrorMessagePrototype(ErrorMessage $errorMessagePrototype)
+ public function setErrorMessagePrototype(ErrorMessage $errorMessagePrototype): static
{
$this->errorMessagePrototype = $errorMessagePrototype;
return $this;
}
- /**
- * Retrieve the error message prototype
- *
- * @return ErrorMessage
- */
- public function getErroMessagePrototype()
+ public function getErrorMessagePrototype(): ?ErrorMessage
{
return $this->errorMessagePrototype;
}
/**
- * @example // add multiple rules at once
- * $validator->add(array(
- * 'field_a' => 'required',
- * 'field_b' => array('required', array('email', null, '{label} must be an email', 'Field B')),
- * ));
- * // add multiple rules using arrays
- * $validator->add('field', array('required', 'email'));
- * // add multiple rules using a string
- * $validator->add('field', 'required | email');
- * // add validator with options
- * $validator->add('field:Label', 'minlength', array('min' => 2), '{label} should have at least {min} characters');
- * // add validator with string and parameters as JSON string
- * $validator->add('field:Label', 'minlength({"min": 2})({label} should have at least {min} characters)');
- * // add validator with string and parameters as query string
- * $validator->add('field:label', 'minlength(min=2)({label} should have at least {min} characters)');
+ * @example
+ * // add multiple rules at once
+ * $validator->add(array(
+ * 'field_a' => 'required',
+ * 'field_b' => ['required', ['email', null, '{label} must be an email', 'Field B']],
+ * ));
+ *
+ * // add multiple rules using arrays
+ * $validator->add('field', ['required', 'email']);
*
- * @param string $selector
- * @param string|callback $name
- * @param string|array $options
- * @param string $messageTemplate
- * @param string $label
+ * // add multiple rules using a string
+ * $validator->add('field', 'required | email');
*
- * @throws \InvalidArgumentException
+ * // add validator with options
+ * $validator->add('field:Label', 'minlength', ['min' => 2], '{label} should have at least {min} characters');
+ *
+ * // add validator with string and parameters as query string
+ * $validator->add('field:label', 'minlength(min=2)({label} should have at least {min} characters)');
*
- * @return Validator
*/
- public function add($selector, $name = null, $options = null, $messageTemplate = null, $label = null)
+ public function add($selector, $name = null, $options = null, $messageTemplate = null, $label = null): static
{
// the $selector is an associative array with $selector => $rules
if (func_num_args() == 1) {
@@ -209,29 +187,28 @@ public function add($selector, $name = null, $options = null, $messageTemplate =
return $this->addMultiple($selector);
}
+ $selector = (string)$selector; // @phpstan-ignore-line
// check if the selector is in the form of 'selector:Label'
- if (strpos($selector, ':') !== false) {
+ if (str_contains($selector, ':')) {
list($selector, $label) = explode(':', $selector, 2);
}
- $this->ensureSelectorRulesExist($selector);
- call_user_func(array($this->rules[$selector], 'add'), $name, $options, $messageTemplate, $label);
+ $this->ensureSelectorRulesExist($selector, $label ?? '');
+ call_user_func([$this->rules[$selector], 'add'], $name, $options, $messageTemplate, $label); // @phpstan-ignore-line
return $this;
}
/**
- * @param array $selectorRulesCollection
- *
- * @return Validator
+ * @param array $selectorRulesCollection
*/
- public function addMultiple($selectorRulesCollection)
+ public function addMultiple(array $selectorRulesCollection): static
{
foreach ($selectorRulesCollection as $selector => $rules) {
-
// a single rule was passed for the $valueSelector
if (!is_array($rules)) {
- return $this->add($selector, $rules);
+ $this->add($selector, $rules);
+ continue;
}
// multiple rules were passed for the same $valueSelector
@@ -239,13 +216,7 @@ public function addMultiple($selectorRulesCollection)
// the rule is an array, this means it contains $name, $options, $messageTemplate, $label
if (is_array($rule)) {
array_unshift($rule, $selector);
- call_user_func_array(
- array(
- $this,
- 'add'
- ),
- $rule
- );
+ call_user_func_array([$this, 'add'], $rule);
// the rule is only the name of the validator
} else {
$this->add($selector, $rule);
@@ -256,16 +227,7 @@ public function addMultiple($selectorRulesCollection)
return $this;
}
- /**
- * @param string $selector
- * data selector
- * @param mixed $name
- * rule name or true if all rules should be deleted for that selector
- * @param mixed $options
- * rule options, necessary for rules that depend on params for their ID
- * @return self
- */
- public function remove($selector, $name = true, $options = null)
+ public function remove($selector, $name = true, $options = null): self
{
if (!array_key_exists($selector, $this->rules)) {
return $this;
@@ -282,9 +244,10 @@ public function remove($selector, $name = true, $options = null)
* This way you can validate anything, not just arrays (which is the default)
*
* @param mixed $data
- * @return \Sirius\Validation\DataWrapper\WrapperInterface
+ *
+ * @return WrapperInterface
*/
- public function getDataWrapper($data = null)
+ public function getDataWrapper($data = null): WrapperInterface
{
// if $data is set reconstruct the data wrapper
if (!$this->dataWrapper || $data) {
@@ -294,60 +257,52 @@ public function getDataWrapper($data = null)
return $this->dataWrapper;
}
- public function setData($data)
+ /**
+ * @param array|\ArrayObject|object $data
+ */
+ public function setData(mixed $data): static
{
$this->getDataWrapper($data);
$this->wasValidated = false;
// reset messages
- $this->messages = array();
+ $this->messages = [];
return $this;
}
/**
- * Performs the validation
- *
- * @param mixed $data
- * array to be validated
- * @return boolean
+ * @param array|\ArrayObject|object|null $data
*/
- public function validate($data = null)
+ public function validate(mixed $data = null): bool
{
if ($data !== null) {
$this->setData($data);
}
// data was already validated, return the results immediately
- if ($this->wasValidated === true) {
- return $this->wasValidated && count($this->messages) === 0;
- }
- foreach ($this->rules as $selector => $valueValidator) {
- foreach ($this->getDataWrapper()->getItemsBySelector($selector) as $valueIdentifier => $value) {
- /* @var $valueValidator \Sirius\Validation\ValueValidator */
- if (!$valueValidator->validate($value, $valueIdentifier, $this->getDataWrapper())) {
- foreach ($valueValidator->getMessages() as $message) {
- $this->addMessage($valueIdentifier, $message);
+ if (!$this->wasValidated === true) {
+ foreach ($this->rules as $selector => $valueValidator) {
+ foreach ($this->getDataWrapper()->getItemsBySelector($selector) as $valueIdentifier => $value) {
+ /* @var $valueValidator \Sirius\Validation\ValueValidator */
+ if (!$valueValidator->validate($value, $valueIdentifier, $this->getDataWrapper())) {
+ foreach ($valueValidator->getMessages() as $message) {
+ $this->addMessage($valueIdentifier, $message);
+ }
}
}
+ $this->wasValidated = true;
}
}
- $this->wasValidated = true;
- return $this->wasValidated && count($this->messages) === 0;
+ return count($this->messages) === 0;
}
- /**
- * @param string $item
- * data identifier (eg: 'email', 'addresses[0][state]')
- * @param string $message
- * @return self
- */
- public function addMessage($item, $message = null)
+ public function addMessage(string $item, string|ErrorMessage $message = null): static
{
if ($message === null || $message === '') {
return $this;
}
if (!array_key_exists($item, $this->messages)) {
- $this->messages[$item] = array();
+ $this->messages[$item] = [];
}
$this->messages[$item][] = $message;
@@ -356,18 +311,15 @@ public function addMessage($item, $message = null)
/**
* Clears the messages of an item
- *
- * @param string $item
- * @return self
*/
- public function clearMessages($item = null)
+ public function clearMessages(string $item = null): static
{
if (is_string($item)) {
if (array_key_exists($item, $this->messages)) {
unset($this->messages[$item]);
}
} elseif ($item === null) {
- $this->messages = array();
+ $this->messages = [];
}
return $this;
@@ -376,30 +328,35 @@ public function clearMessages($item = null)
/**
* @param string $item
* key of the messages array (eg: 'password', 'addresses[0][line_1]')
- * @return array
+ *
+ * @return array
*/
- public function getMessages($item = null)
+ public
+ function getMessages(string $item = null): array
{
if (is_string($item)) {
- return array_key_exists($item, $this->messages) ? $this->messages[$item] : array();
+ return array_key_exists($item, $this->messages) ? $this->messages[$item] : [];
}
return $this->messages;
}
- public function getRules()
+ /**
+ * @return array
+ */
+ public function getRules(): array
{
return $this->rules;
}
- /**
- * @param $selector
- */
- protected function ensureSelectorRulesExist($selector)
+ protected function ensureSelectorRulesExist(string $selector, string $label = ''): void
{
if (!isset($this->rules[$selector])) {
- $this->rules[$selector] = new ValueValidator($this->getRuleFactory(), $this->getErroMessagePrototype());
+ $this->rules[$selector] = new ValueValidator(
+ $this->getRuleFactory(),
+ $this->getErrorMessagePrototype(),
+ $label
+ );
}
}
-
}
diff --git a/src/ValidatorInterface.php b/src/ValidatorInterface.php
index 104f070..7f6aec9 100644
--- a/src/ValidatorInterface.php
+++ b/src/ValidatorInterface.php
@@ -1,13 +1,35 @@
$selector
+ * @param string|callable $name
+ * @param string|array $options
+ * @param string $messageTemplate
+ * @param string $label
+ *
+ * @throws \InvalidArgumentException
+ */
+ public function add($selector, $name = null, $options = null, $messageTemplate = null, $label = null): self;
- public function add($selector, $name = null, $options = null, $messageTemplate = null, $label = null);
+ /**
+ * @param string $selector
+ * data selector
+ * @param mixed $name
+ * rule name or true if all rules should be deleted for that selector
+ * @param mixed $options
+ * rule options, necessary for rules that depend on params for their ID
+ *
+ * @return self
+ */
+ public function remove($selector, $name = true, $options = null): self;
- public function remove($selector, $name = true, $options = null);
-
- public function validate($data = array());
+ /**
+ * @param array $data
+ */
+ public function validate(array $data = []): bool;
}
diff --git a/src/ValueValidator.php b/src/ValueValidator.php
index 3f0cdc7..dde50e1 100644
--- a/src/ValueValidator.php
+++ b/src/ValueValidator.php
@@ -1,8 +1,10 @@
*/
- protected $messages = array();
+ protected $messages = [];
- /**
- * Will be used to construct the rules
- *
- * @var \Sirius\Validation\RuleFactory
- */
- protected $ruleFactory;
+ protected RuleFactory $ruleFactory;
- /**
- * The prototype that will be used to generate the error message
- *
- * @var \Sirius\Validation\ErrorMessage
- */
- protected $errorMessagePrototype;
+ protected ErrorMessage $errorMessagePrototype;
- /**
- * The rule collections for the validation
- *
- * @var \Sirius\Validation\RuleCollection
- */
- protected $rules;
-
- /**
- * The label of the value to be validated
- *
- * @var string
- */
- protected $label;
+ protected RuleCollection $rules;
+ protected string $label;
- function __construct(RuleFactory $ruleFactory = null, ErrorMessage $errorMessagePrototype = null, $label = null)
+ public function __construct(
+ RuleFactory $ruleFactory = null,
+ ErrorMessage $errorMessagePrototype = null,
+ string $label = ''
+ )
{
if (!$ruleFactory) {
$ruleFactory = new RuleFactory();
@@ -59,7 +44,7 @@ function __construct(RuleFactory $ruleFactory = null, ErrorMessage $errorMessage
$this->rules = new RuleCollection;
}
- public function setLabel($label = null)
+ public function setLabel(string $label = ''): self
{
$this->label = $label;
@@ -69,45 +54,50 @@ public function setLabel($label = null)
/**
* Add 1 or more validation rules
*
- * @example // add multiple rules at once
- * $validator->add(array(
- * 'required',
- * array('required', array('email', null, '{label} must be an email', 'Field B')),
- * ));
- * // add multiple rules using a string
- * $validator->add('required | email');
- * // add validator with options
- * $validator->add('minlength', array('min' => 2), '{label} should have at least {min} characters', 'Field label');
- * // add validator with string and parameters as JSON string
- * $validator->add('minlength({"min": 2})({label} should have at least {min} characters)(Field label)');
- * // add validator with string and parameters as query string
- * $validator->add('minlength(min=2)({label} should have at least {min} characters)(Field label)');
- *
- * @param string|callback $name
- * @param string|array $options
- * @param string $messageTemplate
- * @param string $label
+ * @param string|callable $name
+ * @param string|array|null $options
+ * @param string|null $messageTemplate
+ * @param string|null $label
*
* @return ValueValidator
+ * @example
+ * // add multiple rules at once
+ * $validator->add(array(
+ * 'required',
+ * ['required', ['email', null, '{label} must be an email', 'Field B']],
+ * ));
+ *
+ * // add multiple rules using a string
+ * $validator->add('required | email');
+ *
+ * // add validator with options
+ * $validator->add('minlength', ['min' => 2], '{label} should have at least {min} characters', 'Field label');
+ *
+ * // add validator with string and parameters as JSON string
+ * $validator->add('minlength({"min": 2})({label} should have at least {min} characters)(Field label)');
+ *
+ * // add validator with string and parameters as query string
+ * $validator->add('minlength(min=2)({label} should have at least {min} characters)(Field label)');
+ *
*/
- public function add($name, $options = null, $messageTemplate = null, $label = null)
+ public function add(mixed $name, $options = null, string $messageTemplate = null, string $label = null): self
{
- if (is_array($name) && !is_callable($name)) {
+ if (is_array($name)) {
return $this->addMultiple($name);
}
if (is_string($name)) {
// rule was supplied like 'required | email'
if (strpos($name, ' | ') !== false) {
- return $this->add(explode(' | ', $name));
+ return $this->addMultiple(explode(' | ', $name));
}
// rule was supplied like this 'length(2,10)(error message template)(label)'
if (strpos($name, '(') !== false) {
- list ($name, $options, $messageTemplate, $label) = $this->parseRule($name);
+ list($name, $options, $messageTemplate, $label) = $this->parseRule($name);
}
}
// check for the default label
- if (!$label and $this->label) {
+ if (!$label && isset($this->label)) {
$label = $this->label;
}
@@ -117,35 +107,20 @@ public function add($name, $options = null, $messageTemplate = null, $label = nu
}
/**
- * @param array $rules
- *
- * @return ValueValidator
+ * @param array $rules
*/
- public function addMultiple($rules)
+ public function addMultiple($rules): self
{
foreach ($rules as $singleRule) {
// make sure the rule is an array (the parameters of subsequent calls);
- $singleRule = is_array($singleRule) ? $singleRule : array(
- $singleRule
- );
- call_user_func_array(
- array(
- $this,
- 'add'
- ),
- $singleRule
- );
+ $singleRule = is_array($singleRule) ? $singleRule : [$singleRule];
+ call_user_func_array([$this, 'add'], $singleRule);
}
return $this;
}
- /**
- * @param AbstractValidator $validationRule
- *
- * @return ValueValidator
- */
- public function addRule(AbstractRule $validationRule)
+ public function addRule(AbstractRule $validationRule): self
{
$validationRule->setErrorMessagePrototype($this->errorMessagePrototype);
$this->rules->attach($validationRule);
@@ -158,13 +133,14 @@ public function addRule(AbstractRule $validationRule)
*
* @param mixed $name
* rule name or true if all rules should be deleted for that selector
- * @param mixed $options
+ * @param string|array $options
* rule options, necessary for rules that depend on params for their ID
+ *
+ * @return self
* @throws \InvalidArgumentException
* @internal param string $selector data selector
- * @return self
*/
- public function remove($name = true, $options = null)
+ public function remove($name = true, $options = null): self
{
if ($name === true) {
$this->rules = new RuleCollection();
@@ -180,98 +156,137 @@ public function remove($name = true, $options = null)
/**
* Converts a rule that was supplied as string into a set of options that define the rule
*
+ * @param string $ruleAsString
+ *
+ * @return array
* @example 'minLength({"min":2})({label} must have at least {min} characters)(Street)'
*
* will be converted into
*
- * array(
- * 'minLength', // validator name
- * array('min' => 2'), // validator options
- * '{label} must have at least {min} characters',
- * 'Street' // label
- * )
- * @param string $ruleAsString
- * @return array
+ * [
+ * 'minLength', // validator name
+ * ['min' => 2'], // validator options
+ * '{label} must have at least {min} characters',
+ * 'Street' // label
+ * ]
+ *
*/
- protected function parseRule($ruleAsString)
+ protected function parseRule($ruleAsString): array
{
$ruleAsString = trim($ruleAsString);
- $options = array();
+ $name = $ruleAsString;
+ $options = [];
$messageTemplate = null;
$label = null;
- $name = substr($ruleAsString, 0, strpos($ruleAsString, '('));
- $ruleAsString = substr($ruleAsString, strpos($ruleAsString, '('));
- $matches = array();
- preg_match_all('/\(([^\)]*)\)/', $ruleAsString, $matches);
-
- if (isset($matches[1])) {
- if (isset($matches[1][0]) && $matches[1][0]) {
- $options = $matches[1][0];
- }
- if (isset($matches[1][1]) && $matches[1][1]) {
- $messageTemplate = $matches[1][1];
- }
- if (isset($matches[1][2]) && $matches[1][2]) {
- $label = $matches[1][2];
+ if (str_contains($ruleAsString, '(')) {
+ $name = substr($ruleAsString, 0, strpos($ruleAsString, '(')); //@phpstan-ignore-line
+ $ruleAsString = substr($ruleAsString, strpos($ruleAsString, '(')); //@phpstan-ignore-line
+ $matches = [];
+ preg_match_all('/\(([^\)]*)\)/', $ruleAsString, $matches);
+
+ if (isset($matches[1])) {
+ if (isset($matches[1][0]) && $matches[1][0] !== '') {
+ $options = $matches[1][0];
+ }
+ if (isset($matches[1][1]) && $matches[1][1]) {
+ $messageTemplate = $matches[1][1];
+ }
+ if (isset($matches[1][2]) && $matches[1][2]) {
+ $label = $matches[1][2];
+ }
}
}
- return array(
+ return [
$name,
$options,
$messageTemplate,
$label
- );
+ ];
}
- public function validate($value, $valueIdentifier = null, DataWrapper\WrapperInterface $context = null)
+ /**
+ * @param DataWrapper\WrapperInterface|null $context
+ */
+ public function validate(mixed $value, string $valueIdentifier = '', DataWrapper\WrapperInterface $context = null): bool
{
- $this->messages = array();
+ $this->messages = [];
$isRequired = false;
+
+ // evaluate the required rules
+ /** @var AbstractRule $rule */
foreach ($this->rules as $rule) {
if ($rule instanceof Rule\Required) {
$isRequired = true;
- break;
+
+ if (!$this->validateRule($rule, $value, $valueIdentifier, $context)) {
+ return false;
+ }
}
}
- if (!$isRequired && $value === null) {
+ // avoid future rule evaluations if value is null or empty string
+ if ($this->isEmpty($value)) {
return true;
}
- /* @var $rule \Sirius\Validation\Rule\AbstractValidator */
+ // evaluate the non-required rules
+ /** @var AbstractRule $rule */
foreach ($this->rules as $rule) {
- $rule->setContext($context);
- if (!$rule->validate($value, $valueIdentifier)) {
- $this->addMessage($rule->getMessage());
- }
- // if field is required and we have an error,
- // do not continue with the rest of rules
- if ($isRequired && count($this->messages)) {
- break;
+ if (!($rule instanceof Rule\Required)) {
+ $this->validateRule($rule, $value, $valueIdentifier, $context);
+
+ // if field is required and we have an error,
+ // do not continue with the rest of rules
+ if ($isRequired && count($this->messages)) { //@phpstan-ignore-line
+ break;
+ }
}
}
return count($this->messages) === 0;
}
- public function getMessages()
+ /**
+ * @param DataWrapper\WrapperInterface|null $context
+ */
+ private function validateRule(AbstractRule $rule, mixed $value, string $valueIdentifier, $context): bool
+ {
+ $rule->setContext($context);
+ if (!$rule->validate($value, $valueIdentifier)) {
+ $this->addMessage($rule->getMessage());
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * @return mixed[]
+ */
+ public function getMessages(): array
{
return $this->messages;
}
- public function addMessage($message)
+ public function addMessage(mixed $message): ValueValidator
{
array_push($this->messages, $message);
return $this;
}
- public function getRules()
+ public function getRules(): RuleCollection
{
return $this->rules;
}
+ /**
+ * @param mixed $value
+ */
+ protected function isEmpty($value): bool
+ {
+ return in_array($value, [null, ''], true);
+ }
}
diff --git a/tests/Pest.php b/tests/Pest.php
new file mode 100644
index 0000000..5949c61
--- /dev/null
+++ b/tests/Pest.php
@@ -0,0 +1,45 @@
+in('Feature');
+
+/*
+|--------------------------------------------------------------------------
+| Expectations
+|--------------------------------------------------------------------------
+|
+| When you're writing tests, you often need to check that values meet certain conditions. The
+| "expect()" function gives you access to a set of "expectations" methods that you can use
+| to assert different things. Of course, you may extend the Expectation API at any time.
+|
+*/
+
+expect()->extend('toBeOne', function () {
+ return $this->toBe(1);
+});
+
+/*
+|--------------------------------------------------------------------------
+| Functions
+|--------------------------------------------------------------------------
+|
+| While Pest is very powerful out-of-the-box, you may have some testing code specific to your
+| project that you don't want to repeat in every file. Here you can also expose helpers as
+| global functions to help you to reduce the number of lines of code in your test files.
+|
+*/
+
+function something()
+{
+ // ..
+}
diff --git a/tests/TestCase.php b/tests/TestCase.php
new file mode 100644
index 0000000..cfb05b6
--- /dev/null
+++ b/tests/TestCase.php
@@ -0,0 +1,10 @@
+
-
+
@@ -9,4 +18,9 @@
./src/
+
+
+ ./../src
+
+
diff --git a/tests/phpunit_bootstrap.php b/tests/phpunit_bootstrap.php
index ada46a3..7e0761a 100644
--- a/tests/phpunit_bootstrap.php
+++ b/tests/phpunit_bootstrap.php
@@ -1,5 +1,5 @@
validator = new Validator();
- $this->validator
- ->add('email', 'email | required')// does the order matter?
- ->add('email_confirm', 'required | email | match(item=email)')
- ->add('password', 'required')
- ->add('password_confirm', 'required | match(item=password)')
- ->add('feedback', 'requiredwith(item=agree_to_provide_feedback)')
- ->add('birthday', 'requiredwhen', array('item' => 'email_confirm', 'rule' => 'Email'))
- // the lines below don't match the example but that's ok,
- // the individual rules have tests
- ->add('lines[*][price]', 'requiredwith(item=lines[*][quantity])');
- }
-
- function notestWithCorrectData()
- {
- $data = array(
- 'email' => 'me@domain.com',
- 'email_confirm' => 'me@domain.com',
- 'password' => '1234',
- 'password_confirm' => '1234',
- 'agree_to_provide_feedback' => true,
- 'feedback' => 'This is great!',
- 'birthday' => '1980-01-01',
- 'lines' => array(
- array('quantity' => 10, 'price' => 20)
- )
- );
- $this->assertTrue($this->validator->validate($data));
- }
-
- function testWithInvalidData()
- {
- $data = array(
- 'email_confirm' => 'me@domain.com',
- 'password' => '1234',
- 'password_confirm' => '123456',
- 'agree_to_provide_feedback' => true,
- 'lines' => array(
- array('quantity' => 10, 'price' => null)
- )
- );
- $this->validator->validate($data);
- $messages = $this->validator->getMessages();
-
- $this->assertEquals('This field is required', (string)$messages['email'][0]);
- $this->assertEquals('This input does not match password', (string)$messages['password_confirm'][0]);
- $this->assertEquals('This field is required', (string)$messages['feedback'][0]);
- $this->assertEquals('This field is required', (string)$messages['lines[0][price]'][0]);
- }
-
-}
+use \Sirius\Validation\Validator;
+
+beforeEach(function () {
+ $this->validator = new Validator();
+ $this->validator
+ ->add('email', 'email | required')// does the order matter?
+ ->add('email_confirm', 'required | email | match(item=email)')
+ ->add('password', 'required | notmatch(item=email)')
+ ->add('password_confirm', 'required | match(item=password)')
+ ->add('feedback', 'requiredwith(item=agree_to_provide_feedback)')
+ ->add('birthday', 'requiredwhen', array( 'item' => 'email_confirm', 'rule' => 'Email' ))
+ // the lines below don't match the example but that's ok,
+ // the individual rules have tests
+ ->add('lines[*][price]', 'requiredwith(item=lines[*][quantity])');
+});
+
+test('with invalid data', function () {
+ $data = array(
+ 'email' => 'me@domain.com',
+ 'password' => 'me@domain.com',
+ 'password_confirm' => '123456',
+ 'agree_to_provide_feedback' => true,
+ 'lines' => array(
+ array( 'quantity' => 10, 'price' => null )
+ )
+ );
+ $this->validator->validate($data);
+ $messages = $this->validator->getMessages();
+
+ expect((string) $messages['email_confirm'][0])->toEqual('This field is required');
+ expect((string) $messages['password'][0])->toEqual('This input does match email');
+ expect((string) $messages['password_confirm'][0])->toEqual('This input does not match password');
+ expect((string) $messages['feedback'][0])->toEqual('This field is required');
+ expect((string) $messages['lines[0][price]'][0])->toEqual('This field is required');
+});
diff --git a/tests/src/ErrorMessageTest.php b/tests/src/ErrorMessageTest.php
index f7bb31b..15bdfe8 100644
--- a/tests/src/ErrorMessageTest.php
+++ b/tests/src/ErrorMessageTest.php
@@ -1,36 +1,25 @@
validator = new Validator();
- $this->validator->setErrorMessagePrototype(new CustomErrorMessage());
- }
+beforeEach(function () {
+ $this->validator = new Validator();
+ $this->validator->setErrorMessagePrototype(new CustomErrorMessage());
+});
- function testErrorMessage()
- {
- $this->validator->add('email', 'email');
- $this->validator->validate(array('email' => 'not_an_email'));
+test('error message', function () {
+ $this->validator->add('email', 'email');
+ $this->validator->validate(array( 'email' => 'not_an_email' ));
- $messages = $this->validator->getMessages('email');
- $this->assertEquals(1, count($messages));
+ $messages = $this->validator->getMessages('email');
+ expect(count($messages))->toEqual(1);
- $this->assertEquals('!!!This input must be a valid email address', (string)$messages[0]);
- }
-
-
-}
+ expect((string) $messages[0])->toEqual('!!!This input must be a valid email address');
+});
diff --git a/tests/src/HelperTest.php b/tests/src/HelperTest.php
index 4267590..873f5d3 100755
--- a/tests/src/HelperTest.php
+++ b/tests/src/HelperTest.php
@@ -1,692 +1,678 @@
assertTrue(Helper::methodExists('email'));
- $this->assertFalse(Helper::methodExists('nonExistingMethod'));
- }
-
- function testOfRequired()
- {
- $pool = array(
- 'abc' => true,
- 1.2 => true,
- '' => false
- );
- foreach ($pool as $key => $value) {
- $this->assertSame(Helper::required($key), $value);
+use \Sirius\Validation\Helper;
+
+test('method exists', function () {
+ expect(Helper::methodExists('email'))->toBeTrue();
+ expect(Helper::methodExists('nonExistingMethod'))->toBeFalse();
+});
+
+test('required', function () {
+ $pool = array(
+ ['abc', true],
+ [1.2, true],
+ ['', false]
+ );
+ foreach ($pool as list($key, $value)) {
+ expect($value)->toBe(Helper::required($key));
+ }
+ expect(false)->toBe(Helper::required(null));
+});
+
+test('truthy', function () {
+ $pool = array(
+ ['abc', true],
+ [1.2, true],
+ [0, false],
+ ['', false],
+ );
+ foreach ($pool as list($key, $value)) {
+ expect($value)->toBe(Helper::truthy($key));
+ }
+});
+
+test('falsy', function () {
+ $pool = array(
+ ['abc', false],
+ [1.2, false],
+ [0, true],
+ ['', true],
+ );
+ foreach ($pool as list($key, $value)) {
+ expect($value)->toBe(Helper::falsy($key));
+ }
+});
+
+test('callback', function () {
+ expect(Helper::callback(
+ 3,
+ function ($value) {
+ return $value === 3;
}
- $this->assertSame(Helper::required(null), false);
- }
-
- function testOfTruthy()
- {
- $pool = array(
- 'abc' => true,
- 1.2 => true,
- 0 => false,
- '' => false
- );
- foreach ($pool as $key => $value) {
- $this->assertSame(Helper::truthy($key), $value);
+ ))->toBeTrue();
+});
+
+test('email', function () {
+ $pool = array(
+ '-fa /lse@gmail.com' => false,
+ '12345@hotmail.com' => true,
+ 'xxx.yyyy-zzz@domain.com.noc' => true,
+ 'weird.name-99-@yahoo.com' => true,
+ 'shit' => false
+ );
+ foreach ($pool as $key => $value) {
+ if ($value) {
+ $message = $key . ' is a valid email';
+ } else {
+ $message = $key . ' is NOT a valid email';
}
- }
-
- function testOfFalsy()
- {
- $pool = array(
- 'abc' => false,
- 1.2 => false,
- 0 => true,
- '' => true
- );
- foreach ($pool as $key => $value) {
- $this->assertSame(Helper::falsy($key), $value);
+ expect($value)->toBe(Helper::email($key), $message);
+ }
+});
+
+test('number', function () {
+ $pool = array(
+ '1' => true,
+ '1,5' => false,
+ '2.5' => true,
+ 'abc' => false
+ );
+ foreach ($pool as $key => $value) {
+ if ($value) {
+ $message = $key . ' is a valid number';
+ } else {
+ $message = $key . ' is NOT a valid number';
}
- }
-
- function testOfCallback()
- {
- $this->assertTrue(
- Helper::callback(
- 3,
- function ($value) {
- return $value === 3;
- }
- )
- );
- }
-
- function testOfEmail()
- {
- $pool = array(
- '-fa /lse@gmail.com' => false,
- '12345@hotmail.com' => true,
- 'xxx.yyyy-zzz@domain.com.noc' => true,
- 'weird.name-99-@yahoo.com' => true,
- 'shit' => false
- );
- foreach ($pool as $key => $value) {
- if ($value) {
- $message = $key . ' is a valid email';
- } else {
- $message = $key . ' is NOT a valid email';
- }
- $this->assertSame(Helper::email($key), $value, $message);
+ expect($value)->toBe(Helper::number($key), $message);
+ }
+});
+
+test('integer', function () {
+ $pool = array(
+ '1' => true,
+ '12345' => true,
+ '1.00' => true,
+ '1.24' => false
+ );
+ foreach ($pool as $key => $value) {
+ if ($value) {
+ $message = $key . ' is a valid integer';
+ } else {
+ $message = $key . ' is NOT a valid integer';
}
- }
-
- function testOfNumber()
- {
- $pool = array(
- '1' => true,
- '1,5' => false,
- '2.5' => true,
- 'abc' => false
- );
- foreach ($pool as $key => $value) {
- if ($value) {
- $message = $key . ' is a valid number';
- } else {
- $message = $key . ' is NOT a valid number';
- }
- $this->assertSame(Helper::number($key), $value, $message);
+ expect($value)->toBe(Helper::integer($key), $message);
+ }
+});
+
+test('less than', function () {
+ $pool = array(
+ array(
+ 1,
+ 0.5,
+ false
+ ),
+ array(
+ 1,
+ 1.2,
+ true
+ )
+ );
+ foreach ($pool as $sample) {
+ if ($sample[2]) {
+ $message = $sample[0] . ' is less than ' . $sample[1];
+ } else {
+ $message = $sample[0] . ' is NOT less than ' . $sample[1];
}
- }
-
- function testOfInteger()
- {
- $pool = array(
- '1' => true,
- '12345' => true,
- '1.00' => true,
- '1.24' => false
- );
- foreach ($pool as $key => $value) {
- if ($value) {
- $message = $key . ' is a valid integer';
- } else {
- $message = $key . ' is NOT a valid integer';
- }
- $this->assertSame(Helper::integer($key), $value, $message);
+ expect($sample[2])->toBe(Helper::lessThan($sample[0], $sample[1]), $message);
+ }
+});
+
+test('greater than', function () {
+ $pool = array(
+ array(
+ 1,
+ 0.5,
+ true
+ ),
+ array(
+ 1,
+ 1.2,
+ false
+ )
+ );
+ foreach ($pool as $sample) {
+ if ($sample[2]) {
+ $message = $sample[0] . ' is less than ' . $sample[1];
+ } else {
+ $message = $sample[0] . ' is NOT less than ' . $sample[1];
}
- }
-
- function testOfLessThan()
- {
- $pool = array(
- array(
- 1,
- 0.5,
- false
- ),
- array(
- 1,
- 1.2,
- true
- )
- );
- foreach ($pool as $sample) {
- if ($sample[2]) {
- $message = $sample[0] . ' is less than ' . $sample[1];
- } else {
- $message = $sample[0] . ' is NOT less than ' . $sample[1];
- }
- $this->assertSame(Helper::lessThan($sample[0], $sample[1]), $sample[2], $message);
- }
- }
-
- function testOfGreaterThan()
- {
- $pool = array(
- array(
- 1,
- 0.5,
- true
- ),
- array(
- 1,
- 1.2,
- false
- )
- );
- foreach ($pool as $sample) {
- if ($sample[2]) {
- $message = $sample[0] . ' is less than ' . $sample[1];
- } else {
- $message = $sample[0] . ' is NOT less than ' . $sample[1];
- }
- $this->assertSame(Helper::greaterThan($sample[0], $sample[1]), $sample[2], $message);
- }
- }
-
- function testOfBetween()
- {
- $pool = array(
- array(
- 1,
- 0.5,
- 0.8,
- false
- ),
- array(
- 1,
- 0.9,
- 1.2,
- true
- )
- );
- foreach ($pool as $sample) {
- if ($sample[2]) {
- $message = $sample[0] . ' is between ' . $sample[1] . ' and ' . $sample[2];
- } else {
- $message = $sample[0] . ' is NOT between ' . $sample[1] . ' and ' . $sample[2];
- }
- $this->assertSame(Helper::between($sample[0], $sample[1], $sample[2]), $sample[3], $message);
- }
- }
-
- function testOfExactly()
- {
- $pool = array(
- array(
- 1,
- '1',
- true
- ),
- array(
- 1,
- 1.0,
- true
- ),
- array(
- 1,
- 01,
- true
- ),
- array(
- 1,
- 'a',
- false
- )
- );
- foreach ($pool as $sample) {
- if ($sample[2]) {
- $message = $sample[0] . ' is exactly ' . $sample[1];
- } else {
- $message = $sample[0] . ' is NOT exactly ' . $sample[1];
- }
- $this->assertSame(Helper::exactly($sample[0], $sample[1]), $sample[2], $message);
+ expect($sample[2])->toBe(Helper::greaterThan($sample[0], $sample[1]), $message);
+ }
+});
+
+test('between', function () {
+ $pool = array(
+ array(
+ 1,
+ 0.5,
+ 0.8,
+ false
+ ),
+ array(
+ 1,
+ 0.9,
+ 1.2,
+ true
+ )
+ );
+ foreach ($pool as $sample) {
+ if ($sample[2]) {
+ $message = $sample[0] . ' is between ' . $sample[1] . ' and ' . $sample[2];
+ } else {
+ $message = $sample[0] . ' is NOT between ' . $sample[1] . ' and ' . $sample[2];
}
- }
-
- function testOfNot()
- {
- $pool = array(
- array(
- 1,
- '1',
- false
- ),
- array(
- 1,
- 1.0,
- false
- ),
- array(
- 1,
- 01,
- false
- ),
- array(
- 1,
- 'a',
- true
- )
- );
- foreach ($pool as $sample) {
- if ($sample[2]) {
- $message = $sample[0] . ' is not ' . $sample[1];
- } else {
- $message = $sample[0] . ' is ' . $sample[1];
- }
- $this->assertSame(Helper::not($sample[0], $sample[1]), $sample[2], $message);
+ expect($sample[3])->toBe(Helper::between($sample[0], $sample[1], $sample[2]), $message);
+ }
+});
+
+test('exactly', function () {
+ $pool = array(
+ array(
+ 1,
+ '1',
+ true
+ ),
+ array(
+ 1,
+ 1.0,
+ true
+ ),
+ array(
+ 1,
+ 01,
+ true
+ ),
+ array(
+ 1,
+ 'a',
+ false
+ )
+ );
+ foreach ($pool as $sample) {
+ if ($sample[2]) {
+ $message = $sample[0] . ' is exactly ' . $sample[1];
+ } else {
+ $message = $sample[0] . ' is NOT exactly ' . $sample[1];
}
- }
-
- function testOfAlpha()
- {
- $pool = array(
- 'Some Random String ' => true,
- '123' => false,
- 'With other chars :' => false
- );
- foreach ($pool as $key => $value) {
- if ($value) {
- $message = $key . ' is a alphabetic';
- } else {
- $message = $key . ' is NOT a alphabetic';
- }
- $this->assertSame(Helper::alpha($key), $value, $message);
+ expect($sample[2])->toBe(Helper::exactly($sample[0], $sample[1]), $message);
+ }
+});
+
+test('not', function () {
+ $pool = array(
+ array(
+ 1,
+ '1',
+ false
+ ),
+ array(
+ 1,
+ 1.0,
+ false
+ ),
+ array(
+ 1,
+ 01,
+ false
+ ),
+ array(
+ 1,
+ 'a',
+ true
+ )
+ );
+ foreach ($pool as $sample) {
+ if ($sample[2]) {
+ $message = $sample[0] . ' is not ' . $sample[1];
+ } else {
+ $message = $sample[0] . ' is ' . $sample[1];
}
- }
-
- function testOfAlphanumeric()
- {
- $pool = array(
- 'Some Random String ' => true,
- 'Letters and 123' => true,
- 'With other chars :' => false
- );
- foreach ($pool as $key => $value) {
- if ($value) {
- $message = $key . ' is a alphanumeric';
- } else {
- $message = $key . ' is NOT a alphanumeric';
- }
- $this->assertSame(Helper::alphanumeric($key), $value, $message);
+ expect($sample[2])->toBe(Helper::not($sample[0], $sample[1]), $message);
+ }
+});
+
+test('alpha', function () {
+ $pool = array(
+ 'Some Random String ' => true,
+ '123' => false,
+ 'With other chars :' => false
+ );
+ foreach ($pool as $key => $value) {
+ if ($value) {
+ $message = $key . ' is a alphabetic';
+ } else {
+ $message = $key . ' is NOT a alphabetic';
}
- }
-
- function testOfAlphanumhyphen()
- {
- $pool = array(
- 'Some Random String ' => true,
- 'Letters and 123' => true,
- 'With other hyphens _ -' => true,
- '? - this is not acceptable' => false
- );
- foreach ($pool as $key => $value) {
- if ($value) {
- $message = $key . ' is a alphanumhyphen';
- } else {
- $message = $key . ' is NOT a alphanumhyphen';
- }
- $this->assertSame(Helper::alphanumhyphen($key), $value, $message);
+ expect($value)->toBe(Helper::alpha($key), $message);
+ }
+});
+
+test('alphanumeric', function () {
+ $pool = array(
+ 'Some Random String ' => true,
+ 'Letters and 123' => true,
+ 'With other chars :' => false
+ );
+ foreach ($pool as $key => $value) {
+ if ($value) {
+ $message = $key . ' is a alphanumeric';
+ } else {
+ $message = $key . ' is NOT a alphanumeric';
}
- }
-
- function testOfLength()
- {
- $this->assertTrue(Helper::length('abc', 1, 5));
- }
-
- function testOfMinLength()
- {
- $pool = array(
- array(
- 'abcde',
- 7,
- false
- ),
- array(
- 'abcde',
- 4,
- true
- )
- );
- foreach ($pool as $sample) {
- if ($sample[2]) {
- $message = $sample[0] . ' has more than ' . $sample[1] . ' characters';
- } else {
- $message = $sample[0] . ' does NOT have more than ' . $sample[1] . ' characters';
- }
- $this->assertSame(Helper::minLength($sample[0], $sample[1]), $sample[2], $message);
+ expect($value)->toBe(Helper::alphanumeric($key), $message);
+ }
+});
+
+test('alphanumhyphen', function () {
+ $pool = array(
+ 'Some Random String ' => true,
+ 'Letters and 123' => true,
+ 'With other hyphens _ -' => true,
+ '? - this is not acceptable' => false
+ );
+ foreach ($pool as $key => $value) {
+ if ($value) {
+ $message = $key . ' is a alphanumhyphen';
+ } else {
+ $message = $key . ' is NOT a alphanumhyphen';
}
- }
-
- function testOfMaxLength()
- {
- $pool = array(
- array(
- 'abcde',
- 4,
- false
- ),
- array(
- 'abcde',
- 6,
- true
- )
- );
- foreach ($pool as $sample) {
- if ($sample[2]) {
- $message = $sample[0] . ' has less than ' . $sample[1] . ' characters';
- } else {
- $message = $sample[0] . ' does NOT have less than ' . $sample[1] . ' characters';
- }
- $this->assertSame(Helper::maxLength($sample[0], $sample[1]), $sample[2], $message);
+ expect($value)->toBe(Helper::alphanumhyphen($key), $message);
+ }
+});
+
+test('length', function () {
+ expect(Helper::length('abc', 1, 5))->toBeTrue();
+});
+
+test('min length', function () {
+ $pool = array(
+ array(
+ 'abcde',
+ 7,
+ false
+ ),
+ array(
+ 'abcde',
+ 4,
+ true
+ )
+ );
+ foreach ($pool as $sample) {
+ if ($sample[2]) {
+ $message = $sample[0] . ' has more than ' . $sample[1] . ' characters';
+ } else {
+ $message = $sample[0] . ' does NOT have more than ' . $sample[1] . ' characters';
}
- }
-
- function testOfIn()
- {
- $pool = array(
- array(
- '6',
- array(
- '5',
- '8'
- ),
- false
- ),
- array(
- '5',
- array(
- '5',
- '8'
- ),
- true
- )
- );
- foreach ($pool as $sample) {
- $this->assertSame(Helper::in($sample[0], $sample[1]), $sample[2]);
+ expect($sample[2])->toBe(Helper::minLength($sample[0], $sample[1]), $message);
+ }
+});
+
+test('max length', function () {
+ $pool = array(
+ array(
+ 'abcde',
+ 4,
+ false
+ ),
+ array(
+ 'abcde',
+ 6,
+ true
+ )
+ );
+ foreach ($pool as $sample) {
+ if ($sample[2]) {
+ $message = $sample[0] . ' has less than ' . $sample[1] . ' characters';
+ } else {
+ $message = $sample[0] . ' does NOT have less than ' . $sample[1] . ' characters';
}
+ expect($sample[2])->toBe(Helper::maxLength($sample[0], $sample[1]), $message);
}
+});
- function testOfNotIn()
- {
- $pool = array(
+test('in', function () {
+ $pool = array(
+ array(
+ '6',
array(
'5',
- array(
- '5',
- '8'
- ),
- false
- ),
- array(
- '6',
- array(
- '5',
- '8'
- ),
- true
- )
- );
- foreach ($pool as $sample) {
- $this->assertSame(Helper::notIn($sample[0], $sample[1]), $sample[2]);
- }
- }
-
- function testOfRegex()
- {
- $pool = array(
- array(
- 'abc',
- '/[0-9]+/',
- false
- ),
- array(
- '123',
- '/[0-9]+/',
- true
- )
- );
- foreach ($pool as $sample) {
- $this->assertSame(Helper::regex($sample[0], $sample[1]), $sample[2]);
- }
- }
-
- function testOfNotRegex()
- {
- $pool = array(
- array(
- 'abc',
- '/[0-9]+/',
- true
- ),
- array(
- '123',
- '/[0-9]+/',
- false
- )
- );
- foreach ($pool as $sample) {
- $this->assertSame(Helper::notRegex($sample[0], $sample[1]), $sample[2]);
- }
- }
-
- function testOfEqualToWithContext()
- {
- $pool = array(
- array(
- 'value',
- 'element_1',
- true
- ),
- array(
- 'value',
- 'element_2',
- false
- ),
- array(
- 'new value',
- 'element_3[sub_element_1][sub_element_2]',
- true
- )
- );
- $context = array(
- 'element_1' => 'value',
- 'element_2' => 'another_value',
- 'element_3' => array(
- 'sub_element_1' => array(
- 'sub_element_2' => 'new value'
- )
- )
- );
- foreach ($pool as $sample) {
- $this->assertSame(
- Helper::equalTo($sample[0], $sample[1], $context),
- $sample[2],
- sprintf("%s %s", $sample[0], $sample[1])
- );
- }
- }
-
- function testOfEqualToWithoutContext()
- {
- $this->assertTrue(Helper::equalTo(5, '5'));
- $this->assertFalse(Helper::equalTo(5, 'a'));
- }
-
- function testOfWebsite()
- {
- $pool = array(
- array(
- 'https://www.domain.co.uk/',
- true
- ),
- array(
- 'https://www.domain.co.uk/folder/page.html?var=value#!fragment',
- true
- ),
- array(
- '123',
- false
- )
- );
- foreach ($pool as $sample) {
- $this->assertSame(Helper::website($sample[0]), $sample[1]);
- }
- }
-
- function testOfUrl()
- {
- $pool = array(
- array(
- 'ftp://ftp.domain.co.uk/',
- true
- ),
- array(
- 'ftp://username:password@domain.co.uk/folder/',
- true
- ),
- array(
- '123',
- false
- )
- );
- foreach ($pool as $sample) {
- $this->assertSame(Helper::url($sample[0]), $sample[1]);
- }
- }
-
- function testOfIp()
- {
- $pool = array(
- array(
- '196.168.100.1',
- true
+ '8'
),
+ false
+ ),
+ array(
+ '5',
array(
- '256.5765.53.21',
- false
+ '5',
+ '8'
),
- array(
- '2001:db8:85a3:8d3:1319:8a2e:370:7348',
- true
- ) //IPv6
- );
-
- foreach ($pool as $sample) {
- $this->assertSame(Helper::ip($sample[0]), $sample[1]);
- }
+ true
+ )
+ );
+ foreach ($pool as $sample) {
+ expect($sample[2])->toBe(Helper::inList($sample[0], $sample[1]));
}
+});
- function testOfSetMaxSize()
- {
- $set = array(
- 'element_1' => 'value',
- 'element_2' => 'another_value',
- 'element_3' => array(
- 'sub_element_1' => 'new value'
- )
- );
- $pool = array(
+test('not in', function () {
+ $pool = array(
+ array(
+ '5',
array(
- '4',
- true
+ '5',
+ '8'
),
+ false
+ ),
+ array(
+ '6',
array(
- '2',
- false
- )
- );
- foreach ($pool as $sample) {
- $this->assertSame(Helper::setMaxSize($set, $sample[0]), $sample[1]);
- }
- }
-
- function testOfSetMinSize()
- {
- $set = array(
- 'element_1' => 'value',
- 'element_2' => 'another_value',
- 'element_3' => array(
- 'sub_element_1' => 'new value'
- )
- );
- $pool = array(
- array(
- '4',
- false
+ '5',
+ '8'
),
- array(
- '2',
- true
+ true
+ )
+ );
+ foreach ($pool as $sample) {
+ expect($sample[2])->toBe(Helper::notInList($sample[0], $sample[1]));
+ }
+});
+
+test('regex', function () {
+ $pool = array(
+ array(
+ 'abc',
+ '/[0-9]+/',
+ false
+ ),
+ array(
+ '123',
+ '/[0-9]+/',
+ true
+ )
+ );
+ foreach ($pool as $sample) {
+ expect($sample[2])->toBe(Helper::regex($sample[0], $sample[1]));
+ }
+});
+
+test('not regex', function () {
+ $pool = array(
+ array(
+ 'abc',
+ '/[0-9]+/',
+ true
+ ),
+ array(
+ '123',
+ '/[0-9]+/',
+ false
+ )
+ );
+ foreach ($pool as $sample) {
+ expect($sample[2])->toBe(Helper::notRegex($sample[0], $sample[1]));
+ }
+});
+
+test('equal to with context', function () {
+ $pool = array(
+ array(
+ 'value',
+ 'element_1',
+ true
+ ),
+ array(
+ 'value',
+ 'element_2',
+ false
+ ),
+ array(
+ 'new value',
+ 'element_3[sub_element_1][sub_element_2]',
+ true
+ )
+ );
+ $context = array(
+ 'element_1' => 'value',
+ 'element_2' => 'another_value',
+ 'element_3' => array(
+ 'sub_element_1' => array(
+ 'sub_element_2' => 'new value'
)
- );
- foreach ($pool as $sample) {
- $this->assertSame(Helper::setMinSize($set, $sample[0]), $sample[1]);
- }
- }
-
- function testOfSetSize()
- {
- $set = array(
- 'element_1' => 'value',
- 'element_2' => 'another_value',
- 'element_3' => array(
- 'sub_element_1' => 'new value'
+ )
+ );
+ foreach ($pool as $sample) {
+ expect($sample[2])->toBe(Helper::equalTo($sample[0], $sample[1], $context), sprintf("%s %s", $sample[0], $sample[1]));
+ }
+});
+
+test('not equal to with context', function () {
+ $pool = array(
+ array(
+ 'value',
+ 'element_1',
+ false
+ ),
+ array(
+ 'value',
+ 'element_2',
+ true
+ ),
+ array(
+ 'new value',
+ 'element_3[sub_element_1][sub_element_2]',
+ false
+ )
+ );
+ $context = array(
+ 'element_1' => 'value',
+ 'element_2' => 'another_value',
+ 'element_3' => array(
+ 'sub_element_1' => array(
+ 'sub_element_2' => 'new value'
)
- );
- $pool = array(
- array(
- 2,
- 5,
- true
- ),
- array(
- 6,
- 8,
- false
- )
- );
- foreach ($pool as $sample) {
- $this->assertSame(Helper::setSize($set, $sample[0], $sample[1]), $sample[2]);
- }
- }
-
- function validationCallback($value, $options = false, $context = null)
- {
- return ($value == 5 and $options = 3 and $context == null);
- }
-
- function testOfValidAddMethodCalls()
- {
- Helper::addMethod(
- 'myValidation',
- array(
- $this,
- 'validationCallback'
- )
- );
- $this->assertTrue(Helper::myValidation(5, 3));
- $this->assertFalse(Helper::myValidation(5, 3, 3));
- }
-
- function testOfInvalidAddMethodCalls()
- {
- $this->setExpectedException('InvalidArgumentException');
- Helper::addMethod('mySecondValidation', 'nonexistantcallback');
- $this->assertTrue(Helper::mySecondValidation(5));
- }
-
- function testOfFullName()
- {
- $this->assertTrue(Helper::fullName('First Last'));
- $this->assertFalse(Helper::fullName('F Last'));
- $this->assertFalse(Helper::fullName('First L'));
- $this->assertFalse(Helper::fullName('Fi La'));
- }
-
- function testOfEmailDomain()
- {
- $this->assertTrue(Helper::emailDomain('me@hotmail.com'));
- $this->assertFalse(Helper::emailDomain('me@hotmail.com.not.valid'));
- }
-
- function testOfDate()
- {
- $this->assertTrue(Helper::date('2012-07-13', 'Y-m-d'));
- $this->assertFalse(Helper::date('2012-07-13', 'Y/m/d'));
- }
-
- function testOfDateTime()
- {
- $this->assertTrue(Helper::dateTime('2012-07-13 20:00:15', 'Y-m-d H:i:s'));
- $this->assertFalse(Helper::dateTime('2012-07-13'));
- }
-
- function testOfTime()
- {
- $this->assertTrue(Helper::time('20:00:15', 'H:i:s'));
- $this->assertFalse(Helper::time('20:00:99'));
- }
-
+ )
+ );
+ foreach ($pool as $sample) {
+ expect($sample[2])->toBe(Helper::notEqualTo($sample[0], $sample[1], $context), sprintf("%s %s", $sample[0], $sample[1]));
+ }
+});
+
+test('equal to without context', function () {
+ expect(Helper::equalTo(5, '5'))->toBeTrue();
+ expect(Helper::equalTo(5, 'a'))->toBeFalse();
+});
+
+test('not equal to without context', function () {
+ expect(Helper::NotEqualTo(5, 'a'))->toBeTrue();
+ expect(Helper::NotEqualTo(5, '5'))->toBeFalse();
+});
+
+test('website', function () {
+ $pool = array(
+ array(
+ 'https://www.domain.co.uk/',
+ true
+ ),
+ array(
+ 'https://www.domain.co.uk/folder/page.html?var=value#!fragment',
+ true
+ ),
+ array(
+ '123',
+ false
+ )
+ );
+ foreach ($pool as $sample) {
+ expect($sample[1])->toBe(Helper::website($sample[0]));
+ }
+});
+
+test('url', function () {
+ $pool = array(
+ array(
+ 'ftp://ftp.domain.co.uk/',
+ true
+ ),
+ array(
+ 'ftp://username:password@domain.co.uk/folder/',
+ true
+ ),
+ array(
+ '123',
+ false
+ )
+ );
+ foreach ($pool as $sample) {
+ expect($sample[1])->toBe(Helper::url($sample[0]));
+ }
+});
+
+test('ip', function () {
+ $pool = array(
+ array(
+ '196.168.100.1',
+ true
+ ),
+ array(
+ '256.576a.53.21',
+ false
+ ),
+ array(
+ '2002:51c4:7c3c:0000:0000:0000:0000:0000',
+ true
+ ) //IPv6
+ );
+
+ foreach ($pool as $sample) {
+ expect($sample[1])->toBe(Helper::ipAddress($sample[0]), $sample[0]);
+ }
+});
+
+test('set max size', function () {
+ $set = array(
+ 'element_1' => 'value',
+ 'element_2' => 'another_value',
+ 'element_3' => array(
+ 'sub_element_1' => 'new value'
+ )
+ );
+ $pool = array(
+ array(
+ '4',
+ true
+ ),
+ array(
+ '2',
+ false
+ )
+ );
+ foreach ($pool as $sample) {
+ expect($sample[1])->toBe(Helper::setMaxSize($set, $sample[0]));
+ }
+});
+
+test('set min size', function () {
+ $set = array(
+ 'element_1' => 'value',
+ 'element_2' => 'another_value',
+ 'element_3' => array(
+ 'sub_element_1' => 'new value'
+ )
+ );
+ $pool = array(
+ array(
+ '4',
+ false
+ ),
+ array(
+ '2',
+ true
+ )
+ );
+ foreach ($pool as $sample) {
+ expect($sample[1])->toBe(Helper::setMinSize($set, $sample[0]));
+ }
+});
+
+test('set size', function () {
+ $set = array(
+ 'element_1' => 'value',
+ 'element_2' => 'another_value',
+ 'element_3' => array(
+ 'sub_element_1' => 'new value'
+ )
+ );
+ $pool = array(
+ array(
+ 2,
+ 5,
+ true
+ ),
+ array(
+ 6,
+ 8,
+ false
+ )
+ );
+ foreach ($pool as $sample) {
+ expect($sample[2])->toBe(Helper::setSize($set, $sample[0], $sample[1]));
+ }
+});
+
+function validationCallback($value, $options = false, $context = null)
+{
+ return ($value == 5 and $options = 3 and $context == null);
}
+
+test('valid add method calls', function () {
+ Helper::addMethod(
+ 'myValidation',
+ 'validationCallback'
+ );
+ expect(Helper::myValidation(5, 3))->toBeTrue();
+ expect(Helper::myValidation(5, 3, 3))->toBeFalse();
+});
+
+test('invalid add method calls', function () {
+ $this->expectException('InvalidArgumentException');
+ Helper::addMethod('mySecondValidation', 'nonexistantcallback');
+ expect(Helper::mySecondValidation(5))->toBeTrue();
+});
+
+test('full name', function () {
+ expect(Helper::fullName('First Last'))->toBeTrue();
+ expect(Helper::fullName('F Last'))->toBeFalse();
+ expect(Helper::fullName('First L'))->toBeFalse();
+ expect(Helper::fullName('Fi La'))->toBeFalse();
+});
+
+test('email domain', function () {
+ expect(Helper::emailDomain('me@hotmail.com'))->toBeTrue();
+ expect(Helper::emailDomain('me@hotmail.com.not.valid'))->toBeFalse();
+});
+
+test('date', function () {
+ expect(Helper::date('2012-07-13', 'Y-m-d'))->toBeTrue();
+ expect(Helper::date('2012-07-13', 'Y/m/d'))->toBeFalse();
+});
+
+test('date time', function () {
+ expect(Helper::dateTime('2012-07-13 20:00:15', 'Y-m-d H:i:s'))->toBeTrue();
+ expect(Helper::dateTime('2012-07-13'))->toBeFalse();
+});
+
+test('time', function () {
+ expect(Helper::time('20:00:15', 'H:i:s'))->toBeTrue();
+ expect(Helper::time('20:00:99'))->toBeFalse();
+});
diff --git a/tests/src/Rule/AbstractValidatorTest.php b/tests/src/Rule/AbstractValidatorTest.php
index 2944d7a..4d84398 100755
--- a/tests/src/Rule/AbstractValidatorTest.php
+++ b/tests/src/Rule/AbstractValidatorTest.php
@@ -1,11 +1,10 @@
value = $value;
$this->success = (bool)$value && isset($this->context) && $this->context->getItemValue('key');
@@ -14,55 +13,49 @@ function validate($value, $valueIdentifier = null)
}
}
-
-class AbstractRuleTest extends \PHPUnit_Framework_TestCase
-{
-
- function setUp()
- {
- $this->rule = new FakeRule();
- }
-
- function testErrorMessagePrototype()
- {
- // we always have an error message prototype
- $this->assertTrue($this->rule->getErrorMessagePrototype() instanceof \Sirius\Validation\ErrorMessage);
- $proto = new \Sirius\Validation\ErrorMessage('Not valid');
- $this->rule->setErrorMessagePrototype($proto);
- $this->assertEquals('Not valid', (string)$this->rule->getErrorMessagePrototype());
- }
-
- function testMessageIsGeneratedCorrectly()
- {
- $this->rule->setOption('label', 'Accept');
- $this->rule->setMessageTemplate('Field "{label}" must be true, {value} was provided');
- $this->rule->validate('false');
- $this->assertEquals('Field "Accept" must be true, false was provided', (string)$this->rule->getMessage());
- }
-
- function testNoMessageWhenValidationPasses()
- {
- $this->rule->setContext(array('key' => true));
- $this->assertTrue($this->rule->validate(true));
- $this->assertNull($this->rule->getMessage());
- }
-
- function testContext()
- {
- $this->assertFalse($this->rule->validate(true));
- $this->rule->setContext(array('key' => true));
- $this->assertTrue($this->rule->validate(true));
- }
-
- function testErrorMessageTemplateIsUsed()
- {
- $this->rule->setMessageTemplate('Custom message');
- $this->assertEquals('Custom message', (string)$this->rule->getPotentialMessage());
- }
-
- function testErrorThrownOnInvalidContext()
- {
- $this->setExpectedException('\InvalidArgumentException');
- $this->rule->setContext(new \stdClass());
- }
-}
+beforeEach(function () {
+ $this->rule = new FakeRule();
+});
+
+test('error message prototype', function () {
+ // we always have an error message prototype
+ expect($this->rule->getErrorMessagePrototype())->toBeInstanceOf(ErrorMessage::class);
+ $proto = new ErrorMessage('Not valid');
+ $this->rule->setErrorMessagePrototype($proto);
+ expect((string) $this->rule->getErrorMessagePrototype())->toEqual('Not valid');
+});
+
+test('message is generated correctly', function () {
+ $this->rule->setOption('label', 'Accept');
+ $this->rule->setMessageTemplate('Field "{label}" must be true, {value} was provided');
+ $this->rule->validate('false');
+ expect((string) $this->rule->getMessage())->toEqual('Field "Accept" must be true, false was provided');
+});
+
+test('no message when validation passes', function () {
+ $this->rule->setContext(array( 'key' => true ));
+ expect($this->rule->validate(true))->toBeTrue();
+ expect($this->rule->getMessage())->toBeNull();
+});
+
+test('context', function () {
+ expect($this->rule->validate(true))->toBeFalse();
+ $this->rule->setContext(array( 'key' => true ));
+ expect($this->rule->validate(true))->toBeTrue();
+});
+
+test('error message template is used', function () {
+ $this->rule->setMessageTemplate('Custom message');
+ expect((string) $this->rule->getPotentialMessage())->toEqual('Custom message');
+});
+
+test('error thrown on invalid context', function () {
+ $this->expectException('\InvalidArgumentException');
+ $this->rule->setContext(new \stdClass());
+});
+
+test('get option', function () {
+ $this->rule->setOption('label', 'Accept');
+ expect($this->rule->getOption('label'))->toEqual('Accept');
+ expect($this->rule->getOption('notExist'))->toBeNull();
+});
diff --git a/tests/src/Rule/ArrayMaxLengthTest.php b/tests/src/Rule/ArrayMaxLengthTest.php
index c11a310..12870c7 100755
--- a/tests/src/Rule/ArrayMaxLengthTest.php
+++ b/tests/src/Rule/ArrayMaxLengthTest.php
@@ -1,19 +1,12 @@
rule = new Rule();
- }
+beforeEach(function () {
+ $this->rule = new Rule();
+});
- function testValidationWithoutALimit()
- {
- $this->assertTrue($this->rule->validate(array()));
- }
-}
+test('validation without a limit', function () {
+ expect($this->rule->validate(array()))->toBeTrue();
+});
diff --git a/tests/src/Rule/ArrayMinLengthTest.php b/tests/src/Rule/ArrayMinLengthTest.php
index 46f2b3c..3243a31 100755
--- a/tests/src/Rule/ArrayMinLengthTest.php
+++ b/tests/src/Rule/ArrayMinLengthTest.php
@@ -1,19 +1,12 @@
rule = new Rule();
- }
+beforeEach(function () {
+ $this->rule = new Rule();
+});
- function testValidationWithoutALimit()
- {
- $this->assertTrue($this->rule->validate(array()));
- }
-}
+test('validation without a limit', function () {
+ expect($this->rule->validate(array()))->toBeTrue();
+});
diff --git a/tests/src/Rule/BetweenTest.php b/tests/src/Rule/BetweenTest.php
index 22d9ebf..d546a98 100644
--- a/tests/src/Rule/BetweenTest.php
+++ b/tests/src/Rule/BetweenTest.php
@@ -1,24 +1,16 @@
rule = new Rule();
- }
- function testValidation()
- {
- $this->rule->setOption('min', 50);
- $this->rule->setOption('max', 100);
- $this->assertFalse($this->rule->validate(40));
- $this->assertFalse($this->rule->validate(110));
- $this->assertTrue($this->rule->validate(80));
- }
+beforeEach(function () {
+ $this->rule = new Rule();
+});
-}
+test('validation', function () {
+ $this->rule->setOption('min', 50);
+ $this->rule->setOption('max', 100);
+ expect($this->rule->validate(40))->toBeFalse();
+ expect($this->rule->validate(110))->toBeFalse();
+ expect($this->rule->validate(80))->toBeTrue();
+});
diff --git a/tests/src/Rule/CallbackTest.php b/tests/src/Rule/CallbackTest.php
index cb6a32b..732b2d4 100644
--- a/tests/src/Rule/CallbackTest.php
+++ b/tests/src/Rule/CallbackTest.php
@@ -1,58 +1,47 @@
rule = new Rule();
- }
-
- function testValidationWithoutAValidCallback()
- {
- $this->rule->setOption(Rule::OPTION_CALLBACK, 'ssss');
- $this->assertTrue($this->rule->validate('abc'));
- }
-
- function testGetUniqueIdForCallbacksAsStrings()
- {
- $this->rule->setOption(Rule::OPTION_CALLBACK, 'is_int');
- $this->assertTrue(strpos($this->rule->getUniqueId(), '|is_int') !== false);
-
- $this->rule->setOption(Rule::OPTION_CALLBACK, 'Class::method');
- $this->assertTrue(strpos($this->rule->getUniqueId(), '|Class::method') !== false);
- }
-
- function testGetUniqueIdForCallbacksAsArrays()
- {
- $this->rule->setOption(Rule::OPTION_CALLBACK, array('Class', 'method'));
- $this->assertTrue(strpos($this->rule->getUniqueId(), '|Class::method') !== false);
-
- $this->rule->setOption(Rule::OPTION_CALLBACK, array($this, 'setUp'));
- $this->assertTrue(strpos($this->rule->getUniqueId(), '->setUp') !== false);
- }
-
- function testGetUniqueIdForCallbacksWithArguments()
- {
- $this->rule->setOption(Rule::OPTION_CALLBACK, 'is_int');
- $this->rule->setOption(Rule::OPTION_ARGUMENTS, array('b' => 2, 'a' => 1));
-
- // arguments should be sorted by key so test for that too
- $this->assertTrue(strpos($this->rule->getUniqueId(), '|{"a":1,"b":2}') !== false);
- }
-
- function testGetUniqueIdForClosures()
- {
- $this->rule->setOption(
- Rule::OPTION_CALLBACK,
- function ($value, $valueIdentifier) {
- return true;
- }
- );
- $this->assertNotNull($this->rule->getUniqueId());
- }
-}
+
+beforeEach(function () {
+ $this->rule = new Rule();
+});
+
+test('validation without a valid callback', function () {
+ $this->rule->setOption(Rule::OPTION_CALLBACK, 'ssss');
+ expect($this->rule->validate('abc'))->toBeTrue();
+});
+
+test('get unique id for callbacks as strings', function () {
+ $this->rule->setOption(Rule::OPTION_CALLBACK, 'is_int');
+ expect(strpos($this->rule->getUniqueId(), '|is_int') !== false)->toBeTrue();
+
+ $this->rule->setOption(Rule::OPTION_CALLBACK, 'Class::method');
+ expect(strpos($this->rule->getUniqueId(), '|Class::method') !== false)->toBeTrue();
+});
+
+test('get unique id for callbacks as arrays', function () {
+ $this->rule->setOption(Rule::OPTION_CALLBACK, array( 'Class', 'method' ));
+ expect(strpos($this->rule->getUniqueId(), '|Class::method') !== false)->toBeTrue();
+
+ $this->rule->setOption(Rule::OPTION_CALLBACK, array( $this, 'setUp' ));
+ expect(strpos($this->rule->getUniqueId(), '->setUp') !== false)->toBeTrue();
+});
+
+test('get unique id for callbacks with arguments', function () {
+ $this->rule->setOption(Rule::OPTION_CALLBACK, 'is_int');
+ $this->rule->setOption(Rule::OPTION_ARGUMENTS, array( 'b' => 2, 'a' => 1 ));
+
+ // arguments should be sorted by key so test for that too
+ expect(strpos($this->rule->getUniqueId(), '|{"a":1,"b":2}') !== false)->toBeTrue();
+});
+
+test('get unique id for closures', function () {
+ $this->rule->setOption(
+ Rule::OPTION_CALLBACK,
+ function ($value, $valueIdentifier) {
+ return true;
+ }
+ );
+ expect($this->rule->getUniqueId())->not->toBeNull();
+});
diff --git a/tests/src/Rule/EmailTest.php b/tests/src/Rule/EmailTest.php
index 84adabd..2f8d88d 100644
--- a/tests/src/Rule/EmailTest.php
+++ b/tests/src/Rule/EmailTest.php
@@ -1,21 +1,13 @@
rule = new Rule();
- }
- function testValidation()
- {
- $this->assertFalse($this->rule->validate(''));
- $this->assertTrue($this->rule->validate('me@domain.com'));
- }
+beforeEach(function () {
+ $this->rule = new Rule();
+});
-}
+test('validation', function () {
+ expect($this->rule->validate(''))->toBeFalse();
+ expect($this->rule->validate('me@domain.com'))->toBeTrue();
+});
diff --git a/tests/src/Rule/EqualTest.php b/tests/src/Rule/EqualTest.php
index a3c09a3..1322299 100644
--- a/tests/src/Rule/EqualTest.php
+++ b/tests/src/Rule/EqualTest.php
@@ -1,28 +1,19 @@
rule = new Rule();
- }
- function testValidationWithOptionSet()
- {
- $this->rule->setOption(Rule::OPTION_VALUE, '123');
- $this->assertTrue($this->rule->validate('123'));
- $this->assertFalse($this->rule->validate('abc'));
- }
+beforeEach(function () {
+ $this->rule = new Rule();
+});
- function testValidationWithoutOptionSet()
- {
- $this->assertTrue($this->rule->validate('abc'));
- $this->assertTrue($this->rule->validate(null));
- }
+test('validation with option set', function () {
+ $this->rule->setOption(Rule::OPTION_VALUE, '123');
+ expect($this->rule->validate('123'))->toBeTrue();
+ expect($this->rule->validate('abc'))->toBeFalse();
+});
-}
+test('validation without option set', function () {
+ expect($this->rule->validate('abc'))->toBeTrue();
+ expect($this->rule->validate(null))->toBeTrue();
+});
diff --git a/tests/src/Rule/File/ExtensionTest.php b/tests/src/Rule/File/ExtensionTest.php
index a0f9b2c..8f3556a 100644
--- a/tests/src/Rule/File/ExtensionTest.php
+++ b/tests/src/Rule/File/ExtensionTest.php
@@ -1,43 +1,31 @@
validator = new Extension();
+});
- function setUp()
- {
- $this->validator = new Extension();
- }
+test('existing files', function () {
+ $this->validator->setOption(Extension::OPTION_ALLOWED_EXTENSIONS, array( 'jpg' ));
+ $file = realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . 'real_jpeg_file.jpg';
+ expect($this->validator->validate($file))->toBeTrue();
+});
- function testExistingFiles()
- {
- $this->validator->setOption(Extension::OPTION_ALLOWED_EXTENSIONS, array('jpg'));
- $file = realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . 'real_jpeg_file.jpg';
- $this->assertTrue($this->validator->validate($file));
- }
+test('missing files', function () {
+ $this->validator->setOption(Extension::OPTION_ALLOWED_EXTENSIONS, array( 'jpg' ));
+ $file = realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . 'file_that_does_not_exist.jpg';
+ expect($this->validator->validate($file))->toBeFalse();
+});
- function testMissingFiles()
- {
- $this->validator->setOption(Extension::OPTION_ALLOWED_EXTENSIONS, array('jpg'));
- $file = realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . 'file_that_does_not_exist.jpg';
- $this->assertFalse($this->validator->validate($file));
- }
+test('set option as string', function () {
+ $this->validator->setOption(Extension::OPTION_ALLOWED_EXTENSIONS, 'jpg, GIF');
+ $file = realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . 'real_jpeg_file.jpg';
+ expect($this->validator->validate($file))->toBeTrue();
+});
- function testSetOptionAsString()
- {
- $this->validator->setOption(Extension::OPTION_ALLOWED_EXTENSIONS, 'jpg, GIF');
- $file = realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . 'real_jpeg_file.jpg';
- $this->assertTrue($this->validator->validate($file));
- }
-
- function testPotentialMessage()
- {
- $this->validator->setOption(Extension::OPTION_ALLOWED_EXTENSIONS, array('jpg', 'png'));
- $this->validator->validate('no_file.jpg');
- $this->assertEquals(
- 'The file does not have an acceptable extension (JPG, PNG)',
- (string)$this->validator->getPotentialMessage()
- );
- }
-}
+test('potential message', function () {
+ $this->validator->setOption(Extension::OPTION_ALLOWED_EXTENSIONS, array( 'jpg', 'png' ));
+ $this->validator->validate('no_file.jpg');
+ expect((string) $this->validator->getPotentialMessage())->toEqual('The file does not have an acceptable extension (JPG, PNG)');
+});
diff --git a/tests/src/Rule/File/ImageHeightTest.php b/tests/src/Rule/File/ImageHeightTest.php
index e93b0b9..d402859 100644
--- a/tests/src/Rule/File/ImageHeightTest.php
+++ b/tests/src/Rule/File/ImageHeightTest.php
@@ -1,32 +1,24 @@
validator = new ImageHeight(array( 'min' => 400 ));
+});
- function setUp()
- {
- $this->validator = new ImageHeight(array('min' => 400));
- }
+test('missing files', function () {
+ $file = realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . 'file_that_does_not_exist.jpg';
+ expect($this->validator->validate($file))->toBeFalse();
+});
- function testMissingFiles()
- {
- $file = realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . 'file_that_does_not_exist.jpg';
- $this->assertFalse($this->validator->validate($file));
- }
+test('file', function () {
+ $file = realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . 'real_jpeg_file.jpg';
+ expect($this->validator->validate($file))->toBeTrue();
- function testFile()
- {
- $file = realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . 'real_jpeg_file.jpg';
- $this->assertTrue($this->validator->validate($file));
+ $file = realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . 'square_image.gif';
+ expect($this->validator->validate($file))->toBeFalse();
- $file = realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . 'square_image.gif';
- $this->assertFalse($this->validator->validate($file));
-
- // change minimum
- $this->validator->setOption(ImageHeight::OPTION_MIN, 200);
- $this->assertTrue($this->validator->validate($file));
- }
-
-}
+ // change minimum
+ $this->validator->setOption(ImageHeight::OPTION_MIN, 200);
+ expect($this->validator->validate($file))->toBeTrue();
+});
diff --git a/tests/src/Rule/File/ImageRatioTest.php b/tests/src/Rule/File/ImageRatioTest.php
index 57d1313..4e1da1a 100644
--- a/tests/src/Rule/File/ImageRatioTest.php
+++ b/tests/src/Rule/File/ImageRatioTest.php
@@ -1,56 +1,50 @@
validator = new ImageRatio(array('ratio' => 1));
- }
-
- function testMissingFiles()
- {
- $file = realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . 'file_that_does_not_exist.jpg';
- $this->assertFalse($this->validator->validate($file));
- }
-
- function testSquare()
- {
- $file = realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . 'square_image.gif';
- $this->assertTrue($this->validator->validate($file));
- }
-
- function testAlmostSquare()
- {
- $file = realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . 'almost_square_image.gif';
- $this->assertFalse($this->validator->validate($file));
-
- // change the error margin
- $this->validator->setOption(ImageRatio::OPTION_ERROR_MARGIN, 0.2);
- $this->assertTrue($this->validator->validate($file));
- }
-
- function testRatioZero()
- {
- $this->validator->setOption(ImageRatio::OPTION_RATIO, 0);
- $file = realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . 'almost_square_image.gif';
- $this->assertTrue($this->validator->validate($file));
- }
-
- function testInvalidRatio()
- {
- $this->validator->setOption(ImageRatio::OPTION_RATIO, 'abc');
- $file = realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . 'almost_square_image.gif';
- $this->assertTrue($this->validator->validate($file));
- }
-
- function testRatioAsString()
- {
- $this->validator->setOption(ImageRatio::OPTION_RATIO, '4:3');
- $file = realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . '4_by_3_image.jpg';
- $this->assertTrue($this->validator->validate($file));
- }
-
-}
+use \Sirius\Validation\Rule\File\ImageRatio;
+
+beforeEach(function () {
+ $this->validator = new ImageRatio(array( 'ratio' => 1 ));
+});
+
+test('missing files', function () {
+ $file = realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . 'file_that_does_not_exist.jpg';
+ expect($this->validator->validate($file))->toBeFalse();
+});
+
+test('square', function () {
+ $file = realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . 'square_image.gif';
+ expect($this->validator->validate($file))->toBeTrue();
+});
+
+test('almost square', function () {
+ $file = realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . 'almost_square_image.gif';
+ expect($this->validator->validate($file))->toBeFalse();
+
+ // change the error margin
+ $this->validator->setOption(ImageRatio::OPTION_ERROR_MARGIN, 0.2);
+ expect($this->validator->validate($file))->toBeTrue();
+});
+
+test('ratio zero', function () {
+ $this->validator->setOption(ImageRatio::OPTION_RATIO, 0);
+ $file = realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . 'almost_square_image.gif';
+ expect($this->validator->validate($file))->toBeTrue();
+});
+
+test('invalid ratio', function () {
+ $this->validator->setOption(ImageRatio::OPTION_RATIO, 'abc');
+ $file = realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . 'almost_square_image.gif';
+ expect($this->validator->validate($file))->toBeTrue();
+});
+
+test('ratio as string', function () {
+ $this->validator->setOption(ImageRatio::OPTION_RATIO, '4:3');
+ $file = realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . '4_by_3_image.jpg';
+ expect($this->validator->validate($file))->toBeTrue();
+});
+
+test('file not an image', function () {
+ $this->validator->setOption(ImageRatio::OPTION_RATIO, '4:3');
+ $file = realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . 'corrupt_image.jpg';
+ expect($this->validator->validate($file))->toBeFalse();
+});
diff --git a/tests/src/Rule/File/ImageTest.php b/tests/src/Rule/File/ImageTest.php
index ad1cc32..c754496 100644
--- a/tests/src/Rule/File/ImageTest.php
+++ b/tests/src/Rule/File/ImageTest.php
@@ -1,49 +1,37 @@
validator = new Image();
- }
-
- function testMissingFiles()
- {
- $file = realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . 'file_that_does_not_exist.jpg';
- $this->assertFalse($this->validator->validate($file));
- }
-
- function testRealImage()
- {
- $this->validator->setOption(Extension::OPTION_ALLOWED_EXTENSIONS, array('jpg'));
- $file = realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . 'real_jpeg_file.jpg';
- $this->assertTrue($this->validator->validate($file));
- }
-
- function testFakeImage()
- {
- $this->validator->setOption(Extension::OPTION_ALLOWED_EXTENSIONS, array('jpg'));
- $file = realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . 'fake_jpeg_file.jpg';
- $this->assertFalse($this->validator->validate($file));
- }
-
- function testExtensionsAsString()
- {
- $this->validator->setOption(Extension::OPTION_ALLOWED_EXTENSIONS, 'GIF, jpg');
- $file = realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . 'real_jpeg_file.jpg';
- $this->assertTrue($this->validator->validate($file));
- }
-
- function testPotentialMessage()
- {
- $this->validator->setOption(Extension::OPTION_ALLOWED_EXTENSIONS, array('jpg', 'png'));
- $this->validator->validate('no_file.jpg');
- $this->assertEquals(
- 'The file is not a valid image (only JPG, PNG are allowed)',
- (string)$this->validator->getPotentialMessage()
- );
- }
-}
+use \Sirius\Validation\Rule\File\Extension;
+use \Sirius\Validation\Rule\File\Image;
+
+beforeEach(function () {
+ $this->validator = new Image();
+});
+
+test('missing files', function () {
+ $file = realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . 'file_that_does_not_exist.jpg';
+ expect($this->validator->validate($file))->toBeFalse();
+});
+
+test('real image', function () {
+ $this->validator->setOption(Extension::OPTION_ALLOWED_EXTENSIONS, array( 'jpg' ));
+ $file = realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . 'real_jpeg_file.jpg';
+ expect($this->validator->validate($file))->toBeTrue();
+});
+
+test('fake image', function () {
+ $this->validator->setOption(Extension::OPTION_ALLOWED_EXTENSIONS, array( 'jpg' ));
+ $file = realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . 'fake_jpeg_file.jpg';
+ expect($this->validator->validate($file))->toBeFalse();
+});
+
+test('extensions as string', function () {
+ $this->validator->setOption(Extension::OPTION_ALLOWED_EXTENSIONS, 'GIF, jpg');
+ $file = realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . 'real_jpeg_file.jpg';
+ expect($this->validator->validate($file))->toBeTrue();
+});
+
+test('potential message', function () {
+ $this->validator->setOption(Extension::OPTION_ALLOWED_EXTENSIONS, array( 'jpg', 'png' ));
+ $this->validator->validate('no_file.jpg');
+ expect((string) $this->validator->getPotentialMessage())->toEqual('The file is not a valid image (only JPG, PNG are allowed)');
+});
diff --git a/tests/src/Rule/File/ImageWidthTest.php b/tests/src/Rule/File/ImageWidthTest.php
index 7d3602a..5c8fd11 100644
--- a/tests/src/Rule/File/ImageWidthTest.php
+++ b/tests/src/Rule/File/ImageWidthTest.php
@@ -1,32 +1,24 @@
validator = new ImageWidth(array( 'min' => 500 ));
+});
- function setUp()
- {
- $this->validator = new ImageWidth(array('min' => 500));
- }
+test('missing files', function () {
+ $file = realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . 'file_that_does_not_exist.jpg';
+ expect($this->validator->validate($file))->toBeFalse();
+});
- function testMissingFiles()
- {
- $file = realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . 'file_that_does_not_exist.jpg';
- $this->assertFalse($this->validator->validate($file));
- }
+test('file', function () {
+ $file = realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . 'real_jpeg_file.jpg';
+ expect($this->validator->validate($file))->toBeTrue();
- function testFile()
- {
- $file = realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . 'real_jpeg_file.jpg';
- $this->assertTrue($this->validator->validate($file));
+ $file = realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . 'square_image.gif';
+ expect($this->validator->validate($file))->toBeFalse();
- $file = realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . 'square_image.gif';
- $this->assertFalse($this->validator->validate($file));
-
- // change minimum
- $this->validator->setOption(ImageWidth::OPTION_MIN, 200);
- $this->assertTrue($this->validator->validate($file));
- }
-
-}
+ // change minimum
+ $this->validator->setOption(ImageWidth::OPTION_MIN, 200);
+ expect($this->validator->validate($file))->toBeTrue();
+});
diff --git a/tests/src/Rule/File/SizeTest.php b/tests/src/Rule/File/SizeTest.php
index f0270b0..810bdaf 100644
--- a/tests/src/Rule/File/SizeTest.php
+++ b/tests/src/Rule/File/SizeTest.php
@@ -1,39 +1,31 @@
validator = new Size(array('size' => '1M'));
- }
-
- function testMissingFiles()
- {
- $file = realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . 'file_that_does_not_exist.jpg';
- $this->assertFalse($this->validator->validate($file));
- }
-
- function testFile()
- {
- $file = realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . 'real_jpeg_file.jpg';
- $this->assertTrue($this->validator->validate($file));
-
- // change size
- $this->validator->setOption(Size::OPTION_SIZE, '10K');
- $this->assertFalse($this->validator->validate($file));
- }
-
- function testSizeAsNumber()
- {
- $file = realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . 'real_jpeg_file.jpg';
- $this->validator->setOption(Size::OPTION_SIZE, 1000000000000);
- $this->assertTrue($this->validator->validate($file));
-
- // change size
- $this->validator->setOption(Size::OPTION_SIZE, 10000);
- $this->assertFalse($this->validator->validate($file));
- }
-}
+use \Sirius\Validation\Rule\File\Size;
+
+beforeEach(function () {
+ $this->validator = new Size(array( 'size' => '1M' ));
+});
+
+test('missing files', function () {
+ $file = realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . 'file_that_does_not_exist.jpg';
+ expect($this->validator->validate($file))->toBeFalse();
+});
+
+test('file', function () {
+ $file = realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . 'real_jpeg_file.jpg';
+ expect($this->validator->validate($file))->toBeTrue();
+
+ // change size
+ $this->validator->setOption(Size::OPTION_SIZE, '10K');
+ expect($this->validator->validate($file))->toBeFalse();
+});
+
+test('size as number', function () {
+ $file = realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . 'real_jpeg_file.jpg';
+ $this->validator->setOption(Size::OPTION_SIZE, 1000000000000);
+ expect($this->validator->validate($file))->toBeTrue();
+
+ // change size
+ $this->validator->setOption(Size::OPTION_SIZE, 10000);
+ expect($this->validator->validate($file))->toBeFalse();
+});
diff --git a/tests/src/Rule/GreaterThanTest.php b/tests/src/Rule/GreaterThanTest.php
index 9849f8f..18a27ee 100755
--- a/tests/src/Rule/GreaterThanTest.php
+++ b/tests/src/Rule/GreaterThanTest.php
@@ -1,26 +1,39 @@
rule = new Rule();
- }
-
- function testExclusiveValidation()
- {
- $this->rule->setOption('inclusive', false);
- $this->rule->setOption('min', 100);
- $this->assertFalse($this->rule->validate(100));
- }
-
- function testValidationWithoutALimit()
- {
- $this->assertTrue($this->rule->validate(0));
- }
-}
+
+beforeEach(function () {
+ $this->rule = new Rule();
+});
+
+test('default options', function () {
+ expect($this->rule->getOption('min'))->toBeNull();
+ expect($this->rule->getOption('inclusive'))->toBeTrue();
+});
+
+test('exclusive validation', function () {
+ $this->rule->setOption('inclusive', false);
+ $this->rule->setOption('min', 100);
+ expect($this->rule->validate(100))->toBeFalse();
+});
+
+test('validation without a limit', function () {
+ expect($this->rule->validate(0))->toBeTrue();
+});
+
+test('construct csv format min zero and inclusive false', function () {
+ $this->rule = new Rule('0,false');
+ expect($this->rule->getOption('min'))->toBe('0');
+ expect($this->rule->getOption('inclusive'))->toBe(false);
+});
+
+test('construct with min value zero query string format', function () {
+ $this->rule = new Rule('min=0');
+ expect($this->rule->getOption('min'))->toBe('0');
+});
+
+test('construct with min value zero csv format', function () {
+ $this->rule = new Rule('0');
+ expect($this->rule->getOption('min'))->toBe('0');
+});
diff --git a/tests/src/Rule/InListTest.php b/tests/src/Rule/InListTest.php
index e8cf996..f4aba1a 100755
--- a/tests/src/Rule/InListTest.php
+++ b/tests/src/Rule/InListTest.php
@@ -1,19 +1,12 @@
rule = new Rule();
- }
+beforeEach(function () {
+ $this->rule = new Rule();
+});
- function testValidationWithoutALIstOfAcceptableValues()
- {
- $this->assertTrue($this->rule->validate('abc'));
- }
-}
+test('validation without a l ist of acceptable values', function () {
+ expect($this->rule->validate('abc'))->toBeTrue();
+});
diff --git a/tests/src/Rule/IntegerTest.php b/tests/src/Rule/IntegerTest.php
index c3cda25..cb20588 100644
--- a/tests/src/Rule/IntegerTest.php
+++ b/tests/src/Rule/IntegerTest.php
@@ -1,21 +1,14 @@
rule = new Rule();
- }
+beforeEach(function () {
+ $this->rule = new Rule();
+});
- function testValidation()
- {
- $this->assertTrue($this->rule->validate('0'));
- $this->assertTrue($this->rule->validate('10'));
- $this->assertFalse($this->rule->validate('10.3'));
- }
-}
+test('validation', function () {
+ expect($this->rule->validate('0'))->toBeTrue();
+ expect($this->rule->validate('10'))->toBeTrue();
+ expect($this->rule->validate('10.3'))->toBeFalse();
+});
diff --git a/tests/src/Rule/LessThanTest.php b/tests/src/Rule/LessThanTest.php
index 9ef5726..7393bef 100755
--- a/tests/src/Rule/LessThanTest.php
+++ b/tests/src/Rule/LessThanTest.php
@@ -1,47 +1,39 @@
rule = new Rule();
- }
-
- function testExclusiveValidation()
- {
- $this->rule->setOption('inclusive', false);
- $this->rule->setOption('max', 100);
- $this->assertFalse($this->rule->validate(100));
- }
-
- function testValidationWithoutALimit()
- {
- $this->assertTrue($this->rule->validate(0));
- }
-
- function testOptionNormalizationForHttpQueryString() {
- $this->rule = new Rule('max=100&inclusive=false');
- $this->assertFalse($this->rule->validate(100));
-
- $this->rule = new Rule('max=100&inclusive=true');
- $this->assertTrue($this->rule->validate(100));
- }
-
- function testOptionNormalizationForJsonString() {
- $this->rule = new Rule('{"max": 100, "inclusive": false}');
- $this->assertFalse($this->rule->validate(100));
- }
-
- function testOptionNormalizationForCsvString() {
- $this->rule = new Rule('100,false');
- $this->assertFalse($this->rule->validate(100));
-
- $this->rule = new Rule('100,true');
- $this->assertTrue($this->rule->validate(100));
- }
-}
+
+beforeEach(function () {
+ $this->rule = new Rule();
+});
+
+test('exclusive validation', function () {
+ $this->rule->setOption('inclusive', false);
+ $this->rule->setOption('max', 100);
+ expect($this->rule->validate(100))->toBeFalse();
+});
+
+test('validation without a limit', function () {
+ expect($this->rule->validate(0))->toBeTrue();
+});
+
+test('option normalization for http query string', function () {
+ $this->rule = new Rule('max=100&inclusive=false');
+ expect($this->rule->validate(100))->toBeFalse();
+
+ $this->rule = new Rule('max=100&inclusive=true');
+ expect($this->rule->validate(100))->toBeTrue();
+});
+
+test('option normalization for json string', function () {
+ $this->rule = new Rule('{"max": 100, "inclusive": false}');
+ expect($this->rule->validate(100))->toBeFalse();
+});
+
+test('option normalization for csv string', function () {
+ $this->rule = new Rule('100,false');
+ expect($this->rule->validate(100))->toBeFalse();
+
+ $this->rule = new Rule('100,true');
+ expect($this->rule->validate(100))->toBeTrue();
+});
diff --git a/tests/src/Rule/MatchTest.php b/tests/src/Rule/MatchTest.php
index 7355318..d545359 100644
--- a/tests/src/Rule/MatchTest.php
+++ b/tests/src/Rule/MatchTest.php
@@ -1,36 +1,27 @@
rule = new Rule();
- $this->rule->setContext(
- new ArrayWrapper(
- array(
- 'password' => 'secret'
- )
+beforeEach(function () {
+ $this->rule = new Rule();
+ $this->rule->setContext(
+ new ArrayWrapper(
+ array(
+ 'password' => 'secret'
)
- );
- }
-
- function testValidationWithItemPresent()
- {
- $this->rule->setOption(Rule::OPTION_ITEM, 'password');
- $this->assertTrue($this->rule->validate('secret'));
- $this->assertFalse($this->rule->validate('abc'));
- }
+ )
+ );
+});
- function testValidationWithoutItemPresent()
- {
- $this->assertTrue($this->rule->validate('abc'));
- $this->assertTrue($this->rule->validate(null));
- }
+test('validation with item present', function () {
+ $this->rule->setOption(Rule::OPTION_ITEM, 'password');
+ expect($this->rule->validate('secret'))->toBeTrue();
+ expect($this->rule->validate('abc'))->toBeFalse();
+});
-}
+test('validation without item present', function () {
+ expect($this->rule->validate('abc'))->toBeTrue();
+ expect($this->rule->validate(null))->toBeTrue();
+});
diff --git a/tests/src/Rule/NotEqualTest.php b/tests/src/Rule/NotEqualTest.php
new file mode 100644
index 0000000..113b6f0
--- /dev/null
+++ b/tests/src/Rule/NotEqualTest.php
@@ -0,0 +1,19 @@
+rule = new Rule();
+});
+
+test('validation with option set', function () {
+ $this->rule->setOption(Rule::OPTION_VALUE, '123');
+ expect($this->rule->validate('123'))->toBeFalse();
+ expect($this->rule->validate('abc'))->toBeTrue();
+});
+
+test('validation without option set', function () {
+ expect($this->rule->validate('abc'))->toBeFalse();
+ expect($this->rule->validate(null))->toBeFalse();
+});
diff --git a/tests/src/Rule/NotInListTest.php b/tests/src/Rule/NotInListTest.php
index 8c5384f..e9feeda 100755
--- a/tests/src/Rule/NotInListTest.php
+++ b/tests/src/Rule/NotInListTest.php
@@ -1,19 +1,12 @@
rule = new Rule();
- }
+beforeEach(function () {
+ $this->rule = new Rule();
+});
- function testValidationWithoutAListOfForbiddenValues()
- {
- $this->assertTrue($this->rule->validate('abc'));
- }
-}
+test('validation without a list of forbidden values', function () {
+ expect($this->rule->validate('abc'))->toBeTrue();
+});
diff --git a/tests/src/Rule/NotMatchTest.php b/tests/src/Rule/NotMatchTest.php
new file mode 100644
index 0000000..6b1ce49
--- /dev/null
+++ b/tests/src/Rule/NotMatchTest.php
@@ -0,0 +1,27 @@
+rule = new Rule();
+ $this->rule->setContext(
+ new ArrayWrapper(
+ array(
+ 'password' => 'secret'
+ )
+ )
+ );
+});
+
+test('validation with item present', function () {
+ $this->rule->setOption(Rule::OPTION_ITEM, 'password');
+ expect($this->rule->validate('secret'))->toBeFalse();
+ expect($this->rule->validate('abc'))->toBeTrue();
+});
+
+test('validation without item present', function () {
+ expect($this->rule->validate('abc'))->toBeFalse();
+ expect($this->rule->validate(null))->toBeFalse();
+});
diff --git a/tests/src/Rule/NumberTest.php b/tests/src/Rule/NumberTest.php
index ddf53fe..8db90d3 100644
--- a/tests/src/Rule/NumberTest.php
+++ b/tests/src/Rule/NumberTest.php
@@ -1,21 +1,14 @@
rule = new Rule();
- }
+beforeEach(function () {
+ $this->rule = new Rule();
+});
- function testValidation()
- {
- $this->assertTrue($this->rule->validate('0'));
- $this->assertTrue($this->rule->validate('0.3'));
- $this->assertFalse($this->rule->validate('0,3'));
- }
-}
+test('validation', function () {
+ expect($this->rule->validate('0'))->toBeTrue();
+ expect($this->rule->validate('0.3'))->toBeTrue();
+ expect($this->rule->validate('0,3'))->toBeFalse();
+});
diff --git a/tests/src/Rule/RegexTest.php b/tests/src/Rule/RegexTest.php
index e4b581e..6bb38a1 100755
--- a/tests/src/Rule/RegexTest.php
+++ b/tests/src/Rule/RegexTest.php
@@ -1,20 +1,13 @@
rule = new Rule();
- }
+beforeEach(function () {
+ $this->rule = new Rule();
+});
- function testValidationWithoutARegexPattern()
- {
- // pattern was not set, everything is valid
- $this->assertTrue($this->rule->validate('abc'));
- }
-}
+test('validation without a regex pattern', function () {
+ // pattern was not set, everything is valid
+ expect($this->rule->validate('abc'))->toBeTrue();
+});
diff --git a/tests/src/Rule/RequiredTest.php b/tests/src/Rule/RequiredTest.php
index 67f0e47..4bd9597 100644
--- a/tests/src/Rule/RequiredTest.php
+++ b/tests/src/Rule/RequiredTest.php
@@ -1,35 +1,21 @@
rule = new Rule();
- }
+beforeEach(function () {
+ $this->rule = new Rule();
+});
- function testValidationWithNull()
- {
- $this->assertFalse($this->rule->validate(null));
- }
+test('validation with null', function () {
+ expect($this->rule->validate(null))->toBeFalse();
+});
- function testValidationWithEmptyString()
- {
- $this->assertFalse($this->rule->validate(''));
- }
+test('validation with empty string', function () {
+ expect($this->rule->validate(''))->toBeFalse();
+});
- function testValidationWithWhitespaceString()
- {
- $this->assertTrue($this->rule->validate(' '));
- }
-}
+test('validation with whitespace string', function () {
+ expect($this->rule->validate(' '))->toBeTrue();
+});
diff --git a/tests/src/Rule/RequiredWhenTest.php b/tests/src/Rule/RequiredWhenTest.php
index aa5f975..d8d8ad6 100644
--- a/tests/src/Rule/RequiredWhenTest.php
+++ b/tests/src/Rule/RequiredWhenTest.php
@@ -1,89 +1,82 @@
rule = new Rule();
- }
+beforeEach(function () {
+ $this->rule = new Rule();
+});
- function testValidationWithItemValid()
- {
- $this->rule->setOption(Rule::OPTION_ITEM, 'email');
- $this->rule->setOption(Rule::OPTION_RULE, 'Email');
- $this->rule->setContext(
- new ArrayWrapper(
- array(
- 'email' => 'me@domain.com'
- )
+test('validation with item valid', function () {
+ $this->rule->setOption(Rule::OPTION_ITEM, 'email');
+ $this->rule->setOption(Rule::OPTION_RULE, 'Email');
+ $this->rule->setContext(
+ new ArrayWrapper(
+ array(
+ 'email' => 'me@domain.com'
)
- );
- $this->assertTrue($this->rule->validate('abc'));
- $this->assertFalse($this->rule->validate(null));
- }
+ )
+ );
+ expect($this->rule->validate('abc'))->toBeTrue();
+ expect($this->rule->validate(null))->toBeFalse();
+ expect($this->rule->validate(''))->toBeFalse();
+});
- function testValidationWithItemNotValid()
- {
- $this->rule->setOption(Rule::OPTION_ITEM, 'email');
- $this->rule->setOption(Rule::OPTION_RULE, 'Sirius\Validation\Rule\Email');
- $this->rule->setContext(
- new ArrayWrapper(
- array(
- 'email' => 'not_a_valid_email'
- )
+test('validation with item not valid', function () {
+ $this->rule->setOption(Rule::OPTION_ITEM, 'email');
+ $this->rule->setOption(Rule::OPTION_RULE, 'Sirius\Validation\Rule\Email');
+ $this->rule->setContext(
+ new ArrayWrapper(
+ array(
+ 'email' => 'not_a_valid_email'
)
- );
- $this->assertTrue($this->rule->validate('abc'));
- $this->assertTrue($this->rule->validate(null));
- }
+ )
+ );
+ expect($this->rule->validate('abc'))->toBeTrue();
+ expect($this->rule->validate(null))->toBeTrue();
+ expect($this->rule->validate(''))->toBeTrue();
+});
- function testValidationWithoutItem()
- {
- $this->rule->setOption(Rule::OPTION_RULE, 'Sirius\Validation\Rule\Email');
- $this->rule->setContext(
- new ArrayWrapper(
- array(
- 'email' => 'not_a_valid_email'
- )
+test('validation without item', function () {
+ $this->rule->setOption(Rule::OPTION_RULE, 'Sirius\Validation\Rule\Email');
+ $this->rule->setContext(
+ new ArrayWrapper(
+ array(
+ 'email' => 'not_a_valid_email'
)
- );
- $this->assertTrue($this->rule->validate('abc'));
- $this->assertTrue($this->rule->validate(null));
- }
+ )
+ );
+ expect($this->rule->validate('abc'))->toBeTrue();
+ expect($this->rule->validate(null))->toBeTrue();
+ expect($this->rule->validate(''))->toBeTrue();
+});
- function testItemRuleSetAsRuleObject()
- {
- $this->rule->setOption(Rule::OPTION_ITEM, 'email');
- $this->rule->setOption(Rule::OPTION_RULE, new \Sirius\Validation\Rule\Email);
- $this->rule->setContext(
- new ArrayWrapper(
- array(
- 'email' => 'me@domain.com'
- )
+test('item rule set as rule object', function () {
+ $this->rule->setOption(Rule::OPTION_ITEM, 'email');
+ $this->rule->setOption(Rule::OPTION_RULE, new \Sirius\Validation\Rule\Email);
+ $this->rule->setContext(
+ new ArrayWrapper(
+ array(
+ 'email' => 'me@domain.com'
)
- );
- $this->assertTrue($this->rule->validate('abc'));
- $this->assertFalse($this->rule->validate(null));
- }
+ )
+ );
+ expect($this->rule->validate('abc'))->toBeTrue();
+ expect($this->rule->validate(null))->toBeFalse();
+ expect($this->rule->validate(''))->toBeFalse();
+});
- function testExceptionThrownOnInvalidItemRule()
- {
- $this->setExpectedException('\InvalidArgumentException');
- $this->rule->setOption(Rule::OPTION_ITEM, 'email');
- $this->rule->setOption(Rule::OPTION_RULE, new \stdClass());
- $this->rule->setContext(
- new ArrayWrapper(
- array(
- 'email' => 'me@domain.com'
- )
+test('exception thrown on invalid item rule', function () {
+ $this->expectException('\InvalidArgumentException');
+ $this->rule->setOption(Rule::OPTION_ITEM, 'email');
+ $this->rule->setOption(Rule::OPTION_RULE, new \stdClass());
+ $this->rule->setContext(
+ new ArrayWrapper(
+ array(
+ 'email' => 'me@domain.com'
)
- );
- $this->assertTrue($this->rule->validate('abc'));
- }
-}
+ )
+ );
+ expect($this->rule->validate('abc'))->toBeTrue();
+});
diff --git a/tests/src/Rule/RequiredWithTest.php b/tests/src/Rule/RequiredWithTest.php
index db953e0..9e01bb7 100644
--- a/tests/src/Rule/RequiredWithTest.php
+++ b/tests/src/Rule/RequiredWithTest.php
@@ -1,57 +1,44 @@
rule = new Rule();
- $this->rule->setContext(
- new ArrayWrapper(
- array(
- 'item_1' => 'is_present'
- )
+beforeEach(function () {
+ $this->rule = new Rule();
+ $this->rule->setContext(
+ new ArrayWrapper(
+ array(
+ 'item_1' => 'is_present'
)
- );
- }
-
- function testValidationWithItemPresent()
- {
- $this->rule->setOption(Rule::OPTION_ITEM, 'item_1');
- $this->assertTrue($this->rule->validate('abc'));
- $this->assertFalse($this->rule->validate(null));
- }
-
- function testValidationWithoutItemPresent()
- {
- $this->rule->setOption(Rule::OPTION_ITEM, 'item_2');
- $this->assertTrue($this->rule->validate('abc'));
- $this->assertTrue($this->rule->validate(null));
- }
-
- function testValidationWithDeepItems()
- {
- $this->rule->setOption(Rule::OPTION_ITEM, 'lines[*][quantity]');
- $this->rule->setContext(new ArrayWrapper(
- array(
- 'lines' => array(
- 0 => array('quantity' => 10, 'price' => 10),
- 1 => array('quantity' => 20, 'price' => null),
- )
- ))
- );
- $this->assertTrue($this->rule->validate(10, 'lines[0][price]'));
- $this->assertFalse($this->rule->validate(null, 'lines[1][price]'));
- }
-
-}
+ )
+ );
+});
+
+test('validation with item present', function () {
+ $this->rule->setOption(Rule::OPTION_ITEM, 'item_1');
+ expect($this->rule->validate('abc'))->toBeTrue();
+ expect($this->rule->validate(null))->toBeFalse();
+ expect($this->rule->validate(''))->toBeFalse();
+});
+
+test('validation without item present', function () {
+ $this->rule->setOption(Rule::OPTION_ITEM, 'item_2');
+ expect($this->rule->validate('abc'))->toBeTrue();
+ expect($this->rule->validate(null))->toBeTrue();
+});
+
+test('validation with deep items', function () {
+ $this->rule->setOption(Rule::OPTION_ITEM, 'lines[*][quantity]');
+ $this->rule->setContext(new ArrayWrapper(
+ array(
+ 'lines' => array(
+ 0 => array( 'quantity' => 10, 'price' => 10 ),
+ 1 => array( 'quantity' => 20, 'price' => null ),
+ )
+ ))
+ );
+ expect($this->rule->validate(10, 'lines[0][price]'))->toBeTrue();
+ expect($this->rule->validate(null, 'lines[1][price]'))->toBeFalse();
+ expect($this->rule->validate('', 'lines[1][price]'))->toBeFalse();
+});
diff --git a/tests/src/Rule/RequiredWithoutTest.php b/tests/src/Rule/RequiredWithoutTest.php
index 1a2666e..836484a 100644
--- a/tests/src/Rule/RequiredWithoutTest.php
+++ b/tests/src/Rule/RequiredWithoutTest.php
@@ -1,56 +1,45 @@
rule = new Rule();
- $this->rule->setContext(
- new ArrayWrapper(
- array(
- 'item_1' => 'is_present'
- )
+beforeEach(function () {
+ $this->rule = new Rule();
+ $this->rule->setContext(
+ new ArrayWrapper(
+ array(
+ 'item_1' => 'is_present'
)
- );
- }
-
- function testValidationWithoutItemPresent()
- {
- $this->rule->setOption(Rule::OPTION_ITEM, 'item_2');
- $this->assertTrue($this->rule->validate('abc'));
- $this->assertFalse($this->rule->validate(null));
- }
-
- function testValidationWithItemPresent()
- {
- $this->rule->setOption(Rule::OPTION_ITEM, 'item_1');
- $this->assertTrue($this->rule->validate('abc'));
- $this->assertTrue($this->rule->validate(null));
- }
-
- function testValidationWithDeepItems()
- {
- $this->rule->setOption(Rule::OPTION_ITEM, 'lines[*][quantity]');
- $this->rule->setContext(new ArrayWrapper(
- array(
- 'lines' => array(
- 0 => array('quantity' => null, 'price' => null),
- 1 => array('quantity' => 20, 'price' => null),
- )
- ))
- );
- $this->assertFalse($this->rule->validate(null, 'lines[0][price]'));
- $this->assertTrue($this->rule->validate(null, 'lines[1][price]'));
- }
-}
+ )
+ );
+});
+
+test('validation without item present', function () {
+ $this->rule->setOption(Rule::OPTION_ITEM, 'item_2');
+ expect($this->rule->validate('abc'))->toBeTrue();
+ expect($this->rule->validate(null))->toBeFalse();
+ expect($this->rule->validate(''))->toBeFalse();
+});
+
+test('validation with item present', function () {
+ $this->rule->setOption(Rule::OPTION_ITEM, 'item_1');
+ expect($this->rule->validate('abc'))->toBeTrue();
+ expect($this->rule->validate(null))->toBeTrue();
+ expect($this->rule->validate(''))->toBeTrue();
+});
+
+test('validation with deep items', function () {
+ $this->rule->setOption(Rule::OPTION_ITEM, 'lines[*][quantity]');
+ $this->rule->setContext(new ArrayWrapper(
+ array(
+ 'lines' => array(
+ 0 => array( 'quantity' => null, 'price' => null ),
+ 1 => array( 'quantity' => 20, 'price' => null ),
+ )
+ ))
+ );
+ expect($this->rule->validate(null, 'lines[0][price]'))->toBeFalse();
+ expect($this->rule->validate(null, 'lines[1][price]'))->toBeTrue();
+ expect($this->rule->validate('', 'lines[1][price]'))->toBeTrue();
+});
diff --git a/tests/src/Rule/Upload/ExtensionTest.php b/tests/src/Rule/Upload/ExtensionTest.php
index 23c4a73..9c6f020 100644
--- a/tests/src/Rule/Upload/ExtensionTest.php
+++ b/tests/src/Rule/Upload/ExtensionTest.php
@@ -1,63 +1,62 @@
validator = new Extension();
+});
- function setUp()
- {
- $this->validator = new Extension();
- }
+test('existing files', function () {
+ $this->validator->setOption(Extension::OPTION_ALLOWED_EXTENSIONS, array( 'jpg' ));
+ $fileName = 'real_jpeg_file.jpg';
+ $file = array(
+ 'name' => $fileName,
+ 'type' => 'not_required',
+ 'size' => 'not_required',
+ 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
+ 'error' => UPLOAD_ERR_OK
+ );
+ expect($this->validator->validate($file))->toBeTrue();
+});
- function testExistingFiles()
- {
- $this->validator->setOption(Extension::OPTION_ALLOWED_EXTENSIONS, array('jpg'));
- $fileName = 'real_jpeg_file.jpg';
- $file = array(
- 'name' => $fileName,
- 'type' => 'not_required',
- 'size' => 'not_required',
- 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
- 'error' => UPLOAD_ERR_OK
- );
- $this->assertTrue($this->validator->validate($file));
- }
+test('no upload', function () {
+ $file = array(
+ 'name' => 'not_required',
+ 'type' => 'not_required',
+ 'size' => 'not_required',
+ 'tmp_name' => 'not_required',
+ 'error' => UPLOAD_ERR_NO_FILE
+ );
+ expect($this->validator->validate($file))->toBeTrue();
+});
- function testMissingFiles()
- {
- $this->validator->setOption(Extension::OPTION_ALLOWED_EXTENSIONS, array('jpg'));
- $fileName = 'file_that_does_not_exist.jpg';
- $file = array(
- 'name' => $fileName,
- 'type' => 'not_required',
- 'size' => 'not_required',
- 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
- 'error' => UPLOAD_ERR_OK
- );
- $this->assertFalse($this->validator->validate($file));
- }
+test('missing files', function () {
+ $this->validator->setOption(Extension::OPTION_ALLOWED_EXTENSIONS, array( 'jpg' ));
+ $fileName = 'file_that_does_not_exist.jpg';
+ $file = array(
+ 'name' => $fileName,
+ 'type' => 'not_required',
+ 'size' => 'not_required',
+ 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
+ 'error' => UPLOAD_ERR_OK
+ );
+ expect($this->validator->validate($file))->toBeFalse();
+});
- function testSetOptionAsString()
- {
- $this->validator->setOption(Extension::OPTION_ALLOWED_EXTENSIONS, 'jpg, GIF');
- $fileName = 'real_jpeg_file.jpg';
- $file = array(
- 'name' => $fileName,
- 'type' => 'not_required',
- 'size' => 'not_required',
- 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
- 'error' => UPLOAD_ERR_OK
- );
- $this->assertTrue($this->validator->validate($file));
- }
+test('set option as string', function () {
+ $this->validator->setOption(Extension::OPTION_ALLOWED_EXTENSIONS, 'jpg, GIF');
+ $fileName = 'real_jpeg_file.jpg';
+ $file = array(
+ 'name' => $fileName,
+ 'type' => 'not_required',
+ 'size' => 'not_required',
+ 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
+ 'error' => UPLOAD_ERR_OK
+ );
+ expect($this->validator->validate($file))->toBeTrue();
+});
- function testPotentialMessage()
- {
- $this->validator->setOption(Extension::OPTION_ALLOWED_EXTENSIONS, array('jpg', 'png'));
- $this->assertEquals(
- 'The file does not have an acceptable extension (JPG, PNG)',
- (string)$this->validator->getPotentialMessage()
- );
- }
-}
+test('potential message', function () {
+ $this->validator->setOption(Extension::OPTION_ALLOWED_EXTENSIONS, array( 'jpg', 'png' ));
+ expect((string) $this->validator->getPotentialMessage())->toEqual('The file does not have an acceptable extension (JPG, PNG)');
+});
diff --git a/tests/src/Rule/Upload/ImageHeightTest.php b/tests/src/Rule/Upload/ImageHeightTest.php
index 8937d7f..109e047 100644
--- a/tests/src/Rule/Upload/ImageHeightTest.php
+++ b/tests/src/Rule/Upload/ImageHeightTest.php
@@ -1,53 +1,56 @@
validator = new ImageHeight(array('min' => 400));
- }
-
- function testMissingFiles()
- {
- $fileName = 'file_that_does_not_exist.jpg';
- $file = array(
- 'name' => $fileName,
- 'type' => 'not_required',
- 'size' => 'not_required',
- 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
- 'error' => UPLOAD_ERR_OK
- );
- $this->assertFalse($this->validator->validate($file));
- }
-
- function testFile()
- {
- $fileName = 'real_jpeg_file.jpg';
- $file = array(
- 'name' => $fileName,
- 'type' => 'not_required',
- 'size' => 'not_required',
- 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
- 'error' => UPLOAD_ERR_OK
- );
- $this->assertTrue($this->validator->validate($file));
-
- $fileName = 'square_image.gif';
- $file = array(
- 'name' => $fileName,
- 'type' => 'not_required',
- 'size' => 'not_required',
- 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
- 'error' => UPLOAD_ERR_OK
- );
- $this->assertFalse($this->validator->validate($file));
-
- // change minimum
- $this->validator->setOption(ImageHeight::OPTION_MIN, 200);
- $this->assertTrue($this->validator->validate($file));
- }
-
-}
+use \Sirius\Validation\Rule\Upload\ImageHeight;
+
+beforeEach(function () {
+ $this->validator = new ImageHeight(array( 'min' => 400 ));
+});
+
+test('missing files', function () {
+ $fileName = 'file_that_does_not_exist.jpg';
+ $file = array(
+ 'name' => $fileName,
+ 'type' => 'not_required',
+ 'size' => 'not_required',
+ 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
+ 'error' => UPLOAD_ERR_OK
+ );
+ expect($this->validator->validate($file))->toBeFalse();
+});
+
+test('no upload', function () {
+ $file = array(
+ 'name' => 'not_required',
+ 'type' => 'not_required',
+ 'size' => 'not_required',
+ 'tmp_name' => 'not_required',
+ 'error' => UPLOAD_ERR_NO_FILE
+ );
+ expect($this->validator->validate($file))->toBeTrue();
+});
+
+test('file', function () {
+ $fileName = 'real_jpeg_file.jpg';
+ $file = array(
+ 'name' => $fileName,
+ 'type' => 'not_required',
+ 'size' => 'not_required',
+ 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
+ 'error' => UPLOAD_ERR_OK
+ );
+ expect($this->validator->validate($file))->toBeTrue();
+
+ $fileName = 'square_image.gif';
+ $file = array(
+ 'name' => $fileName,
+ 'type' => 'not_required',
+ 'size' => 'not_required',
+ 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
+ 'error' => UPLOAD_ERR_OK
+ );
+ expect($this->validator->validate($file))->toBeFalse();
+
+ // change minimum
+ $this->validator->setOption(ImageHeight::OPTION_MIN, 200);
+ expect($this->validator->validate($file))->toBeTrue();
+});
diff --git a/tests/src/Rule/Upload/ImageRatioTest.php b/tests/src/Rule/Upload/ImageRatioTest.php
index f34d079..d47f674 100644
--- a/tests/src/Rule/Upload/ImageRatioTest.php
+++ b/tests/src/Rule/Upload/ImageRatioTest.php
@@ -1,98 +1,110 @@
validator = new ImageRatio(array( 'ratio' => 1 ));
+});
- function setUp()
- {
- $this->validator = new ImageRatio(array('ratio' => 1));
- }
+test('missing files', function () {
+ $fileName = 'file_that_does_not_exist.gif';
+ $file = array(
+ 'name' => $fileName,
+ 'type' => 'not_required',
+ 'size' => 'not_required',
+ 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
+ 'error' => UPLOAD_ERR_OK
+ );
+ expect($this->validator->validate($file))->toBeFalse();
+});
- function testMissingFiles()
- {
- $fileName = 'file_that_does_not_exist.gif';
- $file = array(
- 'name' => $fileName,
- 'type' => 'not_required',
- 'size' => 'not_required',
- 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
- 'error' => UPLOAD_ERR_OK
- );
- $this->assertFalse($this->validator->validate($file));
- }
+test('no upload', function () {
+ $file = array(
+ 'name' => 'not_required',
+ 'type' => 'not_required',
+ 'size' => 'not_required',
+ 'tmp_name' => 'not_required',
+ 'error' => UPLOAD_ERR_NO_FILE
+ );
+ expect($this->validator->validate($file))->toBeTrue();
+});
- function testSquare()
- {
- $fileName = 'square_image.gif';
- $file = array(
- 'name' => $fileName,
- 'type' => 'not_required',
- 'size' => 'not_required',
- 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
- 'error' => UPLOAD_ERR_OK
- );
- $this->assertTrue($this->validator->validate($file));
- }
+test('square', function () {
+ $fileName = 'square_image.gif';
+ $file = array(
+ 'name' => $fileName,
+ 'type' => 'not_required',
+ 'size' => 'not_required',
+ 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
+ 'error' => UPLOAD_ERR_OK
+ );
+ expect($this->validator->validate($file))->toBeTrue();
+});
- function testAlmostSquare()
- {
- $fileName = 'almost_square_image.gif';
- $file = array(
- 'name' => $fileName,
- 'type' => 'not_required',
- 'size' => 'not_required',
- 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
- 'error' => UPLOAD_ERR_OK
- );
- $this->assertFalse($this->validator->validate($file));
+test('almost square', function () {
+ $fileName = 'almost_square_image.gif';
+ $file = array(
+ 'name' => $fileName,
+ 'type' => 'not_required',
+ 'size' => 'not_required',
+ 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
+ 'error' => UPLOAD_ERR_OK
+ );
+ expect($this->validator->validate($file))->toBeFalse();
- // change the error margin
- $this->validator->setOption(ImageRatio::OPTION_ERROR_MARGIN, 0.2);
- $this->assertTrue($this->validator->validate($file));
- }
+ // change the error margin
+ $this->validator->setOption(ImageRatio::OPTION_ERROR_MARGIN, 0.2);
+ expect($this->validator->validate($file))->toBeTrue();
+});
- function testRatioZero()
- {
- $this->validator->setOption(ImageRatio::OPTION_RATIO, 0);
- $fileName = 'almost_square_image.gif';
- $file = array(
- 'name' => $fileName,
- 'type' => 'not_required',
- 'size' => 'not_required',
- 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
- 'error' => UPLOAD_ERR_OK
- );
- $this->assertTrue($this->validator->validate($file));
- }
+test('ratio zero', function () {
+ $this->validator->setOption(ImageRatio::OPTION_RATIO, 0);
+ $fileName = 'almost_square_image.gif';
+ $file = array(
+ 'name' => $fileName,
+ 'type' => 'not_required',
+ 'size' => 'not_required',
+ 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
+ 'error' => UPLOAD_ERR_OK
+ );
+ expect($this->validator->validate($file))->toBeTrue();
+});
- function testInvalidRatio()
- {
- $this->validator->setOption(ImageRatio::OPTION_RATIO, 'abc');
- $fileName = 'almost_square_image.gif';
- $file = array(
- 'name' => $fileName,
- 'type' => 'not_required',
- 'size' => 'not_required',
- 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
- 'error' => UPLOAD_ERR_OK
- );
- $this->assertTrue($this->validator->validate($file));
- }
+test('invalid ratio', function () {
+ $this->validator->setOption(ImageRatio::OPTION_RATIO, 'abc');
+ $fileName = 'almost_square_image.gif';
+ $file = array(
+ 'name' => $fileName,
+ 'type' => 'not_required',
+ 'size' => 'not_required',
+ 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
+ 'error' => UPLOAD_ERR_OK
+ );
+ expect($this->validator->validate($file))->toBeTrue();
+});
- function testRatioAsString()
- {
- $this->validator->setOption(ImageRatio::OPTION_RATIO, '4:3');
- $fileName = '4_by_3_image.jpg';
- $file = array(
- 'name' => $fileName,
- 'type' => 'not_required',
- 'size' => 'not_required',
- 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
- 'error' => UPLOAD_ERR_OK
- );
- $this->assertTrue($this->validator->validate($file));
- }
+test('ratio as string', function () {
+ $this->validator->setOption(ImageRatio::OPTION_RATIO, '4:3');
+ $fileName = '4_by_3_image.jpg';
+ $file = array(
+ 'name' => $fileName,
+ 'type' => 'not_required',
+ 'size' => 'not_required',
+ 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
+ 'error' => UPLOAD_ERR_OK
+ );
+ expect($this->validator->validate($file))->toBeTrue();
+});
-}
+test('file not an image', function () {
+ $this->validator->setOption(ImageRatio::OPTION_RATIO, '4:3');
+ $fileName = 'corrupt_image.jpg';
+ $file = array(
+ 'name' => $fileName,
+ 'type' => 'not_required',
+ 'size' => 'not_required',
+ 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
+ 'error' => UPLOAD_ERR_OK
+ );
+ expect($this->validator->validate($file))->toBeFalse();
+});
diff --git a/tests/src/Rule/Upload/ImageTest.php b/tests/src/Rule/Upload/ImageTest.php
index 4c2b99b..bf1b93f 100644
--- a/tests/src/Rule/Upload/ImageTest.php
+++ b/tests/src/Rule/Upload/ImageTest.php
@@ -1,76 +1,75 @@
validator = new Image();
+});
- function setUp()
- {
- $this->validator = new Image();
- }
+test('missing files', function () {
+ $fileName = 'file_that_does_not_exist.jpg';
+ $file = array(
+ 'name' => $fileName,
+ 'type' => 'not_required',
+ 'size' => 'not_required',
+ 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
+ 'error' => UPLOAD_ERR_OK
+ );
+ expect($this->validator->validate($file))->toBeFalse();
+});
- function testMissingFiles()
- {
- $fileName = 'file_that_does_not_exist.jpg';
- $file = array(
- 'name' => $fileName,
- 'type' => 'not_required',
- 'size' => 'not_required',
- 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
- 'error' => UPLOAD_ERR_OK
- );
- $this->assertFalse($this->validator->validate($file));
- }
+test('no upload', function () {
+ $file = array(
+ 'name' => 'not_required',
+ 'type' => 'not_required',
+ 'size' => 'not_required',
+ 'tmp_name' => 'not_required',
+ 'error' => UPLOAD_ERR_NO_FILE
+ );
+ expect($this->validator->validate($file))->toBeTrue();
+});
- function testRealImage()
- {
- $this->validator->setOption(Extension::OPTION_ALLOWED_EXTENSIONS, array('jpg'));
- $fileName = 'real_jpeg_file.jpg';
- $file = array(
- 'name' => $fileName,
- 'type' => 'not_required',
- 'size' => 'not_required',
- 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
- 'error' => UPLOAD_ERR_OK
- );
- $this->assertTrue($this->validator->validate($file));
- }
+test('real image', function () {
+ $this->validator->setOption(Extension::OPTION_ALLOWED_EXTENSIONS, array( 'jpg' ));
+ $fileName = 'real_jpeg_file.jpg';
+ $file = array(
+ 'name' => $fileName,
+ 'type' => 'not_required',
+ 'size' => 'not_required',
+ 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
+ 'error' => UPLOAD_ERR_OK
+ );
+ expect($this->validator->validate($file))->toBeTrue();
+});
- function testFakeImage()
- {
- $this->validator->setOption(Extension::OPTION_ALLOWED_EXTENSIONS, array('jpg'));
- $fileName = 'fake_jpeg_file.jpg';
- $file = array(
- 'name' => $fileName,
- 'type' => 'not_required',
- 'size' => 'not_required',
- 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
- 'error' => UPLOAD_ERR_OK
- );
- $this->assertFalse($this->validator->validate($file));
- }
+test('fake image', function () {
+ $this->validator->setOption(Extension::OPTION_ALLOWED_EXTENSIONS, array( 'jpg' ));
+ $fileName = 'fake_jpeg_file.jpg';
+ $file = array(
+ 'name' => $fileName,
+ 'type' => 'not_required',
+ 'size' => 'not_required',
+ 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
+ 'error' => UPLOAD_ERR_OK
+ );
+ expect($this->validator->validate($file))->toBeFalse();
+});
- function testExtensionsAsString()
- {
- $this->validator->setOption(Extension::OPTION_ALLOWED_EXTENSIONS, 'GIF, jpg');
- $fileName = 'real_jpeg_file.jpg';
- $file = array(
- 'name' => $fileName,
- 'type' => 'not_required',
- 'size' => 'not_required',
- 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
- 'error' => UPLOAD_ERR_OK
- );
- $this->assertTrue($this->validator->validate($file));
- }
+test('extensions as string', function () {
+ $this->validator->setOption(Extension::OPTION_ALLOWED_EXTENSIONS, 'GIF, jpg');
+ $fileName = 'real_jpeg_file.jpg';
+ $file = array(
+ 'name' => $fileName,
+ 'type' => 'not_required',
+ 'size' => 'not_required',
+ 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
+ 'error' => UPLOAD_ERR_OK
+ );
+ expect($this->validator->validate($file))->toBeTrue();
+});
- function testPotentialMessage()
- {
- $this->validator->setOption(Extension::OPTION_ALLOWED_EXTENSIONS, array('jpg', 'png'));
- $this->assertEquals(
- 'The file is not a valid image (only JPG, PNG are allowed)',
- (string)$this->validator->getPotentialMessage()
- );
- }
-}
+test('potential message', function () {
+ $this->validator->setOption(Extension::OPTION_ALLOWED_EXTENSIONS, array( 'jpg', 'png' ));
+ expect((string) $this->validator->getPotentialMessage())->toEqual('The file is not a valid image (only JPG, PNG are allowed)');
+});
diff --git a/tests/src/Rule/Upload/ImageWidthTest.php b/tests/src/Rule/Upload/ImageWidthTest.php
index a7de83b..eaf7eb0 100644
--- a/tests/src/Rule/Upload/ImageWidthTest.php
+++ b/tests/src/Rule/Upload/ImageWidthTest.php
@@ -1,53 +1,56 @@
validator = new ImageWidth(array('min' => 500));
- }
-
- function testMissingFiles()
- {
- $fileName = 'file_that_does_not_exist.jpg';
- $file = array(
- 'name' => $fileName,
- 'type' => 'not_required',
- 'size' => 'not_required',
- 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
- 'error' => UPLOAD_ERR_OK
- );
- $this->assertFalse($this->validator->validate($file));
- }
-
- function testFile()
- {
- $fileName = 'real_jpeg_file.jpg';
- $file = array(
- 'name' => $fileName,
- 'type' => 'not_required',
- 'size' => 'not_required',
- 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
- 'error' => UPLOAD_ERR_OK
- );
- $this->assertTrue($this->validator->validate($file));
-
- $fileName = 'square_image.gif';
- $file = array(
- 'name' => $fileName,
- 'type' => 'not_required',
- 'size' => 'not_required',
- 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
- 'error' => UPLOAD_ERR_OK
- );
- $this->assertFalse($this->validator->validate($file));
-
- // change minimum
- $this->validator->setOption(ImageWidth::OPTION_MIN, 200);
- $this->assertTrue($this->validator->validate($file));
- }
-
-}
+use \Sirius\Validation\Rule\Upload\ImageWidth;
+
+beforeEach(function () {
+ $this->validator = new ImageWidth(array( 'min' => 500 ));
+});
+
+test('missing files', function () {
+ $fileName = 'file_that_does_not_exist.jpg';
+ $file = array(
+ 'name' => $fileName,
+ 'type' => 'not_required',
+ 'size' => 'not_required',
+ 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
+ 'error' => UPLOAD_ERR_OK
+ );
+ expect($this->validator->validate($file))->toBeFalse();
+});
+
+test('no upload', function () {
+ $file = array(
+ 'name' => 'not_required',
+ 'type' => 'not_required',
+ 'size' => 'not_required',
+ 'tmp_name' => 'not_required',
+ 'error' => UPLOAD_ERR_NO_FILE
+ );
+ expect($this->validator->validate($file))->toBeTrue();
+});
+
+test('file', function () {
+ $fileName = 'real_jpeg_file.jpg';
+ $file = array(
+ 'name' => $fileName,
+ 'type' => 'not_required',
+ 'size' => 'not_required',
+ 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
+ 'error' => UPLOAD_ERR_OK
+ );
+ expect($this->validator->validate($file))->toBeTrue();
+
+ $fileName = 'square_image.gif';
+ $file = array(
+ 'name' => $fileName,
+ 'type' => 'not_required',
+ 'size' => 'not_required',
+ 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
+ 'error' => UPLOAD_ERR_OK
+ );
+ expect($this->validator->validate($file))->toBeFalse();
+
+ // change minimum
+ $this->validator->setOption(ImageWidth::OPTION_MIN, 200);
+ expect($this->validator->validate($file))->toBeTrue();
+});
diff --git a/tests/src/Rule/Upload/RequiredTest.php b/tests/src/Rule/Upload/RequiredTest.php
new file mode 100644
index 0000000..fc52395
--- /dev/null
+++ b/tests/src/Rule/Upload/RequiredTest.php
@@ -0,0 +1,66 @@
+validator = new Required();
+});
+
+test('missing files', function () {
+ $fileName = 'file_that_does_not_exist.jpg';
+ $file = array(
+ 'name' => $fileName,
+ 'type' => 'not_required',
+ 'size' => 'not_required',
+ 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
+ 'error' => UPLOAD_ERR_OK
+ );
+ expect($this->validator->validate($file))->toBeFalse();
+});
+
+test('upload ok', function () {
+ $fileName = 'real_jpeg_file.jpg';
+ $file = array(
+ 'name' => $fileName,
+ 'type' => 'not_required',
+ 'size' => 'not_required',
+ 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
+ 'error' => UPLOAD_ERR_OK
+ );
+ expect($this->validator->validate($file))->toBeTrue();
+});
+
+test('upload not ok', function () {
+ $fileName = 'real_jpeg_file.jpg';
+ $file = array(
+ 'name' => $fileName,
+ 'type' => 'not_required',
+ 'size' => 'not_required',
+ 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
+ 'error' => UPLOAD_ERR_PARTIAL
+ );
+ expect($this->validator->validate($file))->toBeFalse();
+});
+
+test('no upload', function () {
+ $file = array(
+ 'name' => 'not_required',
+ 'type' => 'not_required',
+ 'size' => 'not_required',
+ 'tmp_name' => 'not_required',
+ 'error' => UPLOAD_ERR_NO_FILE
+ );
+ expect($this->validator->validate($file))->toBeFalse();
+});
+
+test('file', function () {
+ $fileName = 'real_jpeg_file.jpg';
+ $file = array(
+ 'name' => $fileName,
+ 'type' => 'not_required',
+ 'size' => 'not_required',
+ 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
+ 'error' => UPLOAD_ERR_OK
+ );
+ expect($this->validator->validate($file))->toBeTrue();
+});
diff --git a/tests/src/Rule/Upload/SizeTest.php b/tests/src/Rule/Upload/SizeTest.php
index 35546a9..66f86f0 100644
--- a/tests/src/Rule/Upload/SizeTest.php
+++ b/tests/src/Rule/Upload/SizeTest.php
@@ -1,60 +1,63 @@
validator = new Size(array('size' => '1M'));
- }
-
- function testMissingFiles()
- {
- $fileName = 'file_that_does_not_exist.jpg';
- $file = array(
- 'name' => $fileName,
- 'type' => 'not_required',
- 'size' => 'not_required',
- 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
- 'error' => UPLOAD_ERR_OK
- );
- $this->assertFalse($this->validator->validate($file));
- }
-
- function testFile()
- {
- $fileName = 'real_jpeg_file.jpg';
- $file = array(
- 'name' => $fileName,
- 'type' => 'not_required',
- 'size' => 'not_required',
- 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
- 'error' => UPLOAD_ERR_OK
- );
- $this->assertTrue($this->validator->validate($file));
-
- // change size
- $this->validator->setOption(Size::OPTION_SIZE, '10K');
- $this->assertFalse($this->validator->validate($file));
- }
-
- function testSizeAsNumber()
- {
- $fileName = 'real_jpeg_file.jpg';
- $file = array(
- 'name' => $fileName,
- 'type' => 'not_required',
- 'size' => 'not_required',
- 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
- 'error' => UPLOAD_ERR_OK
- );
- $this->validator->setOption(Size::OPTION_SIZE, 1000000000000);
- $this->assertTrue($this->validator->validate($file));
-
- // change size
- $this->validator->setOption(Size::OPTION_SIZE, 10000);
- $this->assertFalse($this->validator->validate($file));
- }
-}
+use \Sirius\Validation\Rule\Upload\Size;
+
+beforeEach(function () {
+ $this->validator = new Size(array( 'size' => '1M' ));
+});
+
+
+test('missing files', function () {
+ $fileName = 'file_that_does_not_exist.jpg';
+ $file = array(
+ 'name' => $fileName,
+ 'type' => 'not_required',
+ 'size' => 'not_required',
+ 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
+ 'error' => UPLOAD_ERR_OK
+ );
+ expect($this->validator->validate($file))->toBeFalse();
+});
+
+test('no upload', function () {
+ $file = array(
+ 'name' => 'not_required',
+ 'type' => 'not_required',
+ 'size' => 'not_required',
+ 'tmp_name' => 'not_required',
+ 'error' => UPLOAD_ERR_NO_FILE
+ );
+ expect($this->validator->validate($file))->toBeTrue();
+});
+
+test('file', function () {
+ $fileName = 'real_jpeg_file.jpg';
+ $file = array(
+ 'name' => $fileName,
+ 'type' => 'not_required',
+ 'size' => 'not_required',
+ 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
+ 'error' => UPLOAD_ERR_OK
+ );
+ expect($this->validator->validate($file))->toBeTrue();
+
+ // change size
+ $this->validator->setOption(Size::OPTION_SIZE, '10K');
+ expect($this->validator->validate($file))->toBeFalse();
+});
+
+test('size as number', function () {
+ $fileName = 'real_jpeg_file.jpg';
+ $file = array(
+ 'name' => $fileName,
+ 'type' => 'not_required',
+ 'size' => 'not_required',
+ 'tmp_name' => realpath(__DIR__ . '/../../../fixitures/') . DIRECTORY_SEPARATOR . $fileName,
+ 'error' => UPLOAD_ERR_OK
+ );
+ $this->validator->setOption(Size::OPTION_SIZE, 1000000000000);
+ expect($this->validator->validate($file))->toBeTrue();
+
+ // change size
+ $this->validator->setOption(Size::OPTION_SIZE, 10000);
+ expect($this->validator->validate($file))->toBeFalse();
+});
diff --git a/tests/src/Rule/UrlTest.php b/tests/src/Rule/UrlTest.php
new file mode 100644
index 0000000..5b9a4af
--- /dev/null
+++ b/tests/src/Rule/UrlTest.php
@@ -0,0 +1,13 @@
+rule = new Rule();
+});
+
+test('validation', function () {
+ expect($this->rule->validate(''))->toBeFalse();
+ expect($this->rule->validate('http://www.google.com'))->toBeTrue();
+});
diff --git a/tests/src/Rule/WebsiteTest.php b/tests/src/Rule/WebsiteTest.php
index 62f7448..9c0a970 100644
--- a/tests/src/Rule/WebsiteTest.php
+++ b/tests/src/Rule/WebsiteTest.php
@@ -1,19 +1,12 @@
rule = new Rule();
- }
+beforeEach(function () {
+ $this->rule = new Rule();
+});
- function testNonHttpAddresses()
- {
- $this->assertTrue($this->rule->validate('//google.com'));
- }
-}
+test('non http addresses', function () {
+ expect($this->rule->validate('//google.com'))->toBeTrue();
+});
diff --git a/tests/src/RuleCollectionTest.php b/tests/src/RuleCollectionTest.php
index 7868554..8019c44 100644
--- a/tests/src/RuleCollectionTest.php
+++ b/tests/src/RuleCollectionTest.php
@@ -1,35 +1,31 @@
collection = new RuleCollection();
- }
-
- function testAddAndRemove()
- {
- $this->collection->attach(new Rule\Required);
- $this->assertEquals(1, count($this->collection));
+beforeEach(function () {
+ $this->collection = new RuleCollection();
+});
- $this->collection->detach(new Rule\Required);
- $this->assertEquals(0, count($this->collection));
- }
+test('add and remove', function () {
+ $this->collection->attach(new Required());
+ expect(count($this->collection))->toEqual(1);
- function testIterator()
- {
- $this->collection->attach(new Rule\Email);
- $this->collection->attach(new Rule\Required);
+ $this->collection->detach(new Required());
+ expect(count($this->collection))->toEqual(0);
+});
- $rules = array();
- foreach ($this->collection as $k => $rule) {
- $rules[] = $rule;
- }
+test('iterator', function () {
+ $this->collection->attach(new Email);
+ $this->collection->attach(new Required);
- // the required rule should be first
- $this->assertTrue($rules[0] instanceof Rule\Required);
- $this->assertTrue($rules[1] instanceof Rule\Email);
+ $rules = array();
+ foreach ($this->collection as $k => $rule) {
+ $rules[] = $rule;
}
-}
+
+ // the required rule should be first
+ expect($rules[0] instanceof Required)->toBeTrue();
+ expect($rules[1] instanceof Email)->toBeTrue();
+});
diff --git a/tests/src/RuleFactoryTest.php b/tests/src/RuleFactoryTest.php
index 95611a1..2f4b03c 100644
--- a/tests/src/RuleFactoryTest.php
+++ b/tests/src/RuleFactoryTest.php
@@ -1,49 +1,40 @@
ruleFactory = new RuleFactory();
+});
- function setUp()
- {
- $this->ruleFactory = new RuleFactory();
- }
+test('registration of validator classes', function () {
+ $this->ruleFactory->register('even', TestingCustomRule::class);
- function testRegistrationOfValidatorClasses()
- {
- $this->ruleFactory->register('even', '\Sirius\Validation\TestingCustomRule');
+ $validator = $this->ruleFactory->createRule('even');
+ expect($validator instanceof TestingCustomRule)->toBeTrue();
+ expect($validator->validate(3))->toBeTrue();
+ expect($validator->validate(4))->toBeFalse();
+ expect((string)$validator->getMessage())->toEqual('Value is not valid');
+});
- $validator = $this->ruleFactory->createRule('even');
- $this->assertTrue($validator instanceof TestingCustomRule);
- $this->assertTrue($validator->validate(3));
- $this->assertFalse($validator->validate(4));
- $this->assertEquals('Value is not valid', (string)$validator->getMessage());
- }
+test('custom error messages', function () {
+ $this->ruleFactory->register('even', TestingCustomRule::class, 'This should be even',
+ '{label} should be even');
- function testCustomErrorMessages()
- {
- $this->ruleFactory->register('even', '\Sirius\Validation\TestingCustomRule', 'This should be even',
- '{label} should be even');
-
- $validatorWithLabel = $this->ruleFactory->createRule('even', null, null, 'Number');
- $validatorWithLabel->validate(4);
- $this->assertEquals('Number should be even', (string)$validatorWithLabel->getMessage());
-
- $validator = $validator = $this->ruleFactory->createRule('even');
- $validator->validate(4);
- $this->assertEquals('This should be even', (string)$validator->getMessage());
+ $validatorWithLabel = $this->ruleFactory->createRule('even', null, null, 'Number');
+ $validatorWithLabel->validate(4);
+ expect((string)$validatorWithLabel->getMessage())->toEqual('Number should be even');
- }
-}
+ $validator = $this->ruleFactory->createRule('even');
+ $validator->validate(4);
+ expect((string)$validator->getMessage())->toEqual('This should be even');
+});
diff --git a/tests/src/Util/ArrTest.php b/tests/src/Util/ArrTest.php
index a6461a4..5df11eb 100644
--- a/tests/src/Util/ArrTest.php
+++ b/tests/src/Util/ArrTest.php
@@ -1,139 +1,104 @@
data = array(
- 'name' => 'John Doe',
- 'addresses' => array(
- 'billing' => array(
- 'street' => '1st Ave'
- ),
- 'shipping' => array(
- 'street' => '1st Boulevar'
- )
+beforeEach(function () {
+ $this->data = array(
+ 'name' => 'John Doe',
+ 'addresses' => array(
+ 'billing' => array(
+ 'street' => '1st Ave'
+ ),
+ 'shipping' => array(
+ 'street' => '1st Boulevar'
)
- );
- }
-
+ )
+ );
+});
- function testOfArrayGetByPath()
- {
- $this->assertEquals(Arr::getByPath($this->data, 'name'), $this->data['name']);
- $this->assertEquals(
- Arr::getByPath($this->data, 'addresses[shipping][street]'),
- $this->data['addresses']['shipping']['street']
- );
- $this->assertEquals(Arr::getByPath($this->data, 'email'), null);
- $this->assertEquals(Arr::getByPath($this->data, 'address[shipping][street]'), null);
- }
+use \Sirius\Validation\Util\Arr;
- function testOfArrayGetByPathRoot()
- {
- $this->assertEquals($this->data, Arr::getByPath($this->data));
- }
+test('array get by path', function () {
+ expect($this->data['name'])->toEqual(Arr::getByPath($this->data, 'name'));
+ expect($this->data['addresses']['shipping']['street'])->toEqual(Arr::getByPath($this->data, 'addresses[shipping][street]'));
+ expect(null)->toEqual(Arr::getByPath($this->data, 'email'));
+ expect(null)->toEqual(Arr::getByPath($this->data, 'address[shipping][street]'));
+});
- function testOfArraySetByPath()
- {
- $this->data = Arr::setBySelector($this->data, 'email', 'my@domain.com');
- $this->assertEquals(Arr::getByPath($this->data, 'email'), 'my@domain.com');
+test('array get by path root', function () {
+ expect(Arr::getByPath($this->data))->toEqual($this->data);
+});
- $this->data = Arr::setBySelector($this->data, 'newsletters[offers]', true);
- $this->assertEquals(Arr::getByPath($this->data, 'newsletters'), array('offers' => true));
- $this->data = Arr::setBySelector($this->data, 'addresses[*][state]', 'California');
- $this->assertEquals(Arr::getByPath($this->data, 'addresses[shipping][state]'), 'California');
- $this->assertEquals(Arr::getByPath($this->data, 'addresses[billing][state]'), 'California');
- }
+test('array set by path', function () {
+ $this->data = Arr::setBySelector($this->data, 'email', 'my@domain.com');
+ expect('my@domain.com')->toEqual(Arr::getByPath($this->data, 'email'));
- function testOfArraySetBySelectorDoesNotOverwriteTheExistingValues()
- {
- $this->data = Arr::setBySelector($this->data, 'name', 'Jane Fonda');
- $this->assertEquals(Arr::getByPath($this->data, 'name'), 'John Doe');
- }
+ $this->data = Arr::setBySelector($this->data, 'newsletters[offers]', true);
+ expect(array( 'offers' => true ))->toEqual(Arr::getByPath($this->data, 'newsletters'));
+ $this->data = Arr::setBySelector($this->data, 'addresses[*][state]', 'California');
+ expect('California')->toEqual(Arr::getByPath($this->data, 'addresses[shipping][state]'));
+ expect('California')->toEqual(Arr::getByPath($this->data, 'addresses[billing][state]'));
+});
- function testOfArraySetBySelectorEnsuresDataIsArray()
- {
- $this->data = Arr::setBySelector('string', 'name', 'Jane Fonda');
- $this->assertEquals(Arr::getByPath($this->data, 'name'), 'Jane Fonda');
- }
+test('array set by selector does not overwrite the existing values', function () {
+ $this->data = Arr::setBySelector($this->data, 'name', 'Jane Fonda');
+ expect('John Doe')->toEqual(Arr::getByPath($this->data, 'name'));
+});
- function testOfArrayGetBySelectorDeepSearch()
- {
- $arr = array(
- 'people' => array(
- array(
- 'name' => 'John',
- 'address' => array(
- 'city' => 'New York'
- )
- ),
- array(
- 'name' => 'Marry',
- 'address' => array(
- 'state' => 'California'
- )
- ),
- )
- );
- $this->assertEquals(
+test('array get by selector deep search', function () {
+ $arr = array(
+ 'people' => array(
array(
- 'people[0][address][city]' => 'New York',
- 'people[1][address][city]' => null
- ),
- Arr::getBySelector($arr, 'people[*][address][city]')
- );
- }
-
- function testOfArrayGetBySelectorUsingPath()
- {
- $arr = array(
- 'recipients' => array(
- array('name' => 'John'),
- array('name' => 'Marry', 'email' => 'marry@gmail.com')
- )
- );
- $this->assertEquals(
- array(
- 'recipients[0][email]' => null
+ 'name' => 'John',
+ 'address' => array(
+ 'city' => 'New York'
+ )
),
- Arr::getBySelector($arr, 'recipients[0][email]')
- );
- $this->assertEquals(
array(
- 'recipients[1][email]' => 'marry@gmail.com'
+ 'name' => 'Marry',
+ 'address' => array(
+ 'state' => 'California'
+ )
),
- Arr::getBySelector($arr, 'recipients[1][email]')
- );
- }
+ )
+ );
+ expect(Arr::getBySelector($arr, 'people[*][address][city]'))->toEqual(array(
+ 'people[0][address][city]' => 'New York',
+ 'people[1][address][city]' => null
+ ));
+});
- function testOfArrayGetBySelectorWithEndingSelector()
- {
- $arr = array(
- 'lines' => array(
- 'quantities' => array(1, 2, 3)
- )
- );
- $this->assertEquals(
- array(
- 'lines[quantities][0]' => 1,
- 'lines[quantities][1]' => 2,
- 'lines[quantities][2]' => 3
- ),
- Arr::getBySelector($arr, 'lines[quantities][*]')
- );
- }
+test('array get by selector using path', function () {
+ $arr = array(
+ 'recipients' => array(
+ array( 'name' => 'John' ),
+ array( 'name' => 'Marry', 'email' => 'marry@gmail.com' )
+ )
+ );
+ expect(Arr::getBySelector($arr, 'recipients[0][email]'))->toEqual(array(
+ 'recipients[0][email]' => null
+ ));
+ expect(Arr::getBySelector($arr, 'recipients[1][email]'))->toEqual(array(
+ 'recipients[1][email]' => 'marry@gmail.com'
+ ));
+});
- function testOfArrayGetBySelectorWithWrongSelector()
- {
- $arr = array(
- 'lines' => array(
- 'quantities' => array(1, 2, 3)
- )
- );
- $this->assertEquals(array(), Arr::getBySelector($arr, 'recipients[*]'));
- }
-}
+test('array get by selector with ending selector', function () {
+ $arr = array(
+ 'lines' => array(
+ 'quantities' => array( 1, 2, 3 )
+ )
+ );
+ expect(Arr::getBySelector($arr, 'lines[quantities][*]'))->toEqual(array(
+ 'lines[quantities][0]' => 1,
+ 'lines[quantities][1]' => 2,
+ 'lines[quantities][2]' => 3
+ ));
+});
+
+test('array get by selector with wrong selector', function () {
+ $arr = array(
+ 'lines' => array(
+ 'quantities' => array( 1, 2, 3 )
+ )
+ );
+ expect(Arr::getBySelector($arr, 'recipients[*]'))->toEqual(array());
+});
diff --git a/tests/src/ValidatorTest.php b/tests/src/ValidatorTest.php
index 0de9540..3b98439 100755
--- a/tests/src/ValidatorTest.php
+++ b/tests/src/ValidatorTest.php
@@ -1,6 +1,8 @@
validator = new Validator(new RuleFactory, new ErrorMessage);
+});
+
+test('if messages can be set and cleared', function () {
+ expect(count($this->validator->getMessages()))->toEqual(0);
+
+ // add empty message does nothing
+ $this->validator->addMessage('field_1');
+ expect(count($this->validator->getMessages()))->toEqual(0);
+
+ $this->validator->addMessage('field_1', 'Field is required');
+ $this->validator->addMessage('field_2', 'Field should be an email');
+ expect(count($this->validator->getMessages()))->toEqual(2);
+
+ $this->validator->clearMessages('field_1');
+ expect(count($this->validator->getMessages()))->toEqual(1);
+ $this->validator->clearMessages();
+ expect(count($this->validator->getMessages()))->toEqual(0);
+});
+
+test('exception thrown when the data is not an array', function () {
+ $this->expectException('InvalidArgumentException');
+ $this->validator->validate('string');
+ $this->validator->validate(false);
+});
+
+test('if validate executes', function () {
+ $this->validator
+ ->add('field_1', 'Required', null)
+ ->add('field_2', 'Email', null, 'This field should be an email');
+
+ expect($this->validator->validate(
+ array(
+ 'field_1' => 'exists',
+ 'field_2' => 'not'
+ )
+ ))->toBeFalse();
+
+ $this->validator->validate(
+ array(
+ 'field_1' => 'exists',
+ 'field_2' => 'me@domain.com'
+ )
+ );
+
+ // execute the validation again without data
+ $this->validator->validate();
+ expect(count($this->validator->getMessages()))->toEqual(0);
+});
+
+test('if missing items validate against the required rule', function () {
+ $this->validator->add('item', 'required', null, 'This field is required');
+ $this->validator->add('items[subitem]', 'required', null, 'This field is required');
+ $this->validator->setData(array());
+ $this->validator->validate();
+ expect(array('This field is required'))->toEqual($this->validator->getMessages('item'));
+ expect(array('This field is required'))->toEqual($this->validator->getMessages('items[subitem]'));
+});
+
+test('different data formats', function () {
+ $this->validator->add('email', 'email');
+
+ // test array objects
+ $data = new \ArrayObject(array(), \ArrayObject::ARRAY_AS_PROPS);
+ $data->email = 'not_an_email';
+
+ $this->validator->validate($data);
+ expect(count($this->validator->getMessages('email')))->toEqual(1);
+
+ // test objects with a 'toArray' method
+ $data = new FakeObject();
+ $data->email = 'not_an_email';
+ $this->validator->validate($data);
+ expect(count($this->validator->getMessages('email')))->toEqual(1);
+});
+
+test('if exception is thrown on invalid rules', function () {
+ $this->expectException('\InvalidArgumentException');
+ $this->validator->add('random_string');
+});
+
+test('adding multiple rules at once', function () {
+ $this->validator->add(
+ array(
+ 'item' => array(
+ 'required',
+ array('minlength', 'min=4', '{label} should have at least {min} characters', 'Item')
+ ),
+ 'itema' => array('required', 'minLength(min=8)', 'required'),
+ 'itemb' => 'required'
+ )
+ );
+ $this->validator->validate(
+ array(
+ 'item' => 'ab',
+ 'itema' => 'abc'
+ )
+ );
+ expect($this->validator->getMessages('item'))->toEqual(array('Item should have at least 4 characters'));
+ expect($this->validator->getMessages('itema'))->toEqual(array('This input should have at least 8 characters'));
+ expect($this->validator->getMessages('itemb'))->toEqual(array('This field is required'));
+});
+
+test('adding validation rules via strings without label arg', function () {
+ $this->validator
+ // mixed rules in 1 string
+ ->add('item:Item', 'required | minLength({"min":4})')
+ // validator options as a QUERY string
+ ->add('itema:Item', 'minLength', 'min=8')
+ // validator without options and custom message
+ ->add('itemb:Item B', 'required')
+ // validator with defaults
+ ->add('itemc', 'email');
+ $this->validator->validate(array('item' => 'ab', 'itema' => 'abc', 'itemc' => 'abc'));
+ expect(array((string)$this->validator->getMessages('item')[0]))->toEqual(array('Item should have at least 4 characters'));
+ expect($this->validator->getMessages('itema'))->toEqual(array('Item should have at least 8 characters'));
+ expect($this->validator->getMessages('itemb'))->toEqual(array('Item B is required'));
+ expect($this->validator->getMessages('itemc'))->toEqual(array('This input must be a valid email address'));
+});
+
+test('adding validation rules via strings', function () {
+ $this->validator
+ // mixed rules in 1 string
+ ->add('item', 'required | minLength({"min":4})({label} should have at least {min} characters)(Item)')
+ // validator options as a QUERY string
+ ->add('itema', 'minLength', 'min=8', '{label} should have at least {min} characters', 'Item')
+ // validator without options and custom message
+ ->add('itemb', 'required()(Item B is required)')
+ // validator with defaults
+ ->add('itemc', 'email');
+ $this->validator->validate(array('item' => 'ab', 'itema' => 'abc', 'itemc' => 'abc'));
+ expect($this->validator->getMessages('item'))->toEqual(array('Item should have at least 4 characters'));
+ expect($this->validator->getMessages('itema'))->toEqual(array('Item should have at least 8 characters'));
+ expect($this->validator->getMessages('itemb'))->toEqual(array('Item B is required'));
+ expect($this->validator->getMessages('itemc'))->toEqual(array('This input must be a valid email address'));
+});
+
+test('exception on invalid validator options', function () {
+ $this->expectException('\InvalidArgumentException');
+ $this->validator->add('item', 'required', new \stdClass());
+});
+
+function fakeValidationMethod($value)
{
+ return false;
+}
- function setUp()
- {
- $this->validator = new Validator(new RuleFactory, new ErrorMessage);
- }
-
- function testIfMessagesCanBeSetAndCleared()
- {
- $this->assertEquals(0, count($this->validator->getMessages()));
-
- // add empty message does nothing
- $this->validator->addMessage('field_1');
- $this->assertEquals(0, count($this->validator->getMessages()));
-
- $this->validator->addMessage('field_1', 'Field is required');
- $this->validator->addMessage('field_2', 'Field should be an email');
- $this->assertEquals(2, count($this->validator->getMessages()));
-
- $this->validator->clearMessages('field_1');
- $this->assertEquals(1, count($this->validator->getMessages()));
- $this->validator->clearMessages();
- $this->assertEquals(0, count($this->validator->getMessages()));
- }
-
- function testExceptionThrownWhenTheDataIsNotAnArray()
- {
- $this->setExpectedException('InvalidArgumentException');
- $this->validator->validate('string');
- $this->validator->validate(false);
- }
-
- function testIfValidateExecutes()
- {
- $this->validator
- ->add('field_1', 'Required', null)
- ->add('field_2', 'Email', null, 'This field should be an email');
-
- $this->assertFalse(
- $this->validator->validate(
- array(
- 'field_1' => 'exists',
- 'field_2' => 'not'
- )
- )
- );
-
- $this->validator->validate(
- array(
- 'field_1' => 'exists',
- 'field_2' => 'me@domain.com'
- )
- );
-
- // execute the validation again without data
- $this->validator->validate();
- $this->assertEquals(0, count($this->validator->getMessages()));
-
- }
-
- function testIfMissingItemsValidateAgainstTheRequiredRule()
- {
- $this->validator->add('item', 'required', null, 'This field is required');
- $this->validator->add('items[subitem]', 'required', null, 'This field is required');
- $this->validator->setData(array());
- $this->validator->validate();
- $this->assertEquals($this->validator->getMessages('item'), array('This field is required'));
- $this->assertEquals($this->validator->getMessages('items[subitem]'), array('This field is required'));
- }
-
- function testDifferentDataFormats()
- {
- $this->validator->add('email', 'email');
-
- // test array objects
- $data = new \ArrayObject(array(), \ArrayObject::ARRAY_AS_PROPS);
- $data->email = 'not_an_email';
-
- $this->validator->validate($data);
- $this->assertEquals(1, count($this->validator->getMessages('email')));
-
- // test objects with a 'toArray' method
- $data = new FakeObject();
- $data->email = 'not_an_email';
- $this->validator->validate($data);
- $this->assertEquals(1, count($this->validator->getMessages('email')));
- }
-
- function testIfExceptionIsThrownOnInvalidRules()
- {
- $this->setExpectedException('\InvalidArgumentException');
- $this->validator->add('random_string');
- }
-
- function testAddingMultipleRulesAtOnce()
- {
- $this->validator->add(
- array(
- 'item' => array(
- 'required',
- array('minlength', 'min=4', '{label} should have at least {min} characters', 'Item')
- ),
- 'itema' => array('required', 'minLength(min=8)', 'required'),
- 'itemb' => 'required'
- )
- );
- $this->validator->validate(
- array(
- 'item' => 'ab',
- 'itema' => 'abc'
- )
- );
- $this->assertEquals(array('Item should have at least 4 characters'), $this->validator->getMessages('item'));
- $this->assertEquals(
- array('This input should have at least 8 characters'),
- $this->validator->getMessages('itema')
- );
- $this->assertEquals(array('This field is required'), $this->validator->getMessages('itemb'));
- }
-
- function testAddingValidationRulesViaStrings()
- {
- $this->validator
- // mixed rules in 1 string
- ->add('item', 'required | minLength({"min":4})({label} should have at least {min} characters)(Item)')
- // validator options as a QUERY string
- ->add('itema', 'minLength', 'min=8', '{label} should have at least {min} characters', 'Item')
- // validator without options and custom message
- ->add('itemb', 'required()(Item B is required)')
- // validator with defaults
- ->add('itemc', 'email');
- $this->validator->validate(array('item' => 'ab', 'itema' => 'abc', 'itemc' => 'abc'));
- $this->assertEquals(array('Item should have at least 4 characters'), $this->validator->getMessages('item'));
- $this->assertEquals(array('Item should have at least 8 characters'), $this->validator->getMessages('itema'));
- $this->assertEquals(array('Item B is required'), $this->validator->getMessages('itemb'));
- $this->assertEquals(array('This input must be a valid email address'), $this->validator->getMessages('itemc'));
- }
-
- function testExceptionOnInvalidValidatorOptions()
- {
- $this->setExpectedException('\InvalidArgumentException');
- $this->validator->add('item', 'required', new \stdClass());
- }
-
- function fakeValidationMethod($value)
- {
- return false;
- }
-
- static function fakeStaticValidationMethod($value, $return = false)
- {
- return $return;
- }
-
-
- function testCallbackValidators()
- {
- $this->validator->add('function', __NAMESPACE__ . '\fakeValidationFunction');
- $this->validator->add('method', array($this, 'fakeValidationMethod'));
- $this->validator->add(
- 'staticMethod',
- array(__CLASS__, 'fakeStaticValidationMethod'),
- array(true)
- ); // this will return true
-
- $this->validator->validate(
- array(
- 'function' => true,
- 'method' => true,
- 'staticMethod' => true,
- )
- );
- $this->assertEquals(2, count($this->validator->getMessages()));
- }
-
- function testRemovingValidationRules()
- {
- $this->validator->add('item', 'required');
- $this->assertFalse($this->validator->validate(array()));
-
- $this->validator->remove('item', 'required');
- $this->assertTrue($this->validator->validate(array()));
- }
-
- function testRemovingAllValidationRules()
- {
- $this->validator->remove('item', true);
- $this->validator->add('item', 'required');
- $this->validator->add('item', 'email');
- $this->validator->setData(array());
- $this->assertFalse($this->validator->validate());
-
- $this->validator->remove('item', true);
- $rules = $this->validator->getRules();
- $this->assertEquals(count($rules['item']->getRules()), 0);
- $this->assertTrue($this->validator->validate(array()));
- }
+function fakeStaticValidationMethod($value, $return = false)
+{
+ return $return;
+}
- function testMatchingRules()
- {
- $this->validator
- ->add('items[*][key]', 'email', null, 'Key must be an email');
- $this->validator->validate(
- array(
- 'items' => array(
- array('key' => 'sss'),
- array('key' => 'sss')
- )
+test('callback validators', function () {
+ $this->validator->add('function', 'fakeValidationFunction');
+
+ // this will return true
+ $this->validator->validate(
+ array(
+ 'function' => true,
+ )
+ );
+ expect(count($this->validator->getMessages()))->toEqual(1);
+});
+
+test('removing validation rules', function () {
+ $this->validator->add('item', 'required');
+ expect($this->validator->validate(array()))->toBeFalse();
+
+ $this->validator->remove('item', 'required');
+ expect($this->validator->validate(array()))->toBeTrue();
+});
+
+test('removing all validation rules', function () {
+ $this->validator->remove('item', true);
+ $this->validator->add('item', 'required');
+ $this->validator->add('item', 'email');
+ $this->validator->setData(array());
+ expect($this->validator->validate())->toBeFalse();
+
+ $this->validator->remove('item', true);
+ $rules = $this->validator->getRules();
+ expect(0)->toEqual(count($rules['item']->getRules()));
+ expect($this->validator->validate(array()))->toBeTrue();
+});
+
+test('matching rules', function () {
+ $this->validator
+ ->add('items[*][key]', 'email', null, 'Key must be an email');
+ $this->validator->validate(
+ array(
+ 'items' => array(
+ array('key' => 'sss'),
+ array('key' => 'sss')
)
- );
- $this->assertEquals(array('Key must be an email'), $this->validator->getMessages('items[0][key]'));
- $this->assertEquals(array('Key must be an email'), $this->validator->getMessages('items[1][key]'));
- }
-
- function testIfParametersAreSentToValidationMethods()
- {
- $this->validator
- ->add('a', 'email', array(0, 1), 'This should be an email')
- ->add('b', 'email', array(0, 1, 2), 'This should be an email')
- ->add('c', 'email', array(0, 1, 2, 3), 'This should be an email');
- $this->validator->validate(array('a' => 'a', 'b' => 'b', 'c' => 'c'));
- $messages = $this->validator->getMessages();
- foreach (array('a', 'b', 'c') as $k) {
- $this->assertEquals(1, count($messages[$k]));
- }
- }
-
- function testIfExceptionIsThrownForInvalidValidationMethods()
- {
- $this->setExpectedException('\InvalidArgumentException');
- $this->validator->add('item', 'faker');
- $this->validator->validate(array('item' => true));
- }
-
-}
+ )
+ );
+ expect($this->validator->getMessages('items[0][key]'))->toEqual(array('Key must be an email'));
+ expect($this->validator->getMessages('items[1][key]'))->toEqual(array('Key must be an email'));
+});
+
+test('if parameters are sent to validation methods', function () {
+ $this->validator
+ ->add('a', 'email', array(0, 1), 'This should be an email')
+ ->add('b', 'email', array(0, 1, 2), 'This should be an email')
+ ->add('c', 'email', array(0, 1, 2, 3), 'This should be an email');
+ $this->validator->validate(array('a' => 'a', 'b' => 'b', 'c' => 'c'));
+ $messages = $this->validator->getMessages();
+ foreach (array('a', 'b', 'c') as $k) {
+ expect(count($messages[$k]))->toEqual(1);
+ }
+});
+
+test('if exception is thrown for invalid validation methods', function () {
+ $this->expectException('\InvalidArgumentException');
+ $this->validator->add('item', 'faker');
+ $this->validator->validate(array('item' => true));
+});
+
+test('empty array validation', function () {
+ $this->validator->add(array(
+ 'a' => array('required'),
+ 'b' => array('required')
+ ));
+ $this->validator->validate(array());
+ expect(count($this->validator->getMessages()))->toEqual(2);
+});
+
+test('validation require conditional', function () {
+ $this->validator->add(array(
+ 'a' => array('number', 'requiredWith(b)'),
+ 'b' => array('number', 'requiredWith(a)')
+ ));
+ expect($this->validator->validate(array()))->toBeTrue();
+});
diff --git a/tests/src/ValueValidatorTest.php b/tests/src/ValueValidatorTest.php
index 33007d3..08aed6e 100644
--- a/tests/src/ValueValidatorTest.php
+++ b/tests/src/ValueValidatorTest.php
@@ -1,67 +1,80 @@
validator = new ValueValidator();
- }
+use \Sirius\Validation\ValueValidator;
- function testAddingValidationRulesRegularly()
- {
- $this->validator->add('required')->add('minlength', '{"min":4}',
- '{label} should have at least {min} characters', 'Item');
- $this->validator->validate('ab');
- $this->assertEquals(array(
- 'Item should have at least 4 characters'
- ), $this->validator->getMessages());
- }
+beforeEach(function () {
+ $this->validator = new ValueValidator();
+});
- function testAddingValidationRulesViaStrings()
- {
- $this->validator->add('required | minlength({"min":4})({label} should have at least {min} characters)(Item)');
- $this->validator->validate('ab');
- $this->assertEquals(array(
- 'Item should have at least 4 characters'
- ), $this->validator->getMessages());
- }
+test('adding validation rules regularly', function () {
+ $this->validator->add('required')->add('minlength', '{"min":4}',
+ '{label} should have at least {min} characters', 'Item');
+ $this->validator->validate('ab');
+ expect($this->validator->getMessages())->toEqual(array(
+ 'Item should have at least 4 characters'
+ ));
+});
- function testRemovingValidationRules()
- {
- $this->validator->add('required');
- $this->assertFalse($this->validator->validate(null));
- $this->validator->remove('required');
- $this->assertTrue($this->validator->validate(null));
- }
+test('adding validation rules via strings', function () {
+ $this->validator->add('required | minlength({"min":4})({label} should have at least {min} characters)(Item)');
+ $this->validator->validate('ab');
+ expect($this->validator->getMessages())->toEqual(array(
+ 'Item should have at least 4 characters'
+ ));
+});
- function testRemovingAllRules()
- {
- $this->validator->add('required')->add('minlength', '{"min":4}',
- '{label} should have at least {min} characters', 'Item');
- $this->validator->validate('ab');
- $this->assertEquals(array(
- 'Item should have at least 4 characters'
- ), $this->validator->getMessages());
- $this->validator->remove(true);
- $this->assertTrue($this->validator->validate(null));
- }
+test('removing validation rules', function () {
+ $this->validator->add('required');
+ expect($this->validator->validate(null))->toBeFalse();
+ $this->validator->remove('required');
+ expect($this->validator->validate(null))->toBeTrue();
+});
- function testNonRequiredRules()
- {
- $this->validator->add('email');
- $this->assertTrue($this->validator->validate(null));
- }
+test('removing all rules', function () {
+ $this->validator->add('required')->add('minlength', '{"min":4}',
+ '{label} should have at least {min} characters', 'Item');
+ $this->validator->validate('ab');
+ expect($this->validator->getMessages())->toEqual(array(
+ 'Item should have at least 4 characters'
+ ));
+ $this->validator->remove(true);
+ expect($this->validator->validate(null))->toBeTrue();
+});
+
+test('non required rules', function () {
+ $this->validator->add('email');
+ expect($this->validator->validate(null))->toBeTrue();
+ expect($this->validator->validate(''))->toBeTrue();
+});
- function testDefaultLabel()
- {
- $this->validator->setLabel('Item');
- $this->validator->add('required')->add('minlength', '{"min":4}',
- '{label} should have at least {min} characters');
- $this->validator->validate('ab');
- $this->assertEquals(array(
- 'Item should have at least 4 characters'
- ), $this->validator->getMessages());
+test('default label', function () {
+ $this->validator->setLabel('Item');
+ $this->validator->add('required')->add('minlength', '{"min":4}',
+ '{label} should have at least {min} characters');
+ $this->validator->validate('ab');
+ expect($this->validator->getMessages())->toEqual(array(
+ 'Item should have at least 4 characters'
+ ));
+});
+
+test('parse rule with zero value in csv format', function () {
+ $this->validator->add('GreaterThan(0)');
+
+ /** @var GreaterThan $rule */
+ foreach ($this->validator->getRules() as $rule) {
+ break;
}
-}
+
+ expect($rule->getOption('min'))->toBe('0');
+
+ $this->validator->validate(1);
+ expect($this->validator->getMessages())->toBeEmpty();
+
+ $this->validator->validate(0);
+ expect($this->validator->getMessages())->toBeEmpty();
+
+ $this->validator->validate(-1);
+ expect($this->validator->getMessages())->not->toBeEmpty();
+});
diff --git a/tools/php-cs-fixer/composer.json b/tools/php-cs-fixer/composer.json
new file mode 100644
index 0000000..bc1aa7b
--- /dev/null
+++ b/tools/php-cs-fixer/composer.json
@@ -0,0 +1,5 @@
+{
+ "require": {
+ "friendsofphp/php-cs-fixer": "^3.34"
+ }
+}