diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..7c32f5c
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,14 @@
+# EditorConfig is awesome: http://EditorConfig.org
+
+# top-most EditorConfig file
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[{*.php,*.json,*.md,*.html,*.css,*.js,*.yml}]
+indent_style = space
+indent_size = 4
diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml
new file mode 100644
index 0000000..586be4a
--- /dev/null
+++ b/.github/workflows/php.yml
@@ -0,0 +1,64 @@
+name: PHP Composer
+
+on:
+ push:
+ branches: [ "master" ]
+ pull_request:
+ branches: [ "master" ]
+
+permissions:
+ contents: read
+
+jobs:
+ tests:
+
+ runs-on: ubuntu-latest
+
+ strategy:
+ matrix:
+ dependencies: [ "lowest", "normal" ]
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Validate composer.json and composer.lock
+ run: composer validate --strict
+
+ - name: Cache Composer packages
+ id: composer-cache
+ uses: actions/cache@v3
+ with:
+ path: vendor
+ key: ${{ runner.os }}-php-${{ matrix.dependencies }}-${{ hashFiles('**/composer.lock') }}
+ restore-keys: |
+ ${{ runner.os }}-php-${{ matrix.dependencies }}-
+
+ - name: Install dependencies (mode ${{ matrix.dependencies }})
+ run: |
+ if [ "${{ matrix.dependencies }}" = "lowest" ]; then
+ composer update --prefer-lowest --prefer-dist --no-progress
+ else
+ composer install --prefer-dist --no-progress
+ fi
+
+ - name: Enable Xdebug
+ run: echo "XDEBUG_MODE=coverage" >> $GITHUB_ENV
+
+ - name: Run test suite
+ run: vendor/bin/phpunit --coverage-clover coverage.xml --log-junit junit.xml
+
+ - name: Upload test results to Codecov
+ if: ${{ !cancelled() && matrix.dependencies == 'normal' }}
+ uses: codecov/test-results-action@v1
+ with:
+ token: ${{ secrets.CODECOV_TOKEN }}
+ fail_ci_if_error: true
+
+ - name: Upload coverage to Codecov
+ if: ${{ !cancelled() && matrix.dependencies == 'normal' }}
+ uses: codecov/codecov-action@v5
+ with:
+ token: ${{ secrets.CODECOV_TOKEN }}
+ files: coverage.xml
+ flags: php
+ fail_ci_if_error: true
diff --git a/.gitignore b/.gitignore
index 7579f74..df1639f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,8 @@
vendor
composer.lock
+.phpunit.cache
+.phpunit.result.cache
+.php-cs-fixer.cache
+clover.xml
+junit.xml
+coverage.xml
diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php
new file mode 100644
index 0000000..5b3b013
--- /dev/null
+++ b/.php-cs-fixer.dist.php
@@ -0,0 +1,27 @@
+ignoreDotFiles(false)
+ ->ignoreVCSIgnored(true)
+ ->in(__DIR__)
+;
+
+return (new Config())
+ ->setRiskyAllowed(true)
+ ->setRules([
+ '@PHP74Migration' => true,
+ '@PHP74Migration:risky' => true,
+ '@PHPUnit100Migration:risky' => true,
+ '@PhpCsFixer' => true,
+ '@PhpCsFixer:risky' => false,
+ 'yoda_style' => true,
+ 'general_phpdoc_annotation_remove' => ['annotations' => ['expectedDeprecation']], // one should use PHPUnit built-in method instead
+ 'modernize_strpos' => true, // needs PHP 8+ or polyfill
+ 'no_useless_concat_operator' => false, // TODO switch back on when the `src/Console/Application.php` no longer needs the concat
+ ])
+ ->setFinder($finder)
+;
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 5ad82f9..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,63 +0,0 @@
-language: php
-
-cache:
- directories:
- - vendor/
-
-before_install:
- # Disable xdebug if php version != 7.2 (only use xdebug for reports)
- - if [[ $ENABLE_CODE_COVERAGE == false ]]; then phpenv config-rm xdebug.ini; fi
- # Enable mongo/mongodb extension regarding php version
- - echo "extension = ${MONGO_EXT_NAME}.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
- - echo "php ext-${MONGO_EXT_NAME} extension enabled."
- # Require alcaeus/mongo-php-adapter for php >= 7 tests
- - if [[ $TRAVIS_PHP_VERSION == 7.* ]]; then composer config "platform.ext-mongo" "1.6.16" && composer require alcaeus/mongo-php-adapter; fi
- # Require doctine collections/orm/mongodb to launch ALL tests
- - composer require doctrine/collections:">=1.0" doctrine/orm:">=2.0" doctrine/mongodb:">=1.0"
-
-env:
- global:
- - MONGO_EXT_NAME=mongo
- - ENABLE_CODE_COVERAGE=false
-
-before_script:
- - composer install
-
-script:
- - ./vendor/bin/phpunit --coverage-clover=coverage.xml
-
-after_success:
- - if [[ $ENABLE_CODE_COVERAGE ]]; then bash <(curl -s https://codecov.io/bash); fi
-
-matrix:
- include:
-#===== TESTS
- - php: '5.3'
- dist: precise
- - php: '5.4'
- - php: '5.5'
- - php: '5.6'
- - php: '7.0'
- env:
- - MONGO_EXT_NAME=mongodb
- - php: '7.1'
- env:
- - MONGO_EXT_NAME=mongodb
- - php: '7.2'
- env:
- - MONGO_EXT_NAME=mongodb
- - ENABLE_CODE_COVERAGE=true
-#===== CODE INSPECTION
- - stage: 'code-inspection'
- php: '7.2'
- env: ''
- before_install: ''
- before_script:
- - composer require phpmd/phpmd:"@stable" squizlabs/php_codesniffer:"@stable"
- - composer install
- install: skip
- script:
- - ./vendor/bin/phpcs --config-set ignore_warnings_on_exit 1
- - ./vendor/bin/phpcs --standard=PSR1 src/
- - ./vendor/bin/phpcs --standard=PSR2 src/
-# - ./vendor/bin/phpmd src/ text codesize,unusedcode,naming,design,cleancode
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..0ca2e83
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,14 @@
+default: install test stan
+
+install:
+ composer install
+
+test:
+ vendor/bin/phpunit
+
+cs:
+ vendor/bin/php-cs-fixer fix -vvv
+
+analyse: test
+ vendor/bin/phpmetrics --junit --report-html=docs/phpmetrics/index.html src
+ vendor/bin/phpstan
diff --git a/composer.json b/composer.json
index 1e36adf..d3de94d 100644
--- a/composer.json
+++ b/composer.json
@@ -1,38 +1,54 @@
{
- "name": "symftony/xpression",
- "authors": [
- {
- "name": "Anthony",
- "email": "symftony@gmail.com"
+ "name": "symftony/xpression",
+ "authors": [
+ {
+ "name": "Anthony",
+ "email": "symftony@gmail.com"
+ }
+ ],
+ "type": "library",
+ "description": "Xpression is a simple PHP implementation of Specification pattern",
+ "keywords": [
+ "dsl",
+ "doctrine",
+ "orm",
+ "mongodb",
+ "collections",
+ "specification",
+ "expression",
+ "parser",
+ "lexer",
+ "query",
+ "builder",
+ "query builder"
+ ],
+ "homepage": "https://github.com/symftony/Xpression",
+ "require": {
+ "php": "^8.0",
+ "doctrine/lexer": "^1.2.1"
+ },
+ "require-dev": {
+ "doctrine/collections": "^1.8.0",
+ "doctrine/orm": "^2.8.0",
+ "phpspec/prophecy": "^1.18",
+ "phpunit/phpunit": "^9.6",
+ "friendsofphp/php-cs-fixer": "^3.41",
+ "phpstan/phpstan": "^1.10",
+ "phpmetrics/phpmetrics": "^2.8"
+ },
+ "suggest": {
+ "doctrine/collections": "If you want filter an ArrayCollection",
+ "doctrine/orm": "If you want filter an ORM query builder"
+ },
+ "license": "MIT",
+ "autoload": {
+ "psr-4": {
+ "Symftony\\Xpression\\": "src/"
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Tests\\Symftony\\Xpression\\": "tests/"
+ }
}
- ],
- "type": "library",
- "description": "Xpression is a simple PHP implementation of Specification pattern",
- "keywords": ["dsl", "doctrine", "orm", "mongodb", "collections", "specification", "expression", "parser", "lexer", "query", "builder", "query builder"],
- "homepage": "https://github.com/symftony/Xpression",
- "require": {
- "php": ">=5.3",
- "doctrine/lexer": "^1.0"
- },
- "require-dev": {
- "phpunit/phpunit": ">=4.8.35",
- "doctrine/collections": "^1.0",
- "doctrine/orm": "^2.4.0"
- },
- "suggest": {
- "doctrine/collections": "If you want filter an ArrayCollection",
- "doctrine/orm": "If you want filter an ORM query builder",
- "doctrine/mongodb": "If you want filter an Mongodb query builder"
- },
- "license": "MIT",
- "autoload": {
- "psr-4": {
- "Symftony\\Xpression\\": "src/"
- }
- },
- "autoload-dev": {
- "psr-4": {
- "Tests\\Symftony\\Xpression\\": "tests/"
- }
- }
}
diff --git a/docs/index.html b/docs/index.html
new file mode 100644
index 0000000..b271dad
--- /dev/null
+++ b/docs/index.html
@@ -0,0 +1,10 @@
+
+
+
+
+ Symftony Xpression
+
+
+WIP github pages
+
+
diff --git a/phpstan.neon.dist b/phpstan.neon.dist
new file mode 100644
index 0000000..7aa9876
--- /dev/null
+++ b/phpstan.neon.dist
@@ -0,0 +1,8 @@
+parameters:
+ level: 6
+ paths:
+ - src
+ ignoreErrors:
+ - '/Method .*::(in|notIn|andX|nandX|orX|norX|xorX)\(\) has parameter .* with no value type specified in iterable type array\./'
+ - '/Method Symftony\\Xpression\\Parser::getNextToken\(\) return type has no value type specified in iterable type array\./'
+ - '/Method Symftony\\Xpression\\Lexer::get(Non)?CatchablePatterns\(\) return type has no value type specified in iterable type array\./'
diff --git a/phpunit.xml b/phpunit.xml
new file mode 100644
index 0000000..1a73bc9
--- /dev/null
+++ b/phpunit.xml
@@ -0,0 +1,30 @@
+
+
+
+
+ tests
+
+
+
+
+
+ src
+
+
+ src/Exception
+
+
+
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
deleted file mode 100644
index f62072a..0000000
--- a/phpunit.xml.dist
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
-
-
-
-
-
-
- tests
-
-
-
-
-
- src
-
- src/Exception
-
-
-
-
diff --git a/src/Bridge/Doctrine/Common/ExpressionBuilderAdapter.php b/src/Bridge/Doctrine/Common/ExpressionBuilderAdapter.php
index 4f59bfa..f14593a 100644
--- a/src/Bridge/Doctrine/Common/ExpressionBuilderAdapter.php
+++ b/src/Bridge/Doctrine/Common/ExpressionBuilderAdapter.php
@@ -1,161 +1,84 @@
expressionBuilder = $expressionBuilder;
- }
-
- /**
- * @return int
- */
- public function getSupportedTokenType()
+ public function getSupportedTokenType(): int
{
return Lexer::T_ALL - Lexer::T_NOT_AND - Lexer::T_NOT_OR - Lexer::T_XOR - Lexer::T_NOT_DOUBLE_OPEN_CURLY_BRACKET;
}
- /**
- * @param $value
- * @param bool $isValue
- *
- * @return mixed
- */
- public function parameter($value, $isValue = false)
+ public function parameter(mixed $value, bool $isValue = false): mixed
{
return $value;
}
- /**
- * @param $value
- * @return mixed
- */
- public function string($value)
+ public function string(mixed $value): mixed
{
return $value;
}
- /**
- * @param string $field
- *
- * @return Comparison
- */
- public function isNull($field)
+ public function isNull(string $field): mixed
{
return $this->expressionBuilder->isNull($field);
}
- /**
- * @param string $field
- * @param mixed $value
- *
- * @return Comparison
- */
- public function eq($field, $value)
+ public function eq(string $field, mixed $value): mixed
{
return $this->expressionBuilder->eq($field, $value);
}
- /**
- * @param string $field
- * @param mixed $value
- *
- * @return Comparison
- */
- public function neq($field, $value)
+ public function neq(string $field, mixed $value): mixed
{
return $this->expressionBuilder->neq($field, $value);
}
- /**
- * @param string $field
- * @param mixed $value
- *
- * @return Comparison
- */
- public function gt($field, $value)
+ public function gt(string $field, mixed $value): mixed
{
return $this->expressionBuilder->gt($field, $value);
}
- /**
- * @param string $field
- * @param mixed $value
- *
- * @return Comparison
- */
- public function gte($field, $value)
+ public function gte(string $field, mixed $value): mixed
{
return $this->expressionBuilder->gte($field, $value);
}
- /**
- * @param string $field
- * @param mixed $value
- *
- * @return Comparison
- */
- public function lt($field, $value)
+ public function lt(string $field, mixed $value): mixed
{
return $this->expressionBuilder->lt($field, $value);
}
- /**
- * @param string $field
- * @param mixed $value
- *
- * @return Comparison
- */
- public function lte($field, $value)
+ public function lte(string $field, mixed $value): mixed
{
return $this->expressionBuilder->lte($field, $value);
}
- /**
- * @param string $field
- * @param mixed $values
- *
- * @return Comparison
- */
- public function in($field, array $values)
+ public function in(string $field, array $values): mixed
{
return $this->expressionBuilder->in($field, $values);
}
- /**
- * @param string $field
- * @param mixed $values
- *
- * @return Comparison
- */
- public function notIn($field, array $values)
+ public function notIn(string $field, array $values): mixed
{
return $this->expressionBuilder->notIn($field, $values);
}
/**
- * /!\ Contains operator appear only in doctrine/common v1.1 /!\
- *
- * @param string $field
- * @param mixed $value
- *
- * @return Comparison
+ * /!\ Contains operator appear only in doctrine/common v1.1 /!\.
*/
- public function contains($field, $value)
+ public function contains(string $field, mixed $value): mixed
{
if (!method_exists($this->expressionBuilder, 'contains')) {
throw new UnsupportedExpressionTypeException('contains');
@@ -164,55 +87,32 @@ public function contains($field, $value)
return $this->expressionBuilder->contains($field, $value);
}
- /**
- * @param string $field
- * @param mixed $value
- */
- public function notContains($field, $value)
+ public function notContains(string $field, mixed $value): mixed
{
throw new UnsupportedExpressionTypeException('notContains');
}
- /**
- * @param array $expressions
- *
- * @return CompositeExpression
- */
- public function andX(array $expressions)
+ public function andX(array $expressions): mixed
{
- return call_user_func_array(array($this->expressionBuilder, 'andX'), $expressions);
+ return $this->expressionBuilder->andX(...$expressions);
}
- /**
- * @param array $expressions
- */
- public function nandX(array $expressions)
+ public function nandX(array $expressions): mixed
{
throw new UnsupportedExpressionTypeException('nandX');
}
- /**
- * @param array $expressions
- *
- * @return CompositeExpression
- */
- public function orX(array $expressions)
+ public function orX(array $expressions): mixed
{
- return call_user_func_array(array($this->expressionBuilder, 'orX'), $expressions);
+ return $this->expressionBuilder->orX(...$expressions);
}
- /**
- * @param array $expressions
- */
- public function norX(array $expressions)
+ public function norX(array $expressions): mixed
{
throw new UnsupportedExpressionTypeException('norX');
}
- /**
- * @param array $expressions
- */
- public function xorX(array $expressions)
+ public function xorX(array $expressions): mixed
{
throw new UnsupportedExpressionTypeException('xorX');
}
diff --git a/src/Bridge/Doctrine/MongoDb/ExprBuilder.php b/src/Bridge/Doctrine/MongoDb/ExprBuilder.php
deleted file mode 100644
index 8d49666..0000000
--- a/src/Bridge/Doctrine/MongoDb/ExprBuilder.php
+++ /dev/null
@@ -1,228 +0,0 @@
-createExpr()->field($field)->equals(null);
- }
-
- /**
- * @param string $field
- * @param mixed $value
- *
- * @return array
- */
- public function eq($field, $value)
- {
- return $this->createExpr()->field($field)->equals($value);
- }
-
- /**
- * @param string $field
- * @param mixed $value
- *
- * @return array
- */
- public function neq($field, $value)
- {
- return $this->createExpr()->field($field)->notEqual($value);
- }
-
- /**
- * @param string $field
- * @param mixed $value
- *
- * @return array
- */
- public function gt($field, $value)
- {
- return $this->createExpr()->field($field)->gt($value);
- }
-
- /**
- * @param string $field
- * @param mixed $value
- *
- * @return array
- */
- public function gte($field, $value)
- {
- return $this->createExpr()->field($field)->gte($value);
- }
-
- /**
- * @param string $field
- * @param mixed $value
- *
- * @return array
- */
- public function lt($field, $value)
- {
- return $this->createExpr()->field($field)->lt($value);
- }
-
- /**
- * @param string $field
- * @param mixed $value
- *
- * @return array
- */
- public function lte($field, $value)
- {
- return $this->createExpr()->field($field)->lte($value);
- }
-
- /**
- * @param string $field
- * @param mixed $values
- *
- * @return array
- */
- public function in($field, array $values)
- {
- return $this->createExpr()->field($field)->in($values);
- }
-
- /**
- * @param string $field
- * @param mixed $values
- *
- * @return array
- */
- public function notIn($field, array $values)
- {
- return $this->createExpr()->field($field)->notIn($values);
- }
-
- /**
- * @param string $field
- * @param mixed $value
- *
- * @return array
- */
- public function contains($field, $value)
- {
- return $this->createExpr()->field($field)->equals(new \MongoRegex(sprintf('/.*%s.*/', $value)));
- }
-
- /**
- * @param string $field
- * @param mixed $value
- *
- * @return array
- */
- public function notContains($field, $value)
- {
- return $this->createExpr()->field($field)->equals(new \MongoRegex(sprintf('/^((?!%s).)*$/', $value)));
- }
-
- /**
- * @param array $expressions
- *
- * @return array
- */
- public function andX(array $expressions)
- {
- $expr = $this->createExpr();
- foreach ($expressions as $expression) {
- $expr->addAnd($expression);
- }
-
- return $expr;
- }
-
- /**
- * @param array $expressions
- */
- public function nandX(array $expressions)
- {
- throw new UnsupportedExpressionTypeException('nandX');
- }
-
- /**
- * @param array $expressions
- *
- * @return array
- */
- public function orX(array $expressions)
- {
- $expr = $this->createExpr();
- foreach ($expressions as $expression) {
- $expr->addOr($expression);
- }
-
- return $expr;
- }
-
- /**
- * @param array $expressions
- *
- * @return array
- */
- public function norX(array $expressions)
- {
- $expr = $this->createExpr();
- foreach ($expressions as $expression) {
- $expr->addNor($expression);
- }
-
- return $expr;
- }
-
- /**
- * @param array $expressions
- */
- public function xorX(array $expressions)
- {
- throw new UnsupportedExpressionTypeException('xorX');
- }
-}
diff --git a/src/Bridge/Doctrine/ORM/ExprAdapter.php b/src/Bridge/Doctrine/ORM/ExprAdapter.php
index c9cd2de..1e1ac12 100644
--- a/src/Bridge/Doctrine/ORM/ExprAdapter.php
+++ b/src/Bridge/Doctrine/ORM/ExprAdapter.php
@@ -1,216 +1,114 @@
expr = $expr;
}
- /**
- * @return int
- */
- public function getSupportedTokenType()
+ public function getSupportedTokenType(): int
{
return Lexer::T_ALL - Lexer::T_NOT_AND - Lexer::T_NOT_OR - Lexer::T_XOR;
}
- /**
- * @param $value
- * @param bool $isValue
- *
- * @return mixed
- */
- public function parameter($value, $isValue = false)
+ public function parameter(mixed $value, bool $isValue = false): mixed
{
return $isValue ? $this->expr->literal($value) : $value;
}
- /**
- * @param $value
- * @return Expr\Literal
- */
- public function string($value)
+ public function string(mixed $value): mixed
{
return $this->expr->literal($value);
}
- /**
- * @param string $field
- *
- * @return string
- */
- public function isNull($field)
+ public function isNull(string $field): mixed
{
return $this->expr->isNull($field);
}
- /**
- * @param string $field
- * @param mixed $value
- *
- * @return Expr\Comparison
- */
- public function eq($field, $value)
+ public function eq(string $field, mixed $value): mixed
{
return $this->expr->eq($field, $value);
}
- /**
- * @param string $field
- * @param mixed $value
- *
- * @return Expr\Comparison
- */
- public function neq($field, $value)
+ public function neq(string $field, mixed $value): mixed
{
return $this->expr->neq($field, $value);
}
- /**
- * @param string $field
- * @param mixed $value
- *
- * @return Expr\Comparison
- */
- public function gt($field, $value)
+ public function gt(string $field, mixed $value): mixed
{
return $this->expr->gt($field, $value);
}
- /**
- * @param string $field
- * @param mixed $value
- *
- * @return Expr\Comparison
- */
- public function gte($field, $value)
+ public function gte(string $field, mixed $value): mixed
{
return $this->expr->gte($field, $value);
}
- /**
- * @param string $field
- * @param mixed $value
- *
- * @return Expr\Comparison
- */
- public function lt($field, $value)
+ public function lt(string $field, mixed $value): mixed
{
return $this->expr->lt($field, $value);
}
- /**
- * @param string $field
- * @param mixed $value
- *
- * @return Expr\Comparison
- */
- public function lte($field, $value)
+ public function lte(string $field, mixed $value): mixed
{
return $this->expr->lte($field, $value);
}
- /**
- * @param string $field
- * @param mixed $values
- *
- * @return Expr\Func
- */
- public function in($field, array $values)
+ public function in(string $field, array $values): mixed
{
return $this->expr->in($field, $values);
}
- /**
- * @param string $field
- * @param mixed $values
- *
- * @return Expr\Func
- */
- public function notIn($field, array $values)
+ public function notIn(string $field, array $values): mixed
{
return $this->expr->notIn($field, $values);
}
- /**
- * @param string $field
- * @param mixed $value
- *
- * @return Expr\Comparison
- */
- public function contains($field, $value)
+ public function contains(string $field, mixed $value): mixed
{
return $this->expr->like($field, $value);
}
- /**
- * @param string $field
- * @param mixed $value
- *
- * @return Expr\Comparison
- */
- public function notContains($field, $value)
+ public function notContains(string $field, mixed $value): mixed
{
return $this->expr->notLike($field, $value);
}
- /**
- * @param array $expressions
- *
- * @return Expr\Andx
- */
- public function andX(array $expressions)
+ public function andX(array $expressions): mixed
{
- return call_user_func_array(array($this->expr, 'andX'), $expressions);
+ return $this->expr->andX(...$expressions);
}
- /**
- * @param array $expressions
- */
- public function nandX(array $expressions)
+ public function nandX(array $expressions): mixed
{
throw new UnsupportedExpressionTypeException('nandX');
}
- /**
- * @param array $expressions
- *
- * @return Expr\Orx
- */
- public function orX(array $expressions)
+ public function orX(array $expressions): mixed
{
- return call_user_func_array(array($this->expr, 'orX'), $expressions);
+ return $this->expr->orX(...$expressions);
}
- /**
- * @param array $expressions
- */
- public function norX(array $expressions)
+ public function norX(array $expressions): mixed
{
throw new UnsupportedExpressionTypeException('norX');
}
- /**
- * @param array $expressions
- */
- public function xorX(array $expressions)
+ public function xorX(array $expressions): mixed
{
throw new UnsupportedExpressionTypeException('xorX');
}
diff --git a/src/Bridge/MongoDB/ExprBuilder.php b/src/Bridge/MongoDB/ExprBuilder.php
new file mode 100644
index 0000000..209f9e2
--- /dev/null
+++ b/src/Bridge/MongoDB/ExprBuilder.php
@@ -0,0 +1,108 @@
+ null];
+ }
+
+ public function eq(string $field, mixed $value): mixed
+ {
+ return [$field => ['$eq' => $value]];
+ }
+
+ public function neq(string $field, mixed $value): mixed
+ {
+ return [$field => ['$ne' => $value]];
+ }
+
+ public function gt(string $field, mixed $value): mixed
+ {
+ return [$field => ['$gt' => $value]];
+ }
+
+ public function gte(string $field, mixed $value): mixed
+ {
+ return [$field => ['$gte' => $value]];
+ }
+
+ public function lt(string $field, mixed $value): mixed
+ {
+ return [$field => ['$lt' => $value]];
+ }
+
+ public function lte(string $field, mixed $value): mixed
+ {
+ return [$field => ['$lte' => $value]];
+ }
+
+ public function in(string $field, array $values): mixed
+ {
+ return [$field => ['$in' => $values]];
+ }
+
+ public function notIn(string $field, array $values): mixed
+ {
+ return [$field => ['$nin' => $values]];
+ }
+
+ public function contains(string $field, mixed $value): mixed
+ {
+ return [$field => ['$regex' => $value]];
+ }
+
+ public function notContains(string $field, mixed $value): mixed
+ {
+ return ['$not' => $this->contains($field, $value)];
+ }
+
+ public function andX(array $expressions): mixed
+ {
+ return ['$and' => $expressions];
+ }
+
+ // Not A AND B = Not A OR Not B
+ public function nandX(array $expressions): mixed
+ {
+ return $this->orX(array_map(static fn ($expression) => ['$not' => $expression], $expressions));
+ }
+
+ public function orX(array $expressions): mixed
+ {
+ return ['$or' => $expressions];
+ }
+
+ public function norX(array $expressions): mixed
+ {
+ return ['$nor' => $expressions];
+ }
+
+ public function xorX(array $expressions): mixed
+ {
+ throw new UnsupportedExpressionTypeException('xorX');
+ }
+}
diff --git a/src/Exception/Expr/UnsupportedExpressionTypeException.php b/src/Exception/Expr/UnsupportedExpressionTypeException.php
index 1f4064b..8f25a9d 100644
--- a/src/Exception/Expr/UnsupportedExpressionTypeException.php
+++ b/src/Exception/Expr/UnsupportedExpressionTypeException.php
@@ -1,29 +1,20 @@
expressionType = $expressionType;
}
- /**
- * @return string
- */
- public function getExpressionType()
+ public function getExpressionType(): string
{
return $this->expressionType;
}
diff --git a/src/Exception/Lexer/LexerException.php b/src/Exception/Lexer/LexerException.php
index cf51842..8eca046 100644
--- a/src/Exception/Lexer/LexerException.php
+++ b/src/Exception/Lexer/LexerException.php
@@ -1,7 +1,7 @@
tokenType = $tokenType;
}
- /**
- * @return string
- */
- public function getTokenType()
+ public function getTokenType(): string
{
return $this->tokenType;
}
diff --git a/src/Exception/Parser/ForbiddenTokenException.php b/src/Exception/Parser/ForbiddenTokenException.php
index ba679c7..0a664b7 100644
--- a/src/Exception/Parser/ForbiddenTokenException.php
+++ b/src/Exception/Parser/ForbiddenTokenException.php
@@ -1,23 +1,22 @@
allowedTokenTypes = $allowedTokenTypes;
}
/**
- * @return string
+ * @return string[]
*/
- public function getAllowedTokenTypes()
+ public function getAllowedTokenTypes(): array
{
return $this->allowedTokenTypes;
}
diff --git a/src/Exception/Parser/InvalidExpressionException.php b/src/Exception/Parser/InvalidExpressionException.php
index 5de241c..034b6d4 100644
--- a/src/Exception/Parser/InvalidExpressionException.php
+++ b/src/Exception/Parser/InvalidExpressionException.php
@@ -1,31 +1,21 @@
input = $input;
+ public function __construct(
+ private string $input,
+ string $message = '',
+ int $code = 0,
+ ?\Exception $previous = null,
+ ) {
+ parent::__construct('' !== $message ? $message : 'Invalid expression.', $code, $previous);
}
- /**
- * @return string
- */
- public function getInput()
+ public function getInput(): string
{
return $this->input;
}
diff --git a/src/Exception/Parser/ParserException.php b/src/Exception/Parser/ParserException.php
index e17525f..a4ff1e3 100644
--- a/src/Exception/Parser/ParserException.php
+++ b/src/Exception/Parser/ParserException.php
@@ -1,7 +1,7 @@
token = $token;
}
/**
- * @return array
+ * @return string[]
*/
- public function getToken()
+ public function getToken(): array
{
return $this->token;
}
diff --git a/src/Exception/Parser/UnexpectedTokenException.php b/src/Exception/Parser/UnexpectedTokenException.php
index c0970be..9eb9b87 100644
--- a/src/Exception/Parser/UnexpectedTokenException.php
+++ b/src/Exception/Parser/UnexpectedTokenException.php
@@ -1,23 +1,22 @@
expectedTokenTypes = $expectedTokenTypes;
}
/**
- * @return string
+ * @return string[]
*/
- public function getExpectedTokenTypes()
+ public function getExpectedTokenTypes(): array
{
return $this->expectedTokenTypes;
}
diff --git a/src/Exception/Parser/UnknowCompositeTypeException.php b/src/Exception/Parser/UnknowCompositeTypeException.php
deleted file mode 100644
index d9e2a36..0000000
--- a/src/Exception/Parser/UnknowCompositeTypeException.php
+++ /dev/null
@@ -1,32 +0,0 @@
-unknownType = $unknownType;
- }
-
- /**
- * @return string
- */
- public function getUnknownType()
- {
- return $this->unknownType;
- }
-}
diff --git a/src/Exception/Parser/UnknownCompositeTypeException.php b/src/Exception/Parser/UnknownCompositeTypeException.php
new file mode 100644
index 0000000..30fdde6
--- /dev/null
+++ b/src/Exception/Parser/UnknownCompositeTypeException.php
@@ -0,0 +1,22 @@
+unknownType;
+ }
+}
diff --git a/src/Exception/Parser/UnsupportedTokenTypeException.php b/src/Exception/Parser/UnsupportedTokenTypeException.php
index cdf0f55..0d07256 100644
--- a/src/Exception/Parser/UnsupportedTokenTypeException.php
+++ b/src/Exception/Parser/UnsupportedTokenTypeException.php
@@ -1,23 +1,22 @@
supportedTokenTypes = $supportedTokenTypes;
}
/**
- * @return string
+ * @return string[]
*/
- public function getSupportedTokenTypes()
+ public function getSupportedTokenTypes(): array
{
return $this->supportedTokenTypes;
}
diff --git a/src/Expr/ClosureExpressionBuilder.php b/src/Expr/ClosureExpressionBuilder.php
index 89f1798..91a550e 100644
--- a/src/Expr/ClosureExpressionBuilder.php
+++ b/src/Expr/ClosureExpressionBuilder.php
@@ -1,24 +1,20 @@
$accessor();
+ return $object->{$accessor}();
}
// __call should be triggered for get.
- $accessor = $accessors[0] . $field;
+ $accessor = $accessors[0].$field;
if (method_exists($object, '__call')) {
- return $object->$accessor();
+ return $object->{$accessor}();
}
if ($object instanceof \ArrayAccess) {
return $object[$field];
}
- if (isset($object->$field)) {
- return $object->$field;
+ if (isset($object->{$field})) {
+ return $object->{$field};
}
// camelcase field name to support different variable naming conventions
- $ccField = preg_replace_callback('/_(.?)/', function ($matches) {
- return strtoupper($matches[1]);
- }, $field);
+ $ccField = preg_replace_callback('/_(.?)/', static fn ($matches) => strtoupper($matches[1]), $field);
foreach ($accessors as $accessor) {
$accessor .= $ccField;
-
if (!method_exists($object, $accessor)) {
continue;
}
- return $object->$accessor();
+ return $object->{$accessor}();
}
- return $object->$field;
+ return $object->{$field};
}
- /**
- * @return int
- */
- public function getSupportedTokenType()
+ public function getSupportedTokenType(): int
{
return Lexer::T_ALL;
}
/**
- * @param $value
- * @param bool $isValue
- *
- * @return mixed
+ * @param bool $isValue
+ * @param mixed $value
*/
- public function parameter($value, $isValue = false)
+ public function parameter($value, $isValue = false): mixed
{
return $value;
}
- /**
- * @param $value
- * @return mixed
- */
- public function string($value)
+ public function string(mixed $value): mixed
{
return $value;
}
- /**
- * @param string $field
- *
- * @return callable
- */
- public function isNull($field)
+ public function isNull(string $field): mixed
{
- return function ($object) use ($field) {
- return ClosureExpressionBuilder::getObjectFieldValue($object, $field) === null;
- };
+ return static fn ($object) => null === ClosureExpressionBuilder::getObjectFieldValue($object, $field);
}
- /**
- * @param string $field
- * @param mixed $value
- *
- * @return callable
- */
- public function eq($field, $value)
+ public function eq(string $field, mixed $value): mixed
{
- return function ($object) use ($field, $value) {
- return ClosureExpressionBuilder::getObjectFieldValue($object, $field) === $value;
- };
+ return static fn ($object) => ClosureExpressionBuilder::getObjectFieldValue($object, $field) === $value;
}
- /**
- * @param string $field
- * @param mixed $value
- *
- * @return callable
- */
- public function neq($field, $value)
+ public function neq(string $field, mixed $value): mixed
{
- return function ($object) use ($field, $value) {
- return ClosureExpressionBuilder::getObjectFieldValue($object, $field) !== $value;
- };
+ return static fn ($object) => ClosureExpressionBuilder::getObjectFieldValue($object, $field) !== $value;
}
- /**
- * @param string $field
- * @param mixed $value
- *
- * @return callable
- */
- public function gt($field, $value)
+ public function gt(string $field, mixed $value): mixed
{
- return function ($object) use ($field, $value) {
- return ClosureExpressionBuilder::getObjectFieldValue($object, $field) > $value;
- };
+ return static fn ($object) => ClosureExpressionBuilder::getObjectFieldValue($object, $field) > $value;
}
- /**
- * @param string $field
- * @param mixed $value
- *
- * @return callable
- */
- public function gte($field, $value)
+ public function gte(string $field, mixed $value): mixed
{
- return function ($object) use ($field, $value) {
- return ClosureExpressionBuilder::getObjectFieldValue($object, $field) >= $value;
- };
+ return static fn ($object) => ClosureExpressionBuilder::getObjectFieldValue($object, $field) >= $value;
}
- /**
- * @param string $field
- * @param mixed $value
- *
- * @return callable
- */
- public function lt($field, $value)
+ public function lt(string $field, mixed $value): mixed
{
- return function ($object) use ($field, $value) {
- return ClosureExpressionBuilder::getObjectFieldValue($object, $field) < $value;
- };
+ return static fn ($object) => ClosureExpressionBuilder::getObjectFieldValue($object, $field) < $value;
}
- /**
- * @param string $field
- * @param mixed $value
- *
- * @return callable
- */
- public function lte($field, $value)
+ public function lte(string $field, mixed $value): mixed
{
- return function ($object) use ($field, $value) {
- return ClosureExpressionBuilder::getObjectFieldValue($object, $field) <= $value;
- };
+ return static fn ($object) => ClosureExpressionBuilder::getObjectFieldValue($object, $field) <= $value;
}
- /**
- * @param string $field
- * @param mixed $values
- *
- * @return callable
- */
- public function in($field, array $values)
+ public function in(string $field, array $values): mixed
{
- return function ($object) use ($field, $values) {
- return in_array(ClosureExpressionBuilder::getObjectFieldValue($object, $field), $values);
- };
+ return static fn ($object) => \in_array(ClosureExpressionBuilder::getObjectFieldValue($object, $field), $values, true);
}
- /**
- * @param string $field
- * @param mixed $values
- *
- * @return callable
- */
- public function notIn($field, array $values)
+ public function notIn(string $field, array $values): mixed
{
- return function ($object) use ($field, $values) {
- return !in_array(ClosureExpressionBuilder::getObjectFieldValue($object, $field), $values);
- };
+ return static fn ($object) => !\in_array(ClosureExpressionBuilder::getObjectFieldValue($object, $field), $values, true);
}
- /**
- * @param string $field
- * @param mixed $value
- *
- * @return callable
- */
- public function contains($field, $value)
+ public function contains(string $field, mixed $value): mixed
{
- return function ($object) use ($field, $value) {
- return false !== strpos(ClosureExpressionBuilder::getObjectFieldValue($object, $field), $value);
- };
+ return static fn ($object) => str_contains(ClosureExpressionBuilder::getObjectFieldValue($object, $field), $value);
}
- /**
- * @param string $field
- * @param mixed $value
- *
- * @return callable
- */
- public function notContains($field, $value)
+ public function notContains(string $field, mixed $value): mixed
{
- $self = $this;
- return function ($object) use ($self, $field, $value) {
- $contains = $self->contains($field, $value);
- return !$contains($object);
- };
+ return static fn ($object) => !str_contains(ClosureExpressionBuilder::getObjectFieldValue($object, $field), $value);
}
- /**
- * @param array $expressions
- *
- * @return callable
- */
- public function andX(array $expressions)
+ public function andX(array $expressions): mixed
{
- return function ($object) use ($expressions) {
+ return static function ($object) use ($expressions) {
foreach ($expressions as $expression) {
if (!$expression($object)) {
return false;
@@ -254,28 +144,16 @@ public function andX(array $expressions)
};
}
- /**
- * @param array $expressions
- *
- * @return callable
- */
- public function nandX(array $expressions)
+ public function nandX(array $expressions): mixed
{
$self = $this;
- return function ($object) use ($self, $expressions) {
- $andX = $self->andX($expressions);
- return !$andX($object);
- };
+
+ return static fn ($object) => !$self->andX($expressions)($object);
}
- /**
- * @param array $expressions
- *
- * @return callable
- */
- public function orX(array $expressions)
+ public function orX(array $expressions): mixed
{
- return function ($object) use ($expressions) {
+ return static function ($object) use ($expressions) {
foreach ($expressions as $expression) {
if ($expression($object)) {
return true;
@@ -286,37 +164,26 @@ public function orX(array $expressions)
};
}
- /**
- * @param array $expressions
- *
- * @return callable
- */
- public function norX(array $expressions)
+ public function norX(array $expressions): mixed
{
$self = $this;
- return function ($object) use ($self, $expressions) {
- $orX = $self->orX($expressions);
- return !$orX($object);
- };
+
+ return static fn ($object) => !$self->orX($expressions)($object);
}
- /**
- * @param array $expressions
- *
- * @return callable
- */
- public function xorX(array $expressions)
+ public function xorX(array $expressions): mixed
{
- return function ($object) use ($expressions) {
+ return static function ($object) use ($expressions) {
$result = 0;
foreach ($expressions as $expression) {
if ($expression($object)) {
- $result++;
+ ++$result;
}
}
- $countExpressions = count($expressions);
- return $result === 1 | (2 < $countExpressions & $result === $countExpressions);
+ $countExpressions = \count($expressions);
+
+ return 1 === $result | (2 < $countExpressions & $result === $countExpressions);
};
}
}
diff --git a/src/Expr/ExpressionBuilderInterface.php b/src/Expr/ExpressionBuilderInterface.php
index 5cbce80..38e0743 100644
--- a/src/Expr/ExpressionBuilderInterface.php
+++ b/src/Expr/ExpressionBuilderInterface.php
@@ -1,116 +1,49 @@
comparisonHtmlBuilder = $comparisonHtmlBuilder ?: function ($field, $operator, $value) {
- return sprintf('%s %s %s
', $field, $operator, $value);
- };
- $this->compositeHtmlBuilder = $compositeHtmlBuilder ?: function (array $expressions, $type) {
- return str_replace(
- array('{type}', '{expressions}'),
- array($type, implode('', $expressions)),
- ''
- );
- };
+ $this->comparisonHtmlBuilder = $comparisonHtmlBuilder ?: static fn ($field, $operator, $value) => sprintf('%s %s %s
', $field, $operator, $value);
+ $this->compositeHtmlBuilder = $compositeHtmlBuilder ?: static fn (array $expressions, $type) => str_replace(
+ ['{type}', '{expressions}'],
+ [$type, implode('', $expressions)],
+ ''
+ );
}
- /**
- * @return int
- */
- public function getSupportedTokenType()
+ public function getSupportedTokenType(): int
{
return Lexer::T_ALL;
}
- /**
- * @param $value
- * @param bool $isValue
- *
- * @return mixed
- */
- public function parameter($value, $isValue = false)
+ public function parameter(mixed $value, bool $isValue = false): mixed
{
return $value;
}
- /**
- * @param $value
- * @return mixed
- */
- public function string($value)
+ public function string(mixed $value): mixed
{
- return '"' . $value . '"';
+ return '"'.$value.'"';
}
- /**
- * @param string $field
- *
- * @return string
- */
- public function isNull($field)
+ public function isNull(string $field): mixed
{
- return call_user_func_array($this->comparisonHtmlBuilder, array($field, 'is', 'null'));
+ return ($this->comparisonHtmlBuilder)($field, 'is', 'null');
}
- /**
- * @param string $field
- * @param mixed $value
- *
- * @return string
- */
- public function eq($field, $value)
+ public function eq(string $field, mixed $value): mixed
{
- return call_user_func_array($this->comparisonHtmlBuilder, array($field, '=', $value));
+ return ($this->comparisonHtmlBuilder)($field, '=', $value);
}
- /**
- * @param string $field
- * @param mixed $value
- *
- * @return string
- */
- public function neq($field, $value)
+ public function neq(string $field, mixed $value): mixed
{
- return call_user_func_array($this->comparisonHtmlBuilder, array($field, '≠', $value));
+ return ($this->comparisonHtmlBuilder)($field, '≠', $value);
}
- /**
- * @param string $field
- * @param mixed $value
- *
- * @return string
- */
- public function gt($field, $value)
+ public function gt(string $field, mixed $value): mixed
{
- return call_user_func_array($this->comparisonHtmlBuilder, array($field, '>', $value));
+ return ($this->comparisonHtmlBuilder)($field, '>', $value);
}
- /**
- * @param string $field
- * @param mixed $value
- *
- * @return string
- */
- public function gte($field, $value)
+ public function gte(string $field, mixed $value): mixed
{
- return call_user_func_array($this->comparisonHtmlBuilder, array($field, '≥', $value));
+ return ($this->comparisonHtmlBuilder)($field, '≥', $value);
}
- /**
- * @param string $field
- * @param mixed $value
- *
- * @return string
- */
- public function lt($field, $value)
+ public function lt(string $field, mixed $value): mixed
{
- return call_user_func_array($this->comparisonHtmlBuilder, array($field, '<', $value));
+ return ($this->comparisonHtmlBuilder)($field, '<', $value);
}
- /**
- * @param string $field
- * @param mixed $value
- *
- * @return string
- */
- public function lte($field, $value)
+ public function lte(string $field, mixed $value): mixed
{
- return call_user_func_array($this->comparisonHtmlBuilder, array($field, '≤', $value));
+ return ($this->comparisonHtmlBuilder)($field, '≤', $value);
}
- /**
- * @param string $field
- * @param mixed $values
- *
- * @return string
- */
- public function in($field, array $values)
+ public function in(string $field, array $values): mixed
{
- return call_user_func_array($this->comparisonHtmlBuilder, array($field, 'value in', implode(', ', $values)));
+ return ($this->comparisonHtmlBuilder)($field, 'value in', implode(', ', $values));
}
- /**
- * @param string $field
- * @param mixed $values
- *
- * @return string
- */
- public function notIn($field, array $values)
+ public function notIn(string $field, array $values): mixed
{
- return call_user_func_array($this->comparisonHtmlBuilder, array($field, 'value not in', implode(', ', $values)));
+ return ($this->comparisonHtmlBuilder)($field, 'value not in', implode(', ', $values));
}
- /**
- * @param string $field
- * @param mixed $value
- *
- * @return string
- */
- public function contains($field, $value)
+ public function contains(string $field, mixed $value): mixed
{
- return call_user_func_array($this->comparisonHtmlBuilder, array($field, 'contains', $value));
+ return ($this->comparisonHtmlBuilder)($field, 'contains', $value);
}
- /**
- * @param string $field
- * @param mixed $value
- *
- * @return string
- */
- public function notContains($field, $value)
+ public function notContains(string $field, mixed $value): mixed
{
- return call_user_func_array($this->comparisonHtmlBuilder, array($field, 'notContains', $value));
+ return ($this->comparisonHtmlBuilder)($field, 'notContains', $value);
}
- /**
- * @param array $expressions
- *
- * @return string
- */
- public function andX(array $expressions)
+ public function andX(array $expressions): mixed
{
- return call_user_func_array($this->compositeHtmlBuilder, array($expressions, 'and'));
+ return ($this->compositeHtmlBuilder)($expressions, 'and');
}
- /**
- * @param array $expressions
- *
- * @return string
- */
- public function nandX(array $expressions)
+ public function nandX(array $expressions): mixed
{
- return call_user_func_array($this->compositeHtmlBuilder, array($expressions, 'not-and'));
+ return ($this->compositeHtmlBuilder)($expressions, 'not-and');
}
- /**
- * @param array $expressions
- *
- * @return string
- */
- public function orX(array $expressions)
+ public function orX(array $expressions): mixed
{
- return call_user_func_array($this->compositeHtmlBuilder, array($expressions, 'or'));
+ return ($this->compositeHtmlBuilder)($expressions, 'or');
}
- /**
- * @param array $expressions
- *
- * @return string
- */
- public function norX(array $expressions)
+ public function norX(array $expressions): mixed
{
- return call_user_func_array($this->compositeHtmlBuilder, array($expressions, 'not-or'));
+ return ($this->compositeHtmlBuilder)($expressions, 'not-or');
}
- /**
- * @param array $expressions
- *
- * @return string
- */
- public function xorX(array $expressions)
+ public function xorX(array $expressions): mixed
{
- return call_user_func_array($this->compositeHtmlBuilder, array($expressions, 'exclusive-or'));
+ return ($this->compositeHtmlBuilder)($expressions, 'exclusive-or');
}
}
diff --git a/src/Expr/MapperExpressionBuilder.php b/src/Expr/MapperExpressionBuilder.php
index fc6d6ae..f983da8 100644
--- a/src/Expr/MapperExpressionBuilder.php
+++ b/src/Expr/MapperExpressionBuilder.php
@@ -1,141 +1,131 @@
expressionBuilder = $expressionBuilder;
- $this->fieldMapping = $fieldMapping;
- }
+ public function __construct(
+ private ExpressionBuilderInterface $expressionBuilder,
+ private array $fieldMapping = [],
+ ) {}
- public function getSupportedTokenType()
+ public function getSupportedTokenType(): int
{
return $this->expressionBuilder->getSupportedTokenType();
}
- public function parameter($value, $isValue = false)
+ public function parameter(mixed $value, bool $isValue = false): mixed
{
return $this->expressionBuilder->parameter($value, $isValue);
}
- public function string($value)
+ public function string(mixed $value): mixed
{
return $this->expressionBuilder->string($value);
}
- public function isNull($field)
+ public function isNull(string $field): mixed
{
return $this->expressionBuilder->isNull($this->mapField($field));
}
- public function eq($field, $value)
+ public function eq(string $field, mixed $value): mixed
{
return $this->expressionBuilder->eq($this->mapField($field), $value);
}
- public function neq($field, $value)
+ public function neq(string $field, mixed $value): mixed
{
return $this->expressionBuilder->neq($this->mapField($field), $value);
}
- public function gt($field, $value)
+ public function gt(string $field, mixed $value): mixed
{
return $this->expressionBuilder->gt($this->mapField($field), $value);
}
- public function gte($field, $value)
+ public function gte(string $field, mixed $value): mixed
{
return $this->expressionBuilder->gte($this->mapField($field), $value);
}
- public function lt($field, $value)
+ public function lt(string $field, mixed $value): mixed
{
return $this->expressionBuilder->lt($this->mapField($field), $value);
}
- public function lte($field, $value)
+ public function lte(string $field, mixed $value): mixed
{
return $this->expressionBuilder->lte($this->mapField($field), $value);
}
- public function in($field, array $values)
+ public function in(string $field, array $values): mixed
{
return $this->expressionBuilder->in($this->mapField($field), $values);
}
- public function notIn($field, array $values)
+ public function notIn(string $field, array $values): mixed
{
return $this->expressionBuilder->notIn($this->mapField($field), $values);
}
- public function contains($field, $value)
+ public function contains(string $field, mixed $value): mixed
{
return $this->expressionBuilder->contains($this->mapField($field), $value);
}
- public function notContains($field, $value)
+ public function notContains(string $field, mixed $value): mixed
{
return $this->expressionBuilder->notContains($this->mapField($field), $value);
}
- public function andX(array $expressions)
+ public function andX(array $expressions): mixed
{
return $this->expressionBuilder->andX($expressions);
}
- public function nandX(array $expressions)
+ public function nandX(array $expressions): mixed
{
return $this->expressionBuilder->nandX($expressions);
}
- public function orX(array $expressions)
+ public function orX(array $expressions): mixed
{
return $this->expressionBuilder->orX($expressions);
}
- public function norX(array $expressions)
+ public function norX(array $expressions): mixed
{
return $this->expressionBuilder->norX($expressions);
}
- public function xorX(array $expressions)
+ public function xorX(array $expressions): mixed
{
return $this->expressionBuilder->xorX($expressions);
}
- private function mapField($field)
+ private function mapField(mixed $field): mixed
{
if (
- is_array($field) ||
- is_object($field) && !method_exists($field, '__toString')
+ \is_array($field)
+ || \is_object($field) && !method_exists($field, '__toString')
) {
return $field;
}
- if (array_key_exists((string)$field, $this->fieldMapping)) {
- return sprintf($this->fieldMapping[(string)$field], $field);
+ if (\array_key_exists((string) $field, $this->fieldMapping)) {
+ return sprintf($this->fieldMapping[(string) $field], $field);
}
- if (array_key_exists('*', $this->fieldMapping)) {
+ if (\array_key_exists('*', $this->fieldMapping)) {
return sprintf($this->fieldMapping['*'], $field);
}
return $field;
}
-}
\ No newline at end of file
+}
diff --git a/src/Lexer.php b/src/Lexer.php
index 980b584..82ce0d8 100644
--- a/src/Lexer.php
+++ b/src/Lexer.php
@@ -1,5 +1,7 @@
';
+ }
+ if ($tokenType & self::T_GREATER_THAN_EQUALS) {
+ $tokenSyntax[] = '≥ or >=';
+ }
+ if ($tokenType & self::T_LOWER_THAN) {
+ $tokenSyntax[] = '<';
+ }
+ if ($tokenType & self::T_LOWER_THAN_EQUALS) {
+ $tokenSyntax[] = '≤ or <=';
+ }
+
+ // Composite operator
+ if ($tokenType & self::T_AND) {
+ $tokenSyntax[] = '&';
+ }
+ if ($tokenType & self::T_NOT_AND) {
+ $tokenSyntax[] = '!&';
+ }
+ if ($tokenType & self::T_OR) {
+ $tokenSyntax[] = '|';
+ }
+ if ($tokenType & self::T_NOT_OR) {
+ $tokenSyntax[] = '!|';
+ }
+ if ($tokenType & self::T_XOR) {
+ $tokenSyntax[] = '⊕ or ^|';
+ }
+
+ // Brace
+ if ($tokenType & self::T_OPEN_PARENTHESIS) {
+ $tokenSyntax[] = '(';
+ }
+ if ($tokenType & self::T_CLOSE_PARENTHESIS) {
+ $tokenSyntax[] = ')';
+ }
+ if ($tokenType & self::T_OPEN_SQUARE_BRACKET) {
+ $tokenSyntax[] = '[';
+ }
+ if ($tokenType & self::T_NOT_OPEN_SQUARE_BRACKET) {
+ $tokenSyntax[] = '![';
+ }
+ if ($tokenType & self::T_CLOSE_SQUARE_BRACKET) {
+ $tokenSyntax[] = ']';
+ }
+ if ($tokenType & self::T_DOUBLE_OPEN_CURLY_BRACKET) {
+ $tokenSyntax[] = '{{';
+ }
+ if ($tokenType & self::T_NOT_DOUBLE_OPEN_CURLY_BRACKET) {
+ $tokenSyntax[] = '!{{';
+ }
+ if ($tokenType & self::T_DOUBLE_CLOSE_CURLY_BRACKET) {
+ $tokenSyntax[] = '}}';
+ }
+
+ return $tokenSyntax;
+ }
/**
* @return array
*/
protected function getCatchablePatterns()
{
- return array(
+ return [
"'(?:[^']|'')*'", // quoted strings
'"(?:[^"]|"")*"', // quoted strings
'\^\||⊕|!&|&|!\||\|', // Composite operator
'≤|≥|≠|<=|>=|!=|<|>|=|\[|!\[|\]|!{{|{{|}}', // Comparison operator
'[a-z_][a-z0-9_\.\-]*', // identifier or qualified name
'(?:[+-]?[0-9]*(?:[\.][0-9]+)*)', // numbers
- );
+ //'(?:[+-]?(?:(?:(?:[0-9]+|(?:[0-9]*[\.][0-9]+)|(?:[0-9]+[\.][0-9]*))[eE][+-]?[0-9]+)|(?:[0-9]*[\.][0-9]+)|(?:[0-9]+[\.][0-9]*)))', // number extended all float (.5 / 1.5 / -1.2e3)
+ ];
}
/**
@@ -67,10 +163,10 @@ protected function getCatchablePatterns()
*/
protected function getNonCatchablePatterns()
{
- return array(
+ return [
'\s+',
'(.)',
- );
+ ];
}
/**
@@ -84,209 +180,156 @@ protected function getType(&$value)
{
switch (true) {
// Punctuation
- case ($value[0] === ','):
+ case ',' === $value[0]:
$type = self::T_COMMA;
+
break;
- // Recognize numeric values
- case (is_numeric($value)):
- if (strpos($value, '.') !== false || stripos($value, 'e') !== false) {
- $value = (float)$value;
+ // Recognize numeric values
+ case is_numeric($value):
+ if (str_contains($value, '.') || false !== stripos($value, 'e')) {
+ $value = (float) $value;
$type = self::T_FLOAT;
+
break;
}
- $value = (int)$value;
+ $value = (int) $value;
$type = self::T_INTEGER;
+
break;
- // Recognize quoted strings
- case ($value[0] === '"'):
- $value = str_replace('""', '"', substr($value, 1, strlen($value) - 2));
+ // Recognize quoted strings
+ case '"' === $value[0]:
+ $value = str_replace('""', '"', substr($value, 1, \strlen($value) - 2));
$type = self::T_STRING;
+
break;
- case ($value[0] === "'"):
- $value = str_replace("''", "'", substr($value, 1, strlen($value) - 2));
+
+ case "'" === $value[0]:
+ $value = str_replace("''", "'", substr($value, 1, \strlen($value) - 2));
$type = self::T_STRING;
+
break;
- case (preg_match('/[a-z_][a-z0-9_]*/i', $value)):
+ case preg_match('/[a-z_][a-z0-9_]*/i', $value):
$type = self::T_INPUT_PARAMETER;
+
break;
- // Comparison operator
- case ($value === '='):
+ // Comparison operator
+ case '=' === $value:
$type = self::T_EQUALS;
+
break;
- case ($value === '≠'):
- case ($value === '!='):
+
+ case '≠' === $value:
+ case '!=' === $value:
$value = '≠';
$type = self::T_NOT_EQUALS;
+
break;
- case ($value === '>'):
+
+ case '>' === $value:
$type = self::T_GREATER_THAN;
+
break;
- case ($value === '>='):
- case ($value === '≥'):
+
+ case '>=' === $value:
+ case '≥' === $value:
$value = '≥';
$type = self::T_GREATER_THAN_EQUALS;
+
break;
- case ($value === '<'):
+
+ case '<' === $value:
$type = self::T_LOWER_THAN;
+
break;
- case ($value === '<='):
- case ($value === '≤'):
+
+ case '<=' === $value:
+ case '≤' === $value:
$value = '≤';
$type = self::T_LOWER_THAN_EQUALS;
+
break;
- // Composite operator
- case ($value === '&'):
+ // Composite operator
+ case '&' === $value:
$type = self::T_AND;
+
break;
- case ($value === '!&'):
+
+ case '!&' === $value:
$type = self::T_NOT_AND;
+
break;
- case ($value === '|'):
+
+ case '|' === $value:
$type = self::T_OR;
+
break;
- case ($value === '!|'):
+
+ case '!|' === $value:
$type = self::T_NOT_OR;
+
break;
- case ($value === '^|'):
- case ($value === '⊕'):
+
+ case '^|' === $value:
+ case '⊕' === $value:
$value = '⊕';
$type = self::T_XOR;
+
break;
- // Brace
- case ($value === '('):
+ // Brace
+ case '(' === $value:
$type = self::T_OPEN_PARENTHESIS;
+
break;
- case ($value === ')'):
+
+ case ')' === $value:
$type = self::T_CLOSE_PARENTHESIS;
+
break;
- case ($value === '['):
+
+ case '[' === $value:
$type = self::T_OPEN_SQUARE_BRACKET;
+
break;
- case ($value === '!['):
+
+ case '![' === $value:
$type = self::T_NOT_OPEN_SQUARE_BRACKET;
+
break;
- case ($value === ']'):
+
+ case ']' === $value:
$type = self::T_CLOSE_SQUARE_BRACKET;
+
break;
- case ($value === '{{'):
+
+ case '{{' === $value:
$type = self::T_DOUBLE_OPEN_CURLY_BRACKET;
+
break;
- case ($value === '!{{'):
+
+ case '!{{' === $value:
$type = self::T_NOT_DOUBLE_OPEN_CURLY_BRACKET;
+
break;
- case ($value === '}}'):
+
+ case '}}' === $value:
$type = self::T_DOUBLE_CLOSE_CURLY_BRACKET;
+
break;
- // Default
+ // Default
default:
throw new UnknownTokenTypeException($value);
}
return $type;
}
-
- /**
- * @param $tokenType
- *
- * @return array
- */
- public static function getTokenSyntax($tokenType)
- {
- $tokenSyntax = array();
- // Punctuation
- if ($tokenType & self::T_COMMA) {
- $tokenSyntax[] = ',';
- }
-
- // Recognize numeric values
- if ($tokenType & self::T_FLOAT) {
- $tokenSyntax[] = 'simple float';
- }
- if ($tokenType & self::T_INTEGER) {
- $tokenSyntax[] = 'simple integer';
- }
- if ($tokenType & self::T_INPUT_PARAMETER) {
- $tokenSyntax[] = '/[a-z_][a-z0-9_]*/';
- }
-
- // Recognize quoted strings
- if ($tokenType & self::T_STRING) {
- $tokenSyntax[] = '"value" or \'value\'';
- }
-
- // Comparison operator
- if ($tokenType & self::T_EQUALS) {
- $tokenSyntax[] = '=';
- }
- if ($tokenType & self::T_NOT_EQUALS) {
- $tokenSyntax[] = '≠ or !=';
- }
- if ($tokenType & self::T_GREATER_THAN) {
- $tokenSyntax[] = '>';
- }
- if ($tokenType & self::T_GREATER_THAN_EQUALS) {
- $tokenSyntax[] = '≥ or >=';
- }
- if ($tokenType & self::T_LOWER_THAN) {
- $tokenSyntax[] = '<';
- }
- if ($tokenType & self::T_LOWER_THAN_EQUALS) {
- $tokenSyntax[] = '≤ or <=';
- }
-
- // Composite operator
- if ($tokenType & self::T_AND) {
- $tokenSyntax[] = '&';
- }
- if ($tokenType & self::T_NOT_AND) {
- $tokenSyntax[] = '!&';
- }
- if ($tokenType & self::T_OR) {
- $tokenSyntax[] = '|';
- }
- if ($tokenType & self::T_NOT_OR) {
- $tokenSyntax[] = '!|';
- }
- if ($tokenType & self::T_XOR) {
- $tokenSyntax[] = '⊕ or ^|';
- }
-
- // Brace
- if ($tokenType & self::T_OPEN_PARENTHESIS) {
- $tokenSyntax[] = '(';
- }
- if ($tokenType & self::T_CLOSE_PARENTHESIS) {
- $tokenSyntax[] = ')';
- }
- if ($tokenType & self::T_OPEN_SQUARE_BRACKET) {
- $tokenSyntax[] = '[';
- }
- if ($tokenType & self::T_NOT_OPEN_SQUARE_BRACKET) {
- $tokenSyntax[] = '![';
- }
- if ($tokenType & self::T_CLOSE_SQUARE_BRACKET) {
- $tokenSyntax[] = ']';
- }
- if ($tokenType & self::T_DOUBLE_OPEN_CURLY_BRACKET) {
- $tokenSyntax[] = '{{';
- }
- if ($tokenType & self::T_NOT_DOUBLE_OPEN_CURLY_BRACKET) {
- $tokenSyntax[] = '!{{';
- }
- if ($tokenType & self::T_DOUBLE_CLOSE_CURLY_BRACKET) {
- $tokenSyntax[] = '}}';
- }
-
- return $tokenSyntax;
- }
}
diff --git a/src/Parser.php b/src/Parser.php
index e7dbc97..44bdb0d 100644
--- a/src/Parser.php
+++ b/src/Parser.php
@@ -1,5 +1,7 @@
15,
Lexer::T_NOT_AND => 14,
Lexer::T_OR => 10,
Lexer::T_XOR => 9,
Lexer::T_NOT_OR => 8,
- );
+ ];
- /**
- * @var int Keep the lexer current index
- */
- public $lexerIndex = 0;
+ private Lexer $lexer;
- /**
- * @var Lexer
- */
- private $lexer;
-
- /**
- * @var ExpressionBuilderInterface
- */
- private $expressionBuilder;
+ private ExpressionBuilderInterface $expressionBuilder;
/**
* @var int Bitwise of all allowed operator. Default was Lexer::T_ALL
*/
- private $allowedTokenType;
+ private int $allowedTokenType;
/**
- * @var int Bitwise of ExpressionBuilder supported operator.
+ * @var int bitwise of ExpressionBuilder supported operator
*/
- private $supportedTokenType;
+ private int $supportedTokenType;
- /**
- * @param ExpressionBuilderInterface $expressionBuilder
- */
public function __construct(ExpressionBuilderInterface $expressionBuilder)
{
$this->lexer = new Lexer();
@@ -59,28 +52,11 @@ public function __construct(ExpressionBuilderInterface $expressionBuilder)
}
/**
- * @return int
- */
- public function getAllowedTokenType()
- {
- return $this->allowedTokenType;
- }
-
- /**
- * @param $input
- * @param null $allowedTokenType
- *
- * @return mixed
- *
* @throws InvalidExpressionException
*/
- public function parse($input, $allowedTokenType = null)
+ public function parse(string $input, ?int $allowedTokenType = null): mixed
{
- if (null !== $allowedTokenType && !is_integer($allowedTokenType)) {
- throw new \InvalidArgumentException('Allowed operator must be an integer.');
- }
-
- $this->allowedTokenType = $allowedTokenType ?: Lexer::T_ALL;
+ $this->allowedTokenType = null !== $allowedTokenType ? $allowedTokenType : Lexer::T_ALL;
$this->supportedTokenType = $this->expressionBuilder->getSupportedTokenType();
try {
@@ -96,19 +72,15 @@ public function parse($input, $allowedTokenType = null)
}
/**
- * @param null $previousExpression
- *
- * @return mixed
- *
* @throws ForbiddenTokenException
* @throws UnexpectedTokenException
* @throws UnsupportedTokenTypeException
*/
- private function getExpression($previousExpression = null)
+ private function getExpression(mixed $previousExpression = null): mixed
{
$expression = $previousExpression ?: null;
$expectedTokenType = null !== $previousExpression ? Lexer::T_COMPOSITE : Lexer::T_OPEN_PARENTHESIS | Lexer::T_INPUT_PARAMETER;
- $expressions = array();
+ $expressions = [];
$tokenPrecedence = null;
$hasOpenParenthesis = false;
@@ -123,7 +95,7 @@ private function getExpression($previousExpression = null)
while ($currentToken = $this->getNextToken()) {
$currentTokenType = $currentToken['type'];
$currentTokenIndex = $this->lexerIndex;
- $this->lexerIndex++;
+ ++$this->lexerIndex;
if (!($this->supportedTokenType & $currentTokenType)) {
throw new UnsupportedTokenTypeException($currentToken, $this->lexer->getTokenSyntax($this->supportedTokenType));
@@ -142,7 +114,9 @@ private function getExpression($previousExpression = null)
$expression = $this->getExpression();
$hasOpenParenthesis = true;
$expectedTokenType = Lexer::T_CLOSE_PARENTHESIS;
+
break;
+
case Lexer::T_CLOSE_PARENTHESIS:
if (!$hasOpenParenthesis) {
$this->lexerIndex = $currentTokenIndex;
@@ -153,16 +127,24 @@ private function getExpression($previousExpression = null)
}
$hasOpenParenthesis = false;
$expectedTokenType = Lexer::T_COMPOSITE | Lexer::T_CLOSE_PARENTHESIS;
+
break;
+
case Lexer::T_COMMA:
- $expectedTokenType = Lexer::T_OPERANDE;
+ $expectedTokenType = Lexer::T_OPERAND;
+
break;
+
case Lexer::T_INPUT_PARAMETER:
$currentTokenValue = $this->expressionBuilder->parameter($currentToken['value'], null !== $comparisonFirstOperande);
+
+ // no break
case Lexer::T_STRING:
if (!isset($currentTokenValue)) {
$currentTokenValue = $this->expressionBuilder->string($currentToken['value']);
}
+
+ // no break
case Lexer::T_INTEGER:
case Lexer::T_FLOAT:
if (!isset($currentTokenValue)) {
@@ -172,13 +154,15 @@ private function getExpression($previousExpression = null)
$comparisonFirstOperande = $currentTokenValue;
$expectedTokenType = Lexer::T_COMPARISON;
$currentTokenValue = null;
+
break;
}
- if (is_array($comparisonMultipleOperande)) {
+ if (\is_array($comparisonMultipleOperande)) {
$comparisonMultipleOperande[] = $currentTokenValue;
$expectedTokenType = Lexer::T_COMMA | Lexer::T_CLOSE_SQUARE_BRACKET;
$currentTokenValue = null;
+
break;
}
@@ -186,72 +170,97 @@ private function getExpression($previousExpression = null)
$containsValue = $currentTokenValue;
$expectedTokenType = Lexer::T_DOUBLE_CLOSE_CURLY_BRACKET;
$currentTokenValue = null;
+
break;
}
-
- $expression = call_user_func_array(array($this->expressionBuilder, $comparisonMethod), array($comparisonFirstOperande, $currentTokenValue));
+ $expression = \call_user_func_array([$this->expressionBuilder, $comparisonMethod], [$comparisonFirstOperande, $currentTokenValue]);
$comparisonFirstOperande = null;
$comparisonMethod = null;
$currentTokenValue = null;
$expectedTokenType = Lexer::T_COMPOSITE | Lexer::T_CLOSE_PARENTHESIS;
+
break;
+
case Lexer::T_EQUALS:
$comparisonMethod = 'eq';
- $expectedTokenType = Lexer::T_OPERANDE;
+ $expectedTokenType = Lexer::T_OPERAND;
+
break;
+
case Lexer::T_NOT_EQUALS:
$comparisonMethod = 'neq';
- $expectedTokenType = Lexer::T_OPERANDE;
+ $expectedTokenType = Lexer::T_OPERAND;
+
break;
+
case Lexer::T_GREATER_THAN:
$comparisonMethod = 'gt';
- $expectedTokenType = Lexer::T_OPERANDE;
+ $expectedTokenType = Lexer::T_OPERAND;
+
break;
+
case Lexer::T_GREATER_THAN_EQUALS:
$comparisonMethod = 'gte';
- $expectedTokenType = Lexer::T_OPERANDE;
+ $expectedTokenType = Lexer::T_OPERAND;
+
break;
+
case Lexer::T_LOWER_THAN:
$comparisonMethod = 'lt';
- $expectedTokenType = Lexer::T_OPERANDE;
+ $expectedTokenType = Lexer::T_OPERAND;
+
break;
+
case Lexer::T_LOWER_THAN_EQUALS:
$comparisonMethod = 'lte';
- $expectedTokenType = Lexer::T_OPERANDE;
+ $expectedTokenType = Lexer::T_OPERAND;
+
break;
+
case Lexer::T_NOT_OPEN_SQUARE_BRACKET:
$comparisonMethod = 'notIn';
- $comparisonMultipleOperande = array();
- $expectedTokenType = Lexer::T_OPERANDE | Lexer::T_CLOSE_SQUARE_BRACKET;
+ $comparisonMultipleOperande = [];
+ $expectedTokenType = Lexer::T_OPERAND | Lexer::T_CLOSE_SQUARE_BRACKET;
+
break;
+
case Lexer::T_OPEN_SQUARE_BRACKET:
$comparisonMethod = 'in';
- $comparisonMultipleOperande = array();
- $expectedTokenType = Lexer::T_OPERANDE | Lexer::T_CLOSE_SQUARE_BRACKET;
+ $comparisonMultipleOperande = [];
+ $expectedTokenType = Lexer::T_OPERAND | Lexer::T_CLOSE_SQUARE_BRACKET;
+
break;
+
case Lexer::T_CLOSE_SQUARE_BRACKET:
- $expression = call_user_func_array(array($this->expressionBuilder, $comparisonMethod), array($comparisonFirstOperande, $comparisonMultipleOperande));
+ $expression = \call_user_func_array([$this->expressionBuilder, $comparisonMethod], [$comparisonFirstOperande, $comparisonMultipleOperande]);
$comparisonMethod = null;
$comparisonFirstOperande = null;
$comparisonMultipleOperande = false;
$expectedTokenType = Lexer::T_COMPOSITE | Lexer::T_CLOSE_PARENTHESIS;
+
break;
+
case Lexer::T_DOUBLE_OPEN_CURLY_BRACKET:
$comparisonMethod = 'contains';
$contains = true;
- $expectedTokenType = Lexer::T_OPERANDE | Lexer::T_DOUBLE_CLOSE_CURLY_BRACKET;
+ $expectedTokenType = Lexer::T_OPERAND | Lexer::T_DOUBLE_CLOSE_CURLY_BRACKET;
+
break;
+
case Lexer::T_NOT_DOUBLE_OPEN_CURLY_BRACKET:
$comparisonMethod = 'notContains';
$contains = true;
- $expectedTokenType = Lexer::T_OPERANDE | Lexer::T_DOUBLE_CLOSE_CURLY_BRACKET;
+ $expectedTokenType = Lexer::T_OPERAND | Lexer::T_DOUBLE_CLOSE_CURLY_BRACKET;
+
break;
+
case Lexer::T_DOUBLE_CLOSE_CURLY_BRACKET:
- $expression = call_user_func_array(array($this->expressionBuilder, $comparisonMethod), array($comparisonFirstOperande, $containsValue));
+ $expression = \call_user_func_array([$this->expressionBuilder, $comparisonMethod], [$comparisonFirstOperande, $containsValue]);
$comparisonMethod = null;
$comparisonFirstOperande = null;
$contains = false;
$expectedTokenType = Lexer::T_COMPOSITE | Lexer::T_CLOSE_PARENTHESIS;
+
break;
case Lexer::T_AND:
@@ -266,16 +275,18 @@ private function getExpression($previousExpression = null)
$compositeOperator = $currentTokenType;
$tokenPrecedence = $currentTokenPrecedence;
$expectedTokenType = Lexer::T_OPEN_PARENTHESIS | Lexer::T_INPUT_PARAMETER;
+
break;
}
if ($currentTokenPrecedence < $tokenPrecedence) {
$expressions[] = $expression;
$expression = null;
- $expressions = array($this->buildComposite($compositeOperator, $expressions));
+ $expressions = [$this->buildComposite($compositeOperator, $expressions)];
$compositeOperator = $currentTokenType;
$tokenPrecedence = $currentTokenPrecedence;
$expectedTokenType = Lexer::T_OPEN_PARENTHESIS | Lexer::T_INPUT_PARAMETER;
+
break;
}
@@ -284,6 +295,7 @@ private function getExpression($previousExpression = null)
$this->lexer->resetPosition($currentTokenIndex);
$this->lexer->moveNext();
$expression = $this->getExpression($expression);
+
break;
}
@@ -292,6 +304,7 @@ private function getExpression($previousExpression = null)
$currentTokenPrecedence,
$tokenPrecedence
));
+
default:
throw new \LogicException(sprintf(
'Token mismatch. Expected token %s given %s',
@@ -305,7 +318,7 @@ private function getExpression($previousExpression = null)
$expressions[] = $expression;
}
- if (count($expressions) === 1) {
+ if (1 === \count($expressions)) {
return $expressions[0];
}
@@ -313,35 +326,40 @@ private function getExpression($previousExpression = null)
}
/**
- * @param $type
- * @param $expressions
+ * @param mixed $type
+ * @param mixed $expressions
*
* @return mixed
*
- * @throws UnknowCompositeTypeException
+ * @throws UnknownCompositeTypeException
*/
private function buildComposite($type, $expressions)
{
switch ($type) {
case Lexer::T_AND:
return $this->expressionBuilder->andX($expressions);
+
case Lexer::T_NOT_AND:
return $this->expressionBuilder->nandX($expressions);
+
case Lexer::T_OR:
return $this->expressionBuilder->orX($expressions);
+
case Lexer::T_NOT_OR:
return $this->expressionBuilder->norX($expressions);
+
case Lexer::T_XOR:
return $this->expressionBuilder->xorX($expressions);
+
default:
- throw new UnknowCompositeTypeException($type);
+ throw new UnknownCompositeTypeException($type);
}
}
/**
- * @return array
+ * @return null|array
*/
- private function getNextToken()
+ private function getNextToken(): mixed
{
$this->lexer->moveNext();
diff --git a/src/QueryStringParser.php b/src/QueryStringParser.php
index 02f2b10..e9396c6 100644
--- a/src/QueryStringParser.php
+++ b/src/QueryStringParser.php
@@ -1,10 +1,12 @@
$matches[1].urlencode($matches[2]).($matches[3] ?? ''),
+ urldecode($queryString)
);
}
}
diff --git a/tests/Bridge/Doctrine/Common/ExpressionBuilderAdapterTest.php b/tests/Bridge/Doctrine/Common/ExpressionBuilderAdapterTest.php
index f8f4ddd..6c93a73 100644
--- a/tests/Bridge/Doctrine/Common/ExpressionBuilderAdapterTest.php
+++ b/tests/Bridge/Doctrine/Common/ExpressionBuilderAdapterTest.php
@@ -1,70 +1,61 @@
markTestSkipped('This test is run when you have "doctrine/orm" installed.');
+ self::markTestSkipped('This test is run when you have "doctrine/orm" installed.');
}
$this->expressionBuilderAdapter = new ExpressionBuilderAdapter(new ExpressionBuilder());
}
- public function testParameter()
+ public function testParameter(): void
{
- $this->assertEquals('my_fake_data', $this->expressionBuilderAdapter->parameter('my_fake_data'));
+ self::assertSame('my_fake_data', $this->expressionBuilderAdapter->parameter('my_fake_data'));
}
- public function testString()
+ public function testString(): void
{
- $this->assertEquals('my_fake_data', $this->expressionBuilderAdapter->string('my_fake_data'));
+ self::assertSame('my_fake_data', $this->expressionBuilderAdapter->string('my_fake_data'));
}
- public function testIsNull()
+ public function testIsNull(): void
{
- $isv0 = !defined('Doctrine\Common\Collections\Expr\Comparison::CONTAINS');
+ $isv0 = !\defined('Doctrine\Common\Collections\Expr\Comparison::CONTAINS');
$field = 'fake_field';
- $this->assertEquals(
+ self::assertEquals(
new Comparison('fake_field', $isv0 ? 'IS' : '=', null),
$this->expressionBuilderAdapter->isNull($field)
);
}
- public function comparisonDataProvider()
- {
- if (!class_exists('Doctrine\Common\Collections\ExpressionBuilder')) {
- return array();
- }
-
- return array(
- array('field', 'value'),
- );
- }
-
/**
* @dataProvider comparisonDataProvider
- *
- * @param $field
- * @param $value
*/
- public function testEq($field, $value)
+ public function testEq(string $field, string $value): void
{
- $this->assertEquals(
+ self::assertEquals(
new Comparison('field', '=', 'value'),
$this->expressionBuilderAdapter->eq($field, $value)
);
@@ -72,13 +63,10 @@ public function testEq($field, $value)
/**
* @dataProvider comparisonDataProvider
- *
- * @param $field
- * @param $value
*/
- public function testNeq($field, $value)
+ public function testNeq(string $field, string $value): void
{
- $this->assertEquals(
+ self::assertEquals(
new Comparison('field', '<>', 'value'),
$this->expressionBuilderAdapter->neq($field, $value)
);
@@ -86,13 +74,10 @@ public function testNeq($field, $value)
/**
* @dataProvider comparisonDataProvider
- *
- * @param $field
- * @param $value
*/
- public function testGt($field, $value)
+ public function testGt(string $field, string $value): void
{
- $this->assertEquals(
+ self::assertEquals(
new Comparison('field', '>', 'value'),
$this->expressionBuilderAdapter->gt($field, $value)
);
@@ -100,13 +85,10 @@ public function testGt($field, $value)
/**
* @dataProvider comparisonDataProvider
- *
- * @param $field
- * @param $value
*/
- public function testGte($field, $value)
+ public function testGte(string $field, string $value): void
{
- $this->assertEquals(
+ self::assertEquals(
new Comparison('field', '>=', 'value'),
$this->expressionBuilderAdapter->gte($field, $value)
);
@@ -114,13 +96,10 @@ public function testGte($field, $value)
/**
* @dataProvider comparisonDataProvider
- *
- * @param $field
- * @param $value
*/
- public function testLt($field, $value)
+ public function testLt(string $field, string $value): void
{
- $this->assertEquals(
+ self::assertEquals(
new Comparison('field', '<', 'value'),
$this->expressionBuilderAdapter->lt($field, $value)
);
@@ -128,13 +107,10 @@ public function testLt($field, $value)
/**
* @dataProvider comparisonDataProvider
- *
- * @param $field
- * @param $value
*/
- public function testLte($field, $value)
+ public function testLte(string $field, string $value): void
{
- $this->assertEquals(
+ self::assertEquals(
new Comparison('field', '<=', 'value'),
$this->expressionBuilderAdapter->lte($field, $value)
);
@@ -142,89 +118,70 @@ public function testLte($field, $value)
/**
* @dataProvider comparisonDataProvider
- *
- * @param $field
- * @param $value
*/
- public function testIn($field, $value)
+ public function testIn(string $field, string $value): void
{
- $this->assertEquals(
- new Comparison('field', 'IN', array('value')),
- $this->expressionBuilderAdapter->in($field, array($value))
+ self::assertEquals(
+ new Comparison('field', 'IN', ['value']),
+ $this->expressionBuilderAdapter->in($field, [$value])
);
}
/**
* @dataProvider comparisonDataProvider
- *
- * @param $field
- * @param $value
*/
- public function testNotIn($field, $value)
+ public function testNotIn(string $field, string $value): void
{
- $this->assertEquals(
- new Comparison('field', 'NIN', array('value')),
- $this->expressionBuilderAdapter->notIn($field, array($value))
+ self::assertEquals(
+ new Comparison('field', 'NIN', ['value']),
+ $this->expressionBuilderAdapter->notIn($field, [$value])
);
}
/**
* @dataProvider comparisonDataProvider
- *
- * @param $field
- * @param $value
*/
- public function testContains($field, $value)
+ public function testContains(string $field, string $value): void
{
+ $expected = new Comparison('field', 'CONTAINS', 'value');
+
if (!method_exists('Doctrine\Common\Collections\ExpressionBuilder', 'contains')) {
- $this->expectException('\Symftony\Xpression\Exception\Expr\UnsupportedExpressionTypeException');
+ $this->expectException(UnsupportedExpressionTypeException::class);
$this->expectExceptionMessage('Unsupported expression type "contains".');
-
- $this->assertNull($this->expressionBuilderAdapter->contains($field, $value));
+ $expected = null;
}
- $this->assertEquals(
- new Comparison('field', 'CONTAINS', 'value'),
+ self::assertEquals(
+ $expected,
$this->expressionBuilderAdapter->contains($field, $value)
);
}
/**
* @dataProvider comparisonDataProvider
- * @expectedException \Symftony\Xpression\Exception\Expr\UnsupportedExpressionTypeException
- *
- * @param $field
- * @param $value
*/
- public function testNotContains($field, $value)
+ public function testNotContains(string $field, string $value): void
{
+ $this->expectException(UnsupportedExpressionTypeException::class);
+ $this->expectExceptionMessage('Unsupported expression type "notContains".');
$this->expressionBuilderAdapter->notContains($field, $value);
}
- public function compositeDataProvider()
+ public static function comparisonDataProvider(): iterable
{
if (!class_exists('Doctrine\Common\Collections\ExpressionBuilder')) {
- return array();
+ return [];
}
- return array(
- array(
- array(
- new Comparison('fieldA', '=', 1),
- new Comparison('fieldB', '>', 2)
- ),
- ),
- );
+ yield ['field', 'value'];
}
/**
* @dataProvider compositeDataProvider
- *
- * @param array $expressions
*/
- public function testAndX(array $expressions)
+ public function testAndX(array $expressions): void
{
- $this->assertEquals(
+ self::assertEquals(
new CompositeExpression('AND', $expressions),
$this->expressionBuilderAdapter->andX($expressions)
);
@@ -232,23 +189,20 @@ public function testAndX(array $expressions)
/**
* @dataProvider compositeDataProvider
- * @expectedException \Symftony\Xpression\Exception\Expr\UnsupportedExpressionTypeException
- *
- * @param array $expressions
*/
- public function testNandX(array $expressions)
+ public function testNandX(array $expressions): void
{
+ $this->expectException(UnsupportedExpressionTypeException::class);
+ $this->expectExceptionMessage('Unsupported expression type "nandX".');
$this->expressionBuilderAdapter->nandX($expressions);
}
/**
* @dataProvider compositeDataProvider
- *
- * @param array $expressions
*/
- public function testOrX(array $expressions)
+ public function testOrX(array $expressions): void
{
- $this->assertEquals(
+ self::assertEquals(
new CompositeExpression('OR', $expressions),
$this->expressionBuilderAdapter->orX($expressions)
);
@@ -256,23 +210,35 @@ public function testOrX(array $expressions)
/**
* @dataProvider compositeDataProvider
- * @expectedException \Symftony\Xpression\Exception\Expr\UnsupportedExpressionTypeException
- *
- * @param array $expressions
*/
- public function testNorX(array $expressions)
+ public function testNorX(array $expressions): void
{
+ $this->expectException(UnsupportedExpressionTypeException::class);
+ $this->expectExceptionMessage('Unsupported expression type "norX".');
$this->expressionBuilderAdapter->norX($expressions);
}
/**
* @dataProvider compositeDataProvider
- * @expectedException \Symftony\Xpression\Exception\Expr\UnsupportedExpressionTypeException
- *
- * @param array $expressions
*/
- public function testXorX(array $expressions)
+ public function testXorX(array $expressions): void
{
+ $this->expectException(UnsupportedExpressionTypeException::class);
+ $this->expectExceptionMessage('Unsupported expression type "xorX".');
$this->expressionBuilderAdapter->xorX($expressions);
}
+
+ public static function compositeDataProvider(): iterable
+ {
+ if (!class_exists('Doctrine\Common\Collections\ExpressionBuilder')) {
+ return [];
+ }
+
+ yield [
+ [
+ new Comparison('fieldA', '=', 1),
+ new Comparison('fieldB', '>', 2),
+ ],
+ ];
+ }
}
diff --git a/tests/Bridge/Doctrine/Common/ParserTest.php b/tests/Bridge/Doctrine/Common/ParserTest.php
index 493a5c5..fb3e6d9 100644
--- a/tests/Bridge/Doctrine/Common/ParserTest.php
+++ b/tests/Bridge/Doctrine/Common/ParserTest.php
@@ -1,15 +1,25 @@
markTestSkipped('This test is run when you have "doctrine/collection" installed.');
+ self::markTestSkipped('This test is run when you have "doctrine/collection" installed.');
}
-
$this->expressionBuilderAdapter = new ExpressionBuilderAdapter(new ExpressionBuilder());
$this->parser = new Parser($this->expressionBuilderAdapter);
}
- public function parseSuccessDataProvider()
+ /**
+ * @dataProvider provideParserCases
+ */
+ public function testParser(string $input, Expression $expectedExpression): void
+ {
+ self::assertEquals($expectedExpression, $this->parser->parse($input));
+ }
+
+ public static function provideParserCases(): iterable
{
if (!class_exists('Doctrine\Common\Collections\ExpressionBuilder')) {
- return array();
+ return [];
}
- return array(
- array(
+ return [
+ [
'fieldA=1',
new Comparison('fieldA', '=', 1),
- ),
- array(
+ ],
+ [
'fieldA="string"',
new Comparison('fieldA', '=', 'string'),
- ),
- array(
+ ],
+ [
'fieldA≥1',
new Comparison('fieldA', '>=', 1),
- ),
- array(
+ ],
+ [
'fieldA>=1',
new Comparison('fieldA', '>=', 1),
- ),
- array(
+ ],
+ [
'fieldA≤1',
new Comparison('fieldA', '<=', 1),
- ),
- array(
+ ],
+ [
'fieldA<=1',
new Comparison('fieldA', '<=', 1),
- ),
- array(
+ ],
+ [
'fieldA≠1',
new Comparison('fieldA', '<>', 1),
- ),
- array(
+ ],
+ [
'fieldA!=1',
new Comparison('fieldA', '<>', 1),
- ),
- array(
+ ],
+ [
'fieldA[1,2]',
- new Comparison('fieldA', 'IN', array(1, 2)),
- ),
- array(
+ new Comparison('fieldA', 'IN', [1, 2]),
+ ],
+ [
'fieldA![1,2]',
- new Comparison('fieldA', 'NIN', array(1, 2)),
- ),
- array(
+ new Comparison('fieldA', 'NIN', [1, 2]),
+ ],
+ [
'fieldA=1|fieldB=2|fieldC=3',
- new CompositeExpression('OR', array(
+ new CompositeExpression('OR', [
new Comparison('fieldA', '=', 1),
new Comparison('fieldB', '=', 2),
new Comparison('fieldC', '=', 3),
- )),
- ),
- array(
+ ]),
+ ],
+ [
'fieldA=1&fieldB=2&fieldC=3',
- new CompositeExpression('AND', array(
+ new CompositeExpression('AND', [
new Comparison('fieldA', '=', 1),
new Comparison('fieldB', '=', 2),
new Comparison('fieldC', '=', 3),
- )),
- ),
+ ]),
+ ],
// Precedences
- array(
+ [
'fieldA=1|fieldB=2|fieldC=3&fieldD=4',
- new CompositeExpression('OR', array(
+ new CompositeExpression('OR', [
new Comparison('fieldA', '=', 1),
new Comparison('fieldB', '=', 2),
- new CompositeExpression('AND', array(
+ new CompositeExpression('AND', [
new Comparison('fieldC', '=', 3),
new Comparison('fieldD', '=', 4),
- )),
- )),
- ),
- array(
+ ]),
+ ]),
+ ],
+ [
'fieldA=1&fieldB=2&fieldC=3|fieldD=4',
- new CompositeExpression('OR', array(
- new CompositeExpression('AND', array(
+ new CompositeExpression('OR', [
+ new CompositeExpression('AND', [
new Comparison('fieldA', '=', 1),
new Comparison('fieldB', '=', 2),
new Comparison('fieldC', '=', 3),
- )),
+ ]),
new Comparison('fieldD', '=', 4),
- )),
- ),
- array(
+ ]),
+ ],
+ [
'fieldA=1&fieldB=2|fieldC=3&fieldD=4',
- new CompositeExpression('OR', array(
- new CompositeExpression('AND', array(
+ new CompositeExpression('OR', [
+ new CompositeExpression('AND', [
new Comparison('fieldA', '=', 1),
new Comparison('fieldB', '=', 2),
- )),
- new CompositeExpression('AND', array(
+ ]),
+ new CompositeExpression('AND', [
new Comparison('fieldC', '=', 3),
new Comparison('fieldD', '=', 4),
- )),
- )),
- ),
+ ]),
+ ]),
+ ],
- //Parenthesis
- array(
+ // Parenthesis
+ [
'((fieldA=1))',
new Comparison('fieldA', '=', 1),
- ),
- array(
+ ],
+ [
'(fieldA=1|fieldB=2)&fieldC=3',
- new CompositeExpression('AND', array(
- new CompositeExpression('OR', array(
+ new CompositeExpression('AND', [
+ new CompositeExpression('OR', [
new Comparison('fieldA', '=', 1),
new Comparison('fieldB', '=', 2),
- )),
+ ]),
new Comparison('fieldC', '=', 3),
- )),
- ),
- array(
+ ]),
+ ],
+ [
'fieldA=1|(fieldB=2&fieldC=3)',
- new CompositeExpression('OR', array(
+ new CompositeExpression('OR', [
new Comparison('fieldA', '=', 1),
- new CompositeExpression('AND', array(
+ new CompositeExpression('AND', [
new Comparison('fieldB', '=', 2),
new Comparison('fieldC', '=', 3),
- )),
- )),
- ),
- );
+ ]),
+ ]),
+ ],
+ ];
}
/**
- * @dataProvider parseSuccessDataProvider
- *
- * @param $input
- * @param $expectedExpression
+ * @dataProvider provideParserThrowUnsupportedExpressionTypeExceptionCases
*/
- public function testParser($input, $expectedExpression)
+ public function testParserThrowUnsupportedExpressionTypeException(string $input): void
{
- $this->assertEquals($expectedExpression, $this->parser->parse($input));
+ $this->expectException(InvalidExpressionException::class);
+ $this->parser->parse($input);
}
- public function unsupportedExpressionTypeDataProvider()
+ public static function provideParserThrowUnsupportedExpressionTypeExceptionCases(): iterable
{
if (!class_exists('Doctrine\Common\Collections\ExpressionBuilder')) {
- return array();
+ return [];
}
- return array(
- array('fieldA=1|fieldB=2|fieldC=3⊕fieldD=4'),
- array('fieldA=1!|fieldB=2!|fieldC=3'),
- array('fieldA=1^|fieldB=2'),
- array('fieldA=1⊕fieldB=2'),
- array('fieldA=1!&fieldB=2!&fieldC=3'),
- array('fieldA=1&fieldB=2&fieldC=3!&fieldD=4'),
- array('fieldA=1|fieldB=2|fieldC=3!|fieldD=4'),
- array('fieldA!{{1}}'),
- );
- }
-
- /**
- * @dataProvider unsupportedExpressionTypeDataProvider
- * @expectedException \Symftony\Xpression\Exception\Parser\InvalidExpressionException
- *
- * @param $input
- */
- public function testParserThrowUnsupportedExpressionTypeException($input)
- {
- $this->parser->parse($input);
+ return [
+ ['fieldA=1|fieldB=2|fieldC=3⊕fieldD=4'],
+ ['fieldA=1!|fieldB=2!|fieldC=3'],
+ ['fieldA=1^|fieldB=2'],
+ ['fieldA=1⊕fieldB=2'],
+ ['fieldA=1!&fieldB=2!&fieldC=3'],
+ ['fieldA=1&fieldB=2&fieldC=3!&fieldD=4'],
+ ['fieldA=1|fieldB=2|fieldC=3!|fieldD=4'],
+ ['fieldA!{{1}}'],
+ ];
}
}
diff --git a/tests/Bridge/Doctrine/MongoDb/ExprBuilderTest.php b/tests/Bridge/Doctrine/MongoDb/ExprBuilderTest.php
deleted file mode 100644
index 4d74928..0000000
--- a/tests/Bridge/Doctrine/MongoDb/ExprBuilderTest.php
+++ /dev/null
@@ -1,285 +0,0 @@
-markTestSkipped('This test is run when you have "doctrine/mongodb-odm" installed.');
- }
-
- $this->exprBuilder = new ExprBuilder();
- }
-
- public function testValueAsString()
- {
- $this->assertEquals('my_fake_data', $this->exprBuilder->valueAsString('my_fake_data'));
- }
-
- public function testIsNull()
- {
- $field = 'fake_field';
- $this->assertEquals(
- $this->createExpr()->field('fake_field')->equals(null),
- $this->exprBuilder->isNull($field)
- );
- }
-
- public function comparisonDataProvider()
- {
- if (!class_exists('Doctrine\MongoDB\Query\Expr')) {
- return array();
- }
-
- return array(
- array('field', 'value'),
- );
- }
-
- /**
- * @dataProvider comparisonDataProvider
- *
- * @param $field
- * @param $value
- */
- public function testEq($field, $value)
- {
- $this->assertEquals(
- $this->createExpr()->field('field')->equals('value'),
- $this->exprBuilder->eq($field, $value)
- );
- }
-
- /**
- * @dataProvider comparisonDataProvider
- *
- * @param $field
- * @param $value
- */
- public function testNeq($field, $value)
- {
- $this->assertEquals(
- $this->createExpr()->field('field')->notEqual('value'),
- $this->exprBuilder->neq($field, $value)
- );
- }
-
- /**
- * @dataProvider comparisonDataProvider
- *
- * @param $field
- * @param $value
- */
- public function testGt($field, $value)
- {
- $this->assertEquals(
- $this->createExpr()->field('field')->gt('value'),
- $this->exprBuilder->gt($field, $value)
- );
- }
-
- /**
- * @dataProvider comparisonDataProvider
- *
- * @param $field
- * @param $value
- */
- public function testGte($field, $value)
- {
- $this->assertEquals(
- $this->createExpr()->field('field')->gte('value'),
- $this->exprBuilder->gte($field, $value)
- );
- }
-
- /**
- * @dataProvider comparisonDataProvider
- *
- * @param $field
- * @param $value
- */
- public function testLt($field, $value)
- {
- $this->assertEquals(
- $this->createExpr()->field('field')->lt('value'),
- $this->exprBuilder->lt($field, $value)
- );
- }
-
- /**
- * @dataProvider comparisonDataProvider
- *
- * @param $field
- * @param $value
- */
- public function testLte($field, $value)
- {
- $this->assertEquals(
- $this->createExpr()->field('field')->lte('value'),
- $this->exprBuilder->lte($field, $value)
- );
- }
-
- /**
- * @dataProvider comparisonDataProvider
- *
- * @param $field
- * @param $value
- */
- public function testIn($field, $value)
- {
- $this->assertEquals(
- $this->createExpr()->field('field')->in(array('value')),
- $this->exprBuilder->in($field, array($value))
- );
- }
-
- /**
- * @dataProvider comparisonDataProvider
- *
- * @param $field
- * @param $value
- */
- public function testNotIn($field, $value)
- {
- $this->assertEquals(
- $this->createExpr()->field('field')->notIn(array('value')),
- $this->exprBuilder->notIn($field, array($value))
- );
- }
-
- /**
- * @dataProvider comparisonDataProvider
- *
- * @param $field
- * @param $value
- */
- public function testContains($field, $value)
- {
- if (!class_exists('\MongoRegex')) {
- $this->markTestSkipped('This test need "\MongoRegex" installed.');
- }
-
- $this->assertEquals(
- $this->createExpr()->field('field')->equals(new \MongoRegex('/.*value.*/')),
- $this->exprBuilder->contains($field, $value)
- );
- }
-
- /**
- * @dataProvider comparisonDataProvider
- *
- * @param $field
- * @param $value
- */
- public function testNotContains($field, $value)
- {
- if (!class_exists('\MongoRegex')) {
- $this->markTestSkipped('This test need "\MongoRegex" installed.');
- }
-
- $this->assertEquals(
- $this->createExpr()->field('field')->equals(new \MongoRegex('/^((?!value).)*$/')),
- $this->exprBuilder->notContains($field, $value)
- );
- }
-
- public function compositeDataProvider()
- {
- if (!class_exists('Doctrine\MongoDB\Query\Expr')) {
- return array();
- }
-
- return array(
- array(
- array(
- array('fieldA' => 'value'),
- array('fieldB' => array('$gt' => 2)),
- ),
- ),
- );
- }
-
- /**
- * @dataProvider compositeDataProvider
- *
- * @param array $expressions
- */
- public function testAndX(array $expressions)
- {
- $this->assertEquals(
- $this->createExpr()
- ->addAnd($this->createExpr()->field('fieldA')->equals('value'))
- ->addAnd($this->createExpr()->field('fieldB')->gt(2)),
- $this->exprBuilder->andX($expressions)
- );
- }
-
- /**
- * @dataProvider compositeDataProvider
- * @expectedException \Symftony\Xpression\Exception\Expr\UnsupportedExpressionTypeException
- *
- * @param array $expressions
- */
- public function testNandX(array $expressions)
- {
- $this->exprBuilder->nandX($expressions);
- }
-
- /**
- * @dataProvider compositeDataProvider
- *
- * @param array $expressions
- */
- public function testOrX(array $expressions)
- {
- $this->assertEquals(
- $this->createExpr()
- ->addOr($this->createExpr()->field('fieldA')->equals('value'))
- ->addOr($this->createExpr()->field('fieldB')->gt(2)),
- $this->exprBuilder->orX($expressions)
- );
- }
-
- /**
- * @dataProvider compositeDataProvider
- *
- * @param array $expressions
- */
- public function testNorX(array $expressions)
- {
- $this->assertEquals(
- $this->createExpr()
- ->addNor($this->createExpr()->field('fieldA')->equals('value'))
- ->addNor($this->createExpr()->field('fieldB')->gt(2)),
- $this->exprBuilder->norX($expressions)
- );
- }
-
- /**
- * @dataProvider compositeDataProvider
- * @expectedException \Symftony\Xpression\Exception\Expr\UnsupportedExpressionTypeException
- *
- * @param array $expressions
- */
- public function testXorX(array $expressions)
- {
- $this->exprBuilder->xorX($expressions);
- }
-
- private function createExpr()
- {
- return new Expr();
- }
-}
diff --git a/tests/Bridge/Doctrine/MongoDb/ParserTest.php b/tests/Bridge/Doctrine/MongoDb/ParserTest.php
deleted file mode 100644
index cf473ef..0000000
--- a/tests/Bridge/Doctrine/MongoDb/ParserTest.php
+++ /dev/null
@@ -1,212 +0,0 @@
-markTestSkipped('This test is run when you have "doctrine/mongodb-odm" installed.');
- }
-
- $this->exprBuilder = new ExprBuilder();
- $this->parser = new Parser($this->exprBuilder);
- }
-
- public function parseSuccessDataProvider()
- {
- if (!class_exists('Doctrine\MongoDB\Query\Expr')) {
- return array();
- }
-
- return array(
- array(
- 'fieldA=1',
- array('fieldA' => 1),
- ),
- array(
- 'fieldA="string"',
- array('fieldA' => 'string'),
- ),
- array(
- 'fieldA≥1',
- array('fieldA' => array('$gte' => 1)),
- ),
- array(
- 'fieldA>=1',
- array('fieldA' => array('$gte' => 1)),
- ),
- array(
- 'fieldA>1',
- array('fieldA' => array('$gt' => 1)),
- ),
- array(
- 'fieldA≤1',
- array('fieldA' => array('$lte' => 1)),
- ),
- array(
- 'fieldA<=1',
- array('fieldA' => array('$lte' => 1)),
- ),
- array(
- 'fieldA<1',
- array('fieldA' => array('$lt' => 1)),
- ),
- array(
- 'fieldA≠1',
- array('fieldA' => array('$ne' => 1)),
- ),
- array(
- 'fieldA!=1',
- array('fieldA' => array('$ne' => 1)),
- ),
- array(
- 'fieldA[1,2]',
- array('fieldA' => array('$in' => array(1, 2))),
- ),
- array(
- 'fieldA![1,2]',
- array('fieldA' => array('$nin' => array(1, 2))),
- ),
- array(
- 'fieldA{{1}}',
- array('fieldA' => new \MongoRegex('/.*1.*/')),
- ),
- array(
- 'fieldA!{{1}}',
- array('fieldA' => new \MongoRegex('/^((?!1).)*$/')),
- ),
- array(
- 'fieldA=1|fieldB=2|fieldC=3',
- array('$or' => array(
- array('fieldA' => 1),
- array('fieldB' => 2),
- array('fieldC' => 3),
- )),
- ),
- array(
- 'fieldA=1&fieldB=2&fieldC=3',
- array('$and' => array(
- array('fieldA' => 1),
- array('fieldB' => 2),
- array('fieldC' => 3),
- )),
- ),
-
- // Precedences
- array(
- 'fieldA=1|fieldB=2|fieldC=3&fieldD=4',
- array('$or' => array(
- array('fieldA' => 1),
- array('fieldB' => 2),
- array('$and' => array(
- array('fieldC' => 3),
- array('fieldD' => 4)
- )),
- )),
- ),
- array(
- 'fieldA=1&fieldB=2&fieldC=3|fieldD=4',
- array('$or' => array(
- array('$and' => array(
- array('fieldA' => 1),
- array('fieldB' => 2),
- array('fieldC' => 3),
- )),
- array('fieldD' => 4)
- )),
- ),
- array(
- 'fieldA=1&fieldB=2|fieldC=3&fieldD=4',
- array('$or' => array(
- array('$and' => array(
- array('fieldA' => 1),
- array('fieldB' => 2),
- )),
- array('$and' => array(
- array('fieldC' => 3),
- array('fieldD' => 4)
- ))
- )),
- ),
-
- //Parenthesis
- array(
- '((fieldA=1))',
- array('fieldA' => 1),
- ),
- array(
- '(fieldA=1|fieldB=2)&fieldC=3',
- array('$and' => array(
- array('$or' => array(
- array('fieldA' => 1),
- array('fieldB' => 2),
- )),
- array('fieldC' => 3)
- )),
- ),
- array(
- 'fieldA=1|(fieldB=2&fieldC=3)',
- array('$or' => array(
- array('fieldA' => 1),
- array('$and' => array(
- array('fieldB' => 2),
- array('fieldC' => 3)
- ))
- )),
- ),
- );
- }
-
- /**
- * @dataProvider parseSuccessDataProvider
- *
- * @param $input
- * @param $expectedExpression
- */
- public function testParser($input, $expectedExpression)
- {
- $this->assertEquals($expectedExpression, $this->parser->parse($input)->getQuery());
- }
-
- public function unsupportedExpressionTypeDataProvider()
- {
- if (!class_exists('Doctrine\MongoDB\Query\Expr')) {
- return array();
- }
-
- return array(
- array('fieldA=1|fieldB=2|fieldC=3⊕fieldD=4'),
- array('fieldA=1^|fieldB=2'),
- array('fieldA=1⊕fieldB=2'),
- array('fieldA=1!&fieldB=2!&fieldC=3'),
- array('fieldA=1&fieldB=2&fieldC=3!&fieldD=4'),
- );
- }
-
- /**
- * @dataProvider unsupportedExpressionTypeDataProvider
- * @expectedException \Symftony\Xpression\Exception\Parser\InvalidExpressionException
- *
- * @param $input
- */
- public function testParserThrowUnsupportedExpressionTypeException($input)
- {
- $this->parser->parse($input);
- }
-}
diff --git a/tests/Bridge/Doctrine/ORM/ExprAdapterTest.php b/tests/Bridge/Doctrine/ORM/ExprAdapterTest.php
index 765b8dd..40afe0a 100644
--- a/tests/Bridge/Doctrine/ORM/ExprAdapterTest.php
+++ b/tests/Bridge/Doctrine/ORM/ExprAdapterTest.php
@@ -1,58 +1,45 @@
markTestSkipped('This test is run when you have "doctrine/orm" installed.');
+ self::markTestSkipped('This test is run when you have "doctrine/orm" installed.');
}
$this->exprAdapter = new ExprAdapter(new Expr());
}
- public function testValueAsString()
- {
- $this->assertEquals((new Expr())->literal('my_fake_data'), $this->exprAdapter->valueAsString('my_fake_data'));
- }
-
- public function testIsNull()
+ public function testIsNull(): void
{
$field = 'fake_field';
- $this->assertEquals('fake_field IS NULL', $this->exprAdapter->isNull($field));
- }
-
- public function comparisonDataProvider()
- {
- if (!class_exists('Doctrine\ORM\Query\Expr')) {
- return array();
- }
-
- return array(
- array('field', 'value'),
- );
+ self::assertSame('fake_field IS NULL', $this->exprAdapter->isNull($field));
}
/**
* @dataProvider comparisonDataProvider
- *
- * @param $field
- * @param $value
*/
- public function testEq($field, $value)
+ public function testEq(string $field, string $value): void
{
- $this->assertEquals(
+ self::assertEquals(
new Expr\Comparison($field, Expr\Comparison::EQ, $value),
$this->exprAdapter->eq($field, $value)
);
@@ -60,13 +47,10 @@ public function testEq($field, $value)
/**
* @dataProvider comparisonDataProvider
- *
- * @param $field
- * @param $value
*/
- public function testNeq($field, $value)
+ public function testNeq(string $field, string $value): void
{
- $this->assertEquals(
+ self::assertEquals(
new Expr\Comparison($field, Expr\Comparison::NEQ, $value),
$this->exprAdapter->neq($field, $value)
);
@@ -74,13 +58,10 @@ public function testNeq($field, $value)
/**
* @dataProvider comparisonDataProvider
- *
- * @param $field
- * @param $value
*/
- public function testGt($field, $value)
+ public function testGt(string $field, string $value): void
{
- $this->assertEquals(
+ self::assertEquals(
new Expr\Comparison($field, Expr\Comparison::GT, $value),
$this->exprAdapter->gt($field, $value)
);
@@ -88,13 +69,10 @@ public function testGt($field, $value)
/**
* @dataProvider comparisonDataProvider
- *
- * @param $field
- * @param $value
*/
- public function testGte($field, $value)
+ public function testGte(string $field, string $value): void
{
- $this->assertEquals(
+ self::assertEquals(
new Expr\Comparison($field, Expr\Comparison::GTE, $value),
$this->exprAdapter->gte($field, $value)
);
@@ -102,13 +80,10 @@ public function testGte($field, $value)
/**
* @dataProvider comparisonDataProvider
- *
- * @param $field
- * @param $value
*/
- public function testLt($field, $value)
+ public function testLt(string $field, string $value): void
{
- $this->assertEquals(
+ self::assertEquals(
new Expr\Comparison($field, Expr\Comparison::LT, $value),
$this->exprAdapter->lt($field, $value)
);
@@ -116,13 +91,10 @@ public function testLt($field, $value)
/**
* @dataProvider comparisonDataProvider
- *
- * @param $field
- * @param $value
*/
- public function testLte($field, $value)
+ public function testLte(string $field, string $value): void
{
- $this->assertEquals(
+ self::assertEquals(
new Expr\Comparison($field, Expr\Comparison::LTE, $value),
$this->exprAdapter->lte($field, $value)
);
@@ -130,41 +102,32 @@ public function testLte($field, $value)
/**
* @dataProvider comparisonDataProvider
- *
- * @param $field
- * @param $value
*/
- public function testIn($field, $value)
+ public function testIn(string $field, string $value): void
{
- $this->assertEquals(
- new Expr\Func('field IN', array("'value'")),
- $this->exprAdapter->in($field, array($value))
+ self::assertEquals(
+ new Expr\Func('field IN', ["'value'"]),
+ $this->exprAdapter->in($field, [$value])
);
}
/**
* @dataProvider comparisonDataProvider
- *
- * @param $field
- * @param $value
*/
- public function testNotIn($field, $value)
+ public function testNotIn(string $field, string $value): void
{
- $this->assertEquals(
- new Expr\Func('field NOT IN', array("'value'")),
- $this->exprAdapter->notIn($field, array($value))
+ self::assertEquals(
+ new Expr\Func('field NOT IN', ["'value'"]),
+ $this->exprAdapter->notIn($field, [$value])
);
}
/**
* @dataProvider comparisonDataProvider
- *
- * @param $field
- * @param $value
*/
- public function testContains($field, $value)
+ public function testContains(string $field, string $value): void
{
- $this->assertEquals(
+ self::assertEquals(
new Expr\Comparison('field', 'LIKE', $value),
$this->exprAdapter->contains($field, $value)
);
@@ -172,56 +135,32 @@ public function testContains($field, $value)
/**
* @dataProvider comparisonDataProvider
- *
- * @param $field
- * @param $value
*/
- public function testNotContains($field, $value)
+ public function testNotContains(string $field, string $value): void
{
- $this->assertEquals(
+ self::assertEquals(
new Expr\Comparison('field', 'NOT LIKE', $value),
$this->exprAdapter->notContains($field, $value)
);
}
- public function compositeDataProvider()
+ public static function comparisonDataProvider(): iterable
{
if (!class_exists('Doctrine\ORM\Query\Expr')) {
- return array();
+ return [];
}
- return array(
- array(array(
- new Expr\Comparison('field', Expr\Comparison::EQ, 'value'),
- )),
- array(array(
- new Expr\Func('field', array('value'))
- )),
- array(array(
- new Expr\Andx(
- array(
- new Expr\Comparison('field', Expr\Comparison::EQ, 'value'),
- )
- )
- )),
- array(array(
- new Expr\Orx(
- array(
- new Expr\Comparison('field', Expr\Comparison::EQ, 'value'),
- )
- )
- )),
- );
+ yield ['field', 'value'];
}
/**
* @dataProvider compositeDataProvider
*
- * @param $expressions
+ * @param Expression[] $expressions
*/
- public function testAndX($expressions)
+ public function testAndX(array $expressions): void
{
- $this->assertEquals(
+ self::assertEquals(
new Expr\Andx($expressions),
$this->exprAdapter->andX($expressions)
);
@@ -229,23 +168,24 @@ public function testAndX($expressions)
/**
* @dataProvider compositeDataProvider
- * @expectedException \Symftony\Xpression\Exception\Expr\UnsupportedExpressionTypeException
*
- * @param $expressions
+ * @param Expression[] $expressions
*/
- public function testNandX($expressions)
+ public function testNandX(array $expressions): void
{
+ $this->expectException(UnsupportedExpressionTypeException::class);
+ $this->expectExceptionMessage('Unsupported expression type "nandX".');
$this->exprAdapter->nandX($expressions);
}
/**
* @dataProvider compositeDataProvider
*
- * @param $expressions
+ * @param Expression[] $expressions
*/
- public function testOrX($expressions)
+ public function testOrX(array $expressions): void
{
- $this->assertEquals(
+ self::assertEquals(
new Expr\Orx($expressions),
$this->exprAdapter->orX($expressions)
);
@@ -253,23 +193,56 @@ public function testOrX($expressions)
/**
* @dataProvider compositeDataProvider
- * @expectedException \Symftony\Xpression\Exception\Expr\UnsupportedExpressionTypeException
*
- * @param $expressions
+ * @param Expression[] $expressions
*/
- public function testNorX($expressions)
+ public function testNorX(array $expressions): void
{
+ $this->expectException(UnsupportedExpressionTypeException::class);
+ $this->expectExceptionMessage('Unsupported expression type "norX".');
$this->exprAdapter->norX($expressions);
}
/**
* @dataProvider compositeDataProvider
- * @expectedException \Symftony\Xpression\Exception\Expr\UnsupportedExpressionTypeException
*
- * @param $expressions
+ * @param Expression[] $expressions
*/
- public function testXorX($expressions)
+ public function testXorX(array $expressions): void
{
+ $this->expectException(UnsupportedExpressionTypeException::class);
+ $this->expectExceptionMessage('Unsupported expression type "xorX".');
$this->exprAdapter->xorX($expressions);
}
+
+ public static function compositeDataProvider(): iterable
+ {
+ if (!class_exists('Doctrine\ORM\Query\Expr')) {
+ return [];
+ }
+
+ yield [[
+ new Expr\Comparison('field', Expr\Comparison::EQ, 'value'),
+ ]];
+
+ yield [[
+ new Expr\Func('field', ['value']),
+ ]];
+
+ yield [[
+ new Expr\Andx(
+ [
+ new Expr\Comparison('field', Expr\Comparison::EQ, 'value'),
+ ]
+ ),
+ ]];
+
+ yield [[
+ new Expr\Orx(
+ [
+ new Expr\Comparison('field', Expr\Comparison::EQ, 'value'),
+ ]
+ ),
+ ]];
+ }
}
diff --git a/tests/Bridge/Doctrine/ORM/ParserTest.php b/tests/Bridge/Doctrine/ORM/ParserTest.php
index 4b39c72..fbbf11e 100644
--- a/tests/Bridge/Doctrine/ORM/ParserTest.php
+++ b/tests/Bridge/Doctrine/ORM/ParserTest.php
@@ -1,207 +1,226 @@
markTestSkipped('This test is run when you have "doctrine/orm" installed.');
+ self::markTestSkipped('This test is run when you have "doctrine/orm" installed.');
}
$this->exprAdapter = new ExprAdapter(new Expr());
$this->parser = new Parser($this->exprAdapter);
}
- public function parseSuccessDataProvider()
+ /**
+ * @dataProvider provideParserCases
+ *
+ * @param mixed $expectedExpression
+ */
+ public function testParser(string $input, $expectedExpression): void
+ {
+ self::assertEquals($expectedExpression, $this->parser->parse($input));
+ }
+
+ public static function provideParserCases(): iterable
{
if (!class_exists('Doctrine\ORM\Query\Expr')) {
- return array();
+ return [];
}
- return array(
- array(
- 'fieldA=1',
+ yield [
+ 'fieldA=1',
+ new Expr\Comparison('fieldA', '=', 1),
+ ];
+
+ yield [
+ 'fieldA="string"',
+ new Expr\Comparison('fieldA', '=', (new Expr())->literal('string')),
+ ];
+
+ yield [
+ 'fieldA≥1',
+ new Expr\Comparison('fieldA', '>=', 1),
+ ];
+
+ yield [
+ 'fieldA>=1',
+ new Expr\Comparison('fieldA', '>=', 1),
+ ];
+
+ yield [
+ 'fieldA≤1',
+ new Expr\Comparison('fieldA', '<=', 1),
+ ];
+
+ yield [
+ 'fieldA<=1',
+ new Expr\Comparison('fieldA', '<=', 1),
+ ];
+
+ yield [
+ 'fieldA≠1',
+ new Expr\Comparison('fieldA', '<>', 1),
+ ];
+
+ yield [
+ 'fieldA!=1',
+ new Expr\Comparison('fieldA', '<>', 1),
+ ];
+
+ yield [
+ 'fieldA[1,2]',
+ new Expr\Func('fieldA IN', [1, 2]),
+ ];
+
+ yield [
+ 'fieldA![1,2]',
+ new Expr\Func('fieldA NOT IN', [1, 2]),
+ ];
+
+ yield [
+ 'fieldA{{1}}',
+ new Expr\Comparison('fieldA', 'LIKE', 1),
+ ];
+
+ yield [
+ 'fieldA!{{1}}',
+ new Expr\Comparison('fieldA', 'NOT LIKE', 1),
+ ];
+
+ yield [
+ 'fieldA=1|fieldB=2|fieldC=3',
+ new Expr\Orx([
+ new Expr\Comparison('fieldA', '=', 1),
+ new Expr\Comparison('fieldB', '=', 2),
+ new Expr\Comparison('fieldC', '=', 3),
+ ]),
+ ];
+
+ yield [
+ 'fieldA=1&fieldB=2&fieldC=3',
+ new Expr\Andx([
+ new Expr\Comparison('fieldA', '=', 1),
+ new Expr\Comparison('fieldB', '=', 2),
+ new Expr\Comparison('fieldC', '=', 3),
+ ]),
+ ];
+
+ // Precedences
+ yield [
+ 'fieldA=1|fieldB=2|fieldC=3&fieldD=4',
+ new Expr\Orx([
new Expr\Comparison('fieldA', '=', 1),
- ),
- array(
- 'fieldA="string"',
- new Expr\Comparison('fieldA', '=', (new Expr())->literal('string')),
- ),
- array(
- 'fieldA≥1',
- new Expr\Comparison('fieldA', '>=', 1),
- ),
- array(
- 'fieldA>=1',
- new Expr\Comparison('fieldA', '>=', 1),
- ),
- array(
- 'fieldA≤1',
- new Expr\Comparison('fieldA', '<=', 1),
- ),
- array(
- 'fieldA<=1',
- new Expr\Comparison('fieldA', '<=', 1),
- ),
- array(
- 'fieldA≠1',
- new Expr\Comparison('fieldA', '<>', 1),
- ),
- array(
- 'fieldA!=1',
- new Expr\Comparison('fieldA', '<>', 1),
- ),
- array(
- 'fieldA[1,2]',
- new Expr\Func('fieldA IN', array(1, 2)),
- ),
- array(
- 'fieldA![1,2]',
- new Expr\Func('fieldA NOT IN', array(1, 2)),
- ),
- array(
- 'fieldA{{1}}',
- new Expr\Comparison('fieldA', 'LIKE', 1),
- ),
- array(
- 'fieldA!{{1}}',
- new Expr\Comparison('fieldA', 'NOT LIKE', 1),
- ),
- array(
- 'fieldA=1|fieldB=2|fieldC=3',
- new Expr\Orx(array(
+ new Expr\Comparison('fieldB', '=', 2),
+ new Expr\Andx([
+ new Expr\Comparison('fieldC', '=', 3),
+ new Expr\Comparison('fieldD', '=', 4),
+ ]),
+ ]),
+ ];
+
+ yield [
+ 'fieldA=1&fieldB=2&fieldC=3|fieldD=4',
+ new Expr\Orx([
+ new Expr\Andx([
new Expr\Comparison('fieldA', '=', 1),
new Expr\Comparison('fieldB', '=', 2),
new Expr\Comparison('fieldC', '=', 3),
- )),
- ),
- array(
- 'fieldA=1&fieldB=2&fieldC=3',
- new Expr\Andx(array(
+ ]),
+ new Expr\Comparison('fieldD', '=', 4),
+ ]),
+ ];
+
+ yield [
+ 'fieldA=1&fieldB=2|fieldC=3&fieldD=4',
+ new Expr\Orx([
+ new Expr\Andx([
new Expr\Comparison('fieldA', '=', 1),
new Expr\Comparison('fieldB', '=', 2),
+ ]),
+ new Expr\Andx([
new Expr\Comparison('fieldC', '=', 3),
- )),
- ),
+ new Expr\Comparison('fieldD', '=', 4),
+ ]),
+ ]),
+ ];
+
+ // Parenthesis
+ yield [
+ '((fieldA=1))',
+ new Expr\Comparison('fieldA', '=', 1),
+ ];
- // Precedences
- array(
- 'fieldA=1|fieldB=2|fieldC=3&fieldD=4',
- new Expr\Orx(array(
+ yield [
+ '(fieldA=1|fieldB=2)&fieldC=3',
+ new Expr\Andx([
+ new Expr\Orx([
new Expr\Comparison('fieldA', '=', 1),
new Expr\Comparison('fieldB', '=', 2),
- new Expr\Andx(array(
- new Expr\Comparison('fieldC', '=', 3),
- new Expr\Comparison('fieldD', '=', 4),
- )),
- )),
- ),
- array(
- 'fieldA=1&fieldB=2&fieldC=3|fieldD=4',
- new Expr\Orx(array(
- new Expr\Andx(array(
- new Expr\Comparison('fieldA', '=', 1),
- new Expr\Comparison('fieldB', '=', 2),
- new Expr\Comparison('fieldC', '=', 3),
- )),
- new Expr\Comparison('fieldD', '=', 4),
- )),
- ),
- array(
- 'fieldA=1&fieldB=2|fieldC=3&fieldD=4',
- new Expr\Orx(array(
- new Expr\Andx(array(
- new Expr\Comparison('fieldA', '=', 1),
- new Expr\Comparison('fieldB', '=', 2),
- )),
- new Expr\Andx(array(
- new Expr\Comparison('fieldC', '=', 3),
- new Expr\Comparison('fieldD', '=', 4),
- )),
- )),
- ),
-
- //Parenthesis
- array(
- '((fieldA=1))',
+ ]),
+ new Expr\Comparison('fieldC', '=', 3),
+ ]),
+ ];
+
+ yield [
+ 'fieldA=1|(fieldB=2&fieldC=3)',
+ new Expr\Orx([
new Expr\Comparison('fieldA', '=', 1),
- ),
- array(
- '(fieldA=1|fieldB=2)&fieldC=3',
- new Expr\Andx(array(
- new Expr\Orx(array(
- new Expr\Comparison('fieldA', '=', 1),
- new Expr\Comparison('fieldB', '=', 2),
- )),
+ new Expr\Andx([
+ new Expr\Comparison('fieldB', '=', 2),
new Expr\Comparison('fieldC', '=', 3),
- )),
- ),
- array(
- 'fieldA=1|(fieldB=2&fieldC=3)',
- new Expr\Orx(array(
- new Expr\Comparison('fieldA', '=', 1),
- new Expr\Andx(array(
- new Expr\Comparison('fieldB', '=', 2),
- new Expr\Comparison('fieldC', '=', 3),
- )),
- )),
- ),
- );
+ ]),
+ ]),
+ ];
}
/**
- * @dataProvider parseSuccessDataProvider
- *
- * @param $input
- * @param $expectedExpression
+ * @dataProvider provideParserThrowUnsupportedExpressionTypeExceptionCases
*/
- public function testParser($input, $expectedExpression)
+ public function testParserThrowUnsupportedExpressionTypeException(string $input): void
{
- $this->assertEquals($expectedExpression, $this->parser->parse($input));
+ $this->expectException(InvalidExpressionException::class);
+ $this->expectExceptionMessage('Invalid expression.');
+ $this->parser->parse($input);
}
- public function unsupportedExpressionTypeDataProvider()
+ public static function provideParserThrowUnsupportedExpressionTypeExceptionCases(): iterable
{
if (!class_exists('Doctrine\ORM\Query\Expr')) {
- return array();
+ return [];
}
- return array(
- array('fieldA=1!|fieldB=2!|fieldC=3'),
- array('fieldA=1^|fieldB=2'),
- array('fieldA=1⊕fieldB=2'),
- array('fieldA=1!&fieldB=2!&fieldC=3'),
- array('fieldA=1&fieldB=2&fieldC=3!&fieldD=4'),
- array('fieldA=1|fieldB=2|fieldC=3!|fieldD=4'),
- array('fieldA=1|fieldB=2|fieldC=3⊕fieldD=4'),
- );
- }
+ yield ['fieldA=1!|fieldB=2!|fieldC=3'];
- /**
- * @dataProvider unsupportedExpressionTypeDataProvider
- * @expectedException \Symftony\Xpression\Exception\Parser\InvalidExpressionException
- *
- * @param $input
- */
- public function testParserThrowUnsupportedExpressionTypeException($input)
- {
- $this->parser->parse($input);
+ yield ['fieldA=1^|fieldB=2'];
+
+ yield ['fieldA=1⊕fieldB=2'];
+
+ yield ['fieldA=1!&fieldB=2!&fieldC=3'];
+
+ yield ['fieldA=1&fieldB=2&fieldC=3!&fieldD=4'];
+
+ yield ['fieldA=1|fieldB=2|fieldC=3!|fieldD=4'];
+
+ yield ['fieldA=1|fieldB=2|fieldC=3⊕fieldD=4'];
}
}
diff --git a/tests/Bridge/MongoDB/ExprBuilderTest.php b/tests/Bridge/MongoDB/ExprBuilderTest.php
new file mode 100644
index 0000000..cd9d8e8
--- /dev/null
+++ b/tests/Bridge/MongoDB/ExprBuilderTest.php
@@ -0,0 +1,139 @@
+exprAdapter = new ExprBuilder();
+ }
+
+ public function testGetSupportedTokenType(): void
+ {
+ self::assertSame(Lexer::T_ALL - Lexer::T_XOR, $this->exprAdapter->getSupportedTokenType());
+ }
+
+ public function testIsNull(): void
+ {
+ $field = 'fake_field';
+ self::assertSame(['fake_field' => null], $this->exprAdapter->isNull($field));
+ }
+
+ public function testEq(): void
+ {
+ self::assertSame(
+ ['fieldA' => ['$eq' => 1]],
+ $this->exprAdapter->eq('fieldA', 1)
+ );
+ }
+
+ public function testNeq(): void
+ {
+ self::assertSame(
+ ['fieldA' => ['$ne' => 1]],
+ $this->exprAdapter->neq('fieldA', 1)
+ );
+ }
+
+ public function testGt(): void
+ {
+ self::assertSame(
+ ['fieldA' => ['$gt' => 1]],
+ $this->exprAdapter->gt('fieldA', 1)
+ );
+ }
+
+ public function testGte(): void
+ {
+ self::assertSame(
+ ['fieldA' => ['$gte' => 1]],
+ $this->exprAdapter->gte('fieldA', 1)
+ );
+ }
+
+ public function testLt(): void
+ {
+ self::assertSame(
+ ['fieldA' => ['$lt' => 1]],
+ $this->exprAdapter->lt('fieldA', 1)
+ );
+ }
+
+ public function testLte(): void
+ {
+ self::assertSame(
+ ['fieldA' => ['$lte' => 1]],
+ $this->exprAdapter->lte('fieldA', 1)
+ );
+ }
+
+ public function testIn(): void
+ {
+ self::assertSame(
+ ['fieldA' => ['$in' => [1, 2]]],
+ $this->exprAdapter->in('fieldA', [1, 2])
+ );
+ }
+
+ public function testNin(): void
+ {
+ self::assertSame(
+ ['fieldA' => ['$nin' => [1, 2]]],
+ $this->exprAdapter->notIn('fieldA', [1, 2])
+ );
+ }
+
+ public function testAnd(): void
+ {
+ self::assertSame(
+ ['$and' => [['expression1'], ['expression2']]],
+ $this->exprAdapter->andX([['expression1'], ['expression2']])
+ );
+ }
+
+ public function testNand(): void
+ {
+ self::assertSame(
+ ['$or' => [['$not' => ['expression1']], ['$not' => ['expression2']]]],
+ $this->exprAdapter->nandX([['expression1'], ['expression2']])
+ );
+ }
+
+ public function testOr(): void
+ {
+ self::assertSame(
+ ['$or' => [['expression1'], ['expression2']]],
+ $this->exprAdapter->orX([['expression1'], ['expression2']])
+ );
+ }
+
+ public function testNor(): void
+ {
+ self::assertSame(
+ ['$nor' => [['expression1'], ['expression2']]],
+ $this->exprAdapter->norX([['expression1'], ['expression2']])
+ );
+ }
+
+ public function testXorX(): void
+ {
+ $this->expectException(UnsupportedExpressionTypeException::class);
+ $this->expectExceptionMessage('Unsupported expression type "xorX".');
+ $this->exprAdapter->xorX([]);
+ }
+}
diff --git a/tests/Bridge/MongoDB/ParserTest.php b/tests/Bridge/MongoDB/ParserTest.php
new file mode 100644
index 0000000..85550b9
--- /dev/null
+++ b/tests/Bridge/MongoDB/ParserTest.php
@@ -0,0 +1,230 @@
+exprBuilder = new ExprBuilder();
+ $this->parser = new Parser($this->exprBuilder);
+ }
+
+ /**
+ * @dataProvider provideParserCases
+ */
+ public function testParser(string $input, array $expectedExpression): void
+ {
+ self::assertSame($expectedExpression, $this->parser->parse($input));
+ }
+
+ public static function provideParserCases(): iterable
+ {
+ yield [
+ 'fieldA=1',
+ ['fieldA' => ['$eq' => 1]],
+ ];
+
+ yield [
+ 'fieldA="string"',
+ ['fieldA' => ['$eq' => 'string']],
+ ];
+
+ yield [
+ 'fieldA≥1',
+ ['fieldA' => ['$gte' => 1]],
+ ];
+
+ yield [
+ 'fieldA>=1',
+ ['fieldA' => ['$gte' => 1]],
+ ];
+
+ yield [
+ 'fieldA≤1',
+ ['fieldA' => ['$lte' => 1]],
+ ];
+
+ yield [
+ 'fieldA<=1',
+ ['fieldA' => ['$lte' => 1]],
+ ];
+
+ yield [
+ 'fieldA≠1',
+ ['fieldA' => ['$ne' => 1]],
+ ];
+
+ yield [
+ 'fieldA!=1',
+ ['fieldA' => ['$ne' => 1]],
+ ];
+
+ yield [
+ 'fieldA[1,2]',
+ ['fieldA' => ['$in' => [1, 2]]],
+ ];
+
+ yield [
+ 'fieldA![1,2]',
+ ['fieldA' => ['$nin' => [1, 2]]],
+ ];
+
+ yield [
+ 'fieldA{{1}}',
+ ['fieldA' => ['$regex' => 1]],
+ ];
+
+ yield [
+ 'fieldA!{{1}}',
+ ['$not' => ['fieldA' => ['$regex' => 1]]],
+ ];
+
+ yield [
+ 'fieldA=1|fieldB=2|fieldC=3',
+ [
+ '$or' => [
+ ['fieldA' => ['$eq' => 1]],
+ ['fieldB' => ['$eq' => 2]],
+ ['fieldC' => ['$eq' => 3]],
+ ],
+ ],
+ ];
+
+ yield [
+ 'fieldA=1&fieldB=2&fieldC=3',
+ [
+ '$and' => [
+ ['fieldA' => ['$eq' => 1]],
+ ['fieldB' => ['$eq' => 2]],
+ ['fieldC' => ['$eq' => 3]],
+ ],
+ ],
+ ];
+
+ // Precedences
+ yield [
+ 'fieldA=1|fieldB=2|fieldC=3&fieldD=4',
+ [
+ '$or' => [
+ ['fieldA' => ['$eq' => 1]],
+ ['fieldB' => ['$eq' => 2]],
+ [
+ '$and' => [
+ ['fieldC' => ['$eq' => 3]],
+ ['fieldD' => ['$eq' => 4]],
+ ],
+ ],
+ ],
+ ],
+ ];
+
+ yield [
+ 'fieldA=1&fieldB=2&fieldC=3|fieldD=4',
+ [
+ '$or' => [
+ [
+ '$and' => [
+ ['fieldA' => ['$eq' => 1]],
+ ['fieldB' => ['$eq' => 2]],
+ ['fieldC' => ['$eq' => 3]],
+ ],
+ ],
+ ['fieldD' => ['$eq' => 4]],
+ ],
+ ],
+ ];
+
+ yield [
+ 'fieldA=1&fieldB=2|fieldC=3&fieldD=4',
+ [
+ '$or' => [
+ [
+ '$and' => [
+ ['fieldA' => ['$eq' => 1]],
+ ['fieldB' => ['$eq' => 2]],
+ ],
+ ],
+ [
+ '$and' => [
+ ['fieldC' => ['$eq' => 3]],
+ ['fieldD' => ['$eq' => 4]],
+ ],
+ ],
+ ],
+ ],
+ ];
+
+ // Parenthesis
+ yield [
+ '((fieldA=1))',
+ ['fieldA' => ['$eq' => 1]],
+ ];
+
+ yield [
+ '(fieldA=1|fieldB=2)&fieldC=3',
+ [
+ '$and' => [
+ [
+ '$or' => [
+ ['fieldA' => ['$eq' => 1]],
+ ['fieldB' => ['$eq' => 2]],
+ ],
+ ],
+ ['fieldC' => ['$eq' => 3]],
+ ],
+ ],
+ ];
+
+ yield [
+ 'fieldA=1|(fieldB=2&fieldC=3)',
+ [
+ '$or' => [
+ ['fieldA' => ['$eq' => 1]],
+ [
+ '$and' => [
+ ['fieldB' => ['$eq' => 2]],
+ ['fieldC' => ['$eq' => 3]],
+ ],
+ ],
+ ],
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider provideParserThrowUnsupportedExpressionTypeExceptionCases
+ */
+ public function testParserThrowUnsupportedExpressionTypeException(string $input): void
+ {
+ $this->expectException(InvalidExpressionException::class);
+ $this->expectExceptionMessage('Invalid expression.');
+ $this->parser->parse($input);
+ }
+
+ public static function provideParserThrowUnsupportedExpressionTypeExceptionCases(): iterable
+ {
+ yield ['fieldA=1^|fieldB=2'];
+
+ yield ['fieldA=1⊕fieldB=2'];
+
+ yield ['fieldA=1|fieldB=2|fieldC=3⊕fieldD=4'];
+ }
+}
diff --git a/tests/Expr/ClosureExpressionBuilderTest.php b/tests/Expr/ClosureExpressionBuilderTest.php
index 8567730..b4289d4 100644
--- a/tests/Expr/ClosureExpressionBuilderTest.php
+++ b/tests/Expr/ClosureExpressionBuilderTest.php
@@ -1,304 +1,266 @@
exampleData = array(
+ $this->exampleData = [
'field_null' => null,
'field_number_5' => 5,
'field_number_10' => 10,
'field_string' => 'my_fake_string',
- );
+ ];
$this->closureExpressionBuilder = new ClosureExpressionBuilder();
}
- public function getObjectFieldValueDataProvider()
- {
- $object = new \stdClass();
- $object->property = 'fake_property';
- $object->_property4 = 'fake_property';
-
- return array(
- array(
- array('fake_key' => 'fake_value'),
- 'fake_key',
- 'fake_value'
- ),
- array(
- new FakeClass(),
- 'property1',
- 'fake_is_property'
- ),
- array(
- new FakeClass(),
- 'property2',
- 'fake_get_property'
- ),
- array(
- new FakeClass(),
- 'callProperty',
- 'getcallProperty'
- ),
- array(
- new FakeArrayAccess(),
- 'callProperty',
- 'callProperty'
- ),
- array(
- $object,
- 'property',
- 'fake_property'
- ),
- array(
- new FakeClass2(),
- '_property4',
- 'property4'
- ),
- array(
- $object,
- '_property4',
- 'fake_property'
- ),
- );
- }
-
/**
- * @dataProvider getObjectFieldValueDataProvider
- *
- * @param $object
- * @param $value
- * @param $expectedResult
+ * @dataProvider provideGetObjectFieldValueCases
*/
- public function testGetObjectFieldValue($object, $value, $expectedResult)
+ public function testGetObjectFieldValue(mixed $object, mixed $value, mixed $expectedResult): void
{
- $this->assertEquals($expectedResult, ClosureExpressionBuilder::getObjectFieldValue($object, $value));
+ self::assertSame($expectedResult, ClosureExpressionBuilder::getObjectFieldValue($object, $value));
}
- public function testGetSupportedTokenType()
+ public static function provideGetObjectFieldValueCases(): iterable
{
- $this->assertEquals(Lexer::T_ALL, $this->closureExpressionBuilder->getSupportedTokenType());
+ yield [
+ ['fake_key' => 'fake_value'],
+ 'fake_key',
+ 'fake_value',
+ ];
+
+ yield [
+ new FakeClass(),
+ 'property1',
+ 'fake_is_property',
+ ];
+
+ yield [
+ new FakeClass(),
+ 'property2',
+ 'fake_get_property',
+ ];
+
+ yield [
+ new FakeClass(),
+ 'callProperty',
+ 'getcallProperty',
+ ];
+
+ yield [
+ new FakeClass2(),
+ '_property4',
+ 'property4',
+ ];
+
+ yield [
+ new FakeArrayAccess(),
+ 'callProperty',
+ 'callProperty',
+ ];
+
+ $object = new \stdClass();
+ $object->property = 'fake_property';
+ $object->_property4 = 'fake_property';
+
+ yield [
+ $object,
+ 'property',
+ 'fake_property',
+ ];
+
+ yield [
+ $object,
+ '_property4',
+ 'fake_property',
+ ];
}
- public function testParameter()
+ public function testGetSupportedTokenType(): void
{
- $this->assertEquals('my_fake_data', $this->closureExpressionBuilder->parameter('my_fake_data'));
- $this->assertEquals('my_fake_data', $this->closureExpressionBuilder->parameter('my_fake_data', true));
+ self::assertSame(Lexer::T_ALL, $this->closureExpressionBuilder->getSupportedTokenType());
}
- public function testString()
+ public function testParameter(): void
{
- $this->assertEquals('my_fake_data', $this->closureExpressionBuilder->string('my_fake_data'));
+ self::assertSame('my_fake_data', $this->closureExpressionBuilder->parameter('my_fake_data'));
+ self::assertSame('my_fake_data', $this->closureExpressionBuilder->parameter('my_fake_data', true));
}
- public function isNullDataProvider()
+ public function testString(): void
{
- return array(
- array('field_null', true),
- array('field_number_5', false),
- );
+ self::assertSame('my_fake_data', $this->closureExpressionBuilder->string('my_fake_data'));
}
/**
- * @dataProvider isNullDataProvider
- *
- * @param $field
- * @param $expectedResult
+ * @dataProvider provideIsNullCases
*/
- public function testIsNull($field, $expectedResult)
+ public function testIsNull(mixed $field, mixed $expectedResult): void
{
$expression = $this->closureExpressionBuilder->isNull($field);
- $this->assertEquals(
+ self::assertSame(
$expectedResult,
$expression($this->exampleData)
);
}
- public function eqDataProvider()
+ public static function provideIsNullCases(): iterable
{
- return array(
- array('field_number_5', 1, false),
- array('field_number_5', 5, true),
- array('field_number_5', 10, false),
- );
+ yield ['field_null', true];
+
+ yield ['field_number_5', false];
}
/**
- * @dataProvider eqDataProvider
- *
- * @param $field
- * @param $value
- * @param $expectedResult
+ * @dataProvider provideEqCases
*/
- public function testEq($field, $value, $expectedResult)
+ public function testEq(mixed $field, mixed $value, mixed $expectedResult): void
{
$expression = $this->closureExpressionBuilder->eq($field, $value);
- $this->assertEquals(
+ self::assertSame(
$expectedResult,
$expression($this->exampleData)
);
}
- public function neqDataProvider()
+ public static function provideEqCases(): iterable
{
- return array(
- array('field_number_5', 1, true),
- array('field_number_5', 5, false),
- array('field_number_5', 10, true),
- );
+ yield ['field_number_5', 1, false];
+
+ yield ['field_number_5', 5, true];
+
+ yield ['field_number_5', 10, false];
}
/**
- * @dataProvider neqDataProvider
- *
- * @param $field
- * @param $value
- * @param $expectedResult
+ * @dataProvider provideNeqCases
*/
- public function testNeq($field, $value, $expectedResult)
+ public function testNeq(mixed $field, mixed $value, mixed $expectedResult): void
{
$expression = $this->closureExpressionBuilder->neq($field, $value);
- $this->assertEquals(
+ self::assertSame(
$expectedResult,
$expression($this->exampleData)
);
}
- public function gtDataProvider()
+ public static function provideNeqCases(): iterable
{
- return array(
- array('field_number_5', 1, true),
- array('field_number_5', 5, false),
- array('field_number_5', 10, false),
- );
+ yield ['field_number_5', 1, true];
+
+ yield ['field_number_5', 5, false];
+
+ yield ['field_number_5', 10, true];
}
/**
- * @dataProvider gtDataProvider
- *
- * @param $field
- * @param $value
- * @param $expectedResult
+ * @dataProvider provideGtCases
*/
- public function testGt($field, $value, $expectedResult)
+ public function testGt(mixed $field, mixed $value, mixed $expectedResult): void
{
$expression = $this->closureExpressionBuilder->gt($field, $value);
- $this->assertEquals(
+ self::assertSame(
$expectedResult,
$expression($this->exampleData)
);
}
- public function gteDataProvider()
+ public static function provideGtCases(): iterable
{
- return array(
- array('field_number_5', 1, true),
- array('field_number_5', 5, true),
- array('field_number_5', 10, false),
- );
+ yield ['field_number_5', 1, true];
+
+ yield ['field_number_5', 5, false];
+
+ yield ['field_number_5', 10, false];
}
/**
- * @dataProvider gteDataProvider
- *
- * @param $field
- * @param $value
- * @param $expectedResult
+ * @dataProvider provideGteCases
*/
- public function testGte($field, $value, $expectedResult)
+ public function testGte(mixed $field, mixed $value, mixed $expectedResult): void
{
$expression = $this->closureExpressionBuilder->gte($field, $value);
- $this->assertEquals(
+ self::assertSame(
$expectedResult,
$expression($this->exampleData)
);
}
- public function ltDataProvider()
+ public static function provideGteCases(): iterable
{
- return array(
- array('field_number_5', 1, false),
- array('field_number_5', 5, false),
- array('field_number_5', 10, true),
- );
+ yield ['field_number_5', 1, true];
+
+ yield ['field_number_5', 5, true];
+
+ yield ['field_number_5', 10, false];
}
/**
- * @dataProvider ltDataProvider
- *
- * @param $field
- * @param $value
- * @param $expectedResult
+ * @dataProvider provideLtCases
*/
- public function testLt($field, $value, $expectedResult)
+ public function testLt(mixed $field, mixed $value, mixed $expectedResult): void
{
$expression = $this->closureExpressionBuilder->lt($field, $value);
- $this->assertEquals(
+ self::assertSame(
$expectedResult,
$expression($this->exampleData)
);
}
- public function lteDataProvider()
+ public static function provideLtCases(): iterable
{
- return array(
- array('field_number_5', 1, false),
- array('field_number_5', 5, true),
- array('field_number_5', 10, true),
- );
+ yield ['field_number_5', 1, false];
+
+ yield ['field_number_5', 5, false];
+
+ yield ['field_number_5', 10, true];
}
/**
- * @dataProvider lteDataProvider
- *
- * @param $field
- * @param $value
- * @param $expectedResult
+ * @dataProvider provideLteCases
*/
- public function testLte($field, $value, $expectedResult)
+ public function testLte(mixed $field, mixed $value, mixed $expectedResult): void
{
$expression = $this->closureExpressionBuilder->lte($field, $value);
- $this->assertEquals(
+ self::assertSame(
$expectedResult,
$expression($this->exampleData)
);
}
- public function inDataProvider()
+ public static function provideLteCases(): iterable
{
- return array(
- array('field_number_5', array(1), false),
- array('field_number_5', array(1, 2, 3, 4, 5), true),
- );
+ yield ['field_number_5', 1, false];
+
+ yield ['field_number_5', 5, true];
+
+ yield ['field_number_5', 10, true];
}
/**
* @dataProvider inDataProvider
- *
- * @param $field
- * @param $value
- * @param $expectedResult
*/
- public function testIn($field, $value, $expectedResult)
+ public function testIn(mixed $field, mixed $value, mixed $expectedResult): void
{
$expression = $this->closureExpressionBuilder->in($field, $value);
- $this->assertEquals(
+ self::assertSame(
$expectedResult,
$expression($this->exampleData)
);
@@ -306,39 +268,30 @@ public function testIn($field, $value, $expectedResult)
/**
* @dataProvider inDataProvider
- *
- * @param $field
- * @param $value
- * @param $expectedResult
*/
- public function testNotIn($field, $value, $expectedResult)
+ public function testNotIn(mixed $field, mixed $value, mixed $expectedResult): void
{
$expression = $this->closureExpressionBuilder->notIn($field, $value);
- $this->assertEquals(
+ self::assertSame(
!$expectedResult,
$expression($this->exampleData)
);
}
- public function containsDataProvider()
+ public static function inDataProvider(): iterable
{
- return array(
- array('field_string', 'toto', false),
- array('field_string', 'fake', true),
- );
+ yield ['field_number_5', [1], false];
+
+ yield ['field_number_5', [1, 2, 3, 4, 5], true];
}
/**
* @dataProvider containsDataProvider
- *
- * @param $field
- * @param $value
- * @param $expectedResult
*/
- public function testContains($field, $value, $expectedResult)
+ public function testContains(mixed $field, mixed $value, mixed $expectedResult): void
{
$expression = $this->closureExpressionBuilder->contains($field, $value);
- $this->assertEquals(
+ self::assertSame(
$expectedResult,
$expression($this->exampleData)
);
@@ -346,45 +299,31 @@ public function testContains($field, $value, $expectedResult)
/**
* @dataProvider containsDataProvider
- *
- * @param $field
- * @param $value
- * @param $expectedResult
*/
- public function testNotContains($field, $value, $expectedResult)
+ public function testNotContains(mixed $field, mixed $value, mixed $expectedResult): void
{
$expression = $this->closureExpressionBuilder->notContains($field, $value);
- $this->assertEquals(
+ self::assertSame(
!$expectedResult,
$expression($this->exampleData)
);
}
- public function andXDataProvider()
+ public static function containsDataProvider(): iterable
{
- return array(
- array(array(false, false), false),
- array(array(false, true), false),
- array(array(true, false), false),
- array(array(true, true), true),
- );
+ yield ['field_string', 'toto', false];
+
+ yield ['field_string', 'fake', true];
}
/**
* @dataProvider andXDataProvider
- *
- * @param array $expressions
- * @param $expectedResult
*/
- public function testAndX(array $expressions, $expectedResult)
+ public function testAndX(array $expressions, mixed $expectedResult): void
{
- $expressionsCallable = array_map(function ($value) {
- return function () use ($value) {
- return $value;
- };
- }, $expressions);
+ $expressionsCallable = array_map(static fn ($value) => static fn () => $value, $expressions);
$expression = $this->closureExpressionBuilder->andX($expressionsCallable);
- $this->assertEquals(
+ self::assertSame(
$expectedResult,
$expression('useless_data')
);
@@ -392,49 +331,36 @@ public function testAndX(array $expressions, $expectedResult)
/**
* @dataProvider andXDataProvider
- *
- * @param array $expressions
- * @param $expectedResult
*/
- public function testNandX(array $expressions, $expectedResult)
+ public function testNandX(array $expressions, mixed $expectedResult): void
{
- $expressionsCallable = array_map(function ($value) {
- return function () use ($value) {
- return $value;
- };
- }, $expressions);
+ $expressionsCallable = array_map(static fn ($value) => static fn () => $value, $expressions);
$expression = $this->closureExpressionBuilder->nandX($expressionsCallable);
- $this->assertEquals(
+ self::assertSame(
!$expectedResult,
$expression('useless_data')
);
}
- public function orXDataProvider()
+ public static function andXDataProvider(): iterable
{
- return array(
- array(array(false, false), false),
- array(array(false, true), true),
- array(array(true, false), true),
- array(array(true, true), true),
- );
+ yield [[false, false], false];
+
+ yield [[false, true], false];
+
+ yield [[true, false], false];
+
+ yield [[true, true], true];
}
/**
* @dataProvider orXDataProvider
- *
- * @param array $expressions
- * @param $expectedResult
*/
- public function testOrX(array $expressions, $expectedResult)
+ public function testOrX(array $expressions, mixed $expectedResult): void
{
- $expressionsCallable = array_map(function ($value) {
- return function () use ($value) {
- return $value;
- };
- }, $expressions);
+ $expressionsCallable = array_map(static fn ($value) => static fn () => $value, $expressions);
$expression = $this->closureExpressionBuilder->orX($expressionsCallable);
- $this->assertEquals(
+ self::assertSame(
$expectedResult,
$expression('useless_data')
);
@@ -442,66 +368,76 @@ public function testOrX(array $expressions, $expectedResult)
/**
* @dataProvider orXDataProvider
- *
- * @param array $expressions
- * @param $expectedResult
*/
- public function testNorX(array $expressions, $expectedResult)
+ public function testNorX(array $expressions, mixed $expectedResult): void
{
- $expressionsCallable = array_map(function ($value) {
- return function () use ($value) {
- return $value;
- };
- }, $expressions);
+ $expressionsCallable = array_map(static fn ($value) => static fn () => $value, $expressions);
$expression = $this->closureExpressionBuilder->norX($expressionsCallable);
- $this->assertEquals(
+ self::assertSame(
!$expectedResult,
$expression('useless_data')
);
}
- public function xorXDataProvider()
+ public static function orXDataProvider(): iterable
{
- return array(
- array(array(false, false), false),
- array(array(false, true), true),
- array(array(true, false), true),
- array(array(true, true), false),
+ yield [[false, false], false];
- array(array(false, false, false), false),
- array(array(false, false, true), true),
- array(array(false, true, false), true),
- array(array(false, true, true), false),
- array(array(true, false, false), true),
- array(array(true, false, true), false),
- array(array(true, true, false), false),
- array(array(true, true, true), true),
- );
+ yield [[false, true], true];
+
+ yield [[true, false], true];
+
+ yield [[true, true], true];
}
/**
- * @dataProvider xorXDataProvider
- *
- * @param array $expressions
- * @param $expectedResult
+ * @dataProvider provideXorXCases
*/
- public function testXorX(array $expressions, $expectedResult)
+ public function testXorX(array $expressions, mixed $expectedResult): void
{
- $expressionsCallable = array_map(function ($value) {
- return function () use ($value) {
- return $value;
- };
- }, $expressions);
+ $expressionsCallable = array_map(static fn ($value) => static fn () => $value, $expressions);
$expression = $this->closureExpressionBuilder->xorX($expressionsCallable);
- $this->assertEquals(
+ self::assertEquals(
$expectedResult,
$expression('useless_data')
);
}
+
+ public static function provideXorXCases(): iterable
+ {
+ yield [[false, false], false];
+
+ yield [[false, true], true];
+
+ yield [[true, false], true];
+
+ yield [[true, true], false];
+
+ yield [[false, false, false], false];
+
+ yield [[false, false, true], true];
+
+ yield [[false, true, false], true];
+
+ yield [[false, true, true], false];
+
+ yield [[true, false, false], true];
+
+ yield [[true, false, true], false];
+
+ yield [[true, true, false], false];
+
+ yield [[true, true, true], true];
+ }
}
class FakeClass
{
+ public function __call($name, $arguments)
+ {
+ return $name.implode(', ', $arguments);
+ }
+
public function isProperty1()
{
return 'fake_is_property';
@@ -521,11 +457,6 @@ public function getPROPERTY4()
{
return 'property4';
}
-
- public function __call($name, $arguments)
- {
- return $name . implode(', ', $arguments);
- }
}
class FakeClass2
@@ -543,20 +474,17 @@ public function getPROPERTY4()
class FakeArrayAccess implements \ArrayAccess
{
- public function offsetExists($offset)
+ public function offsetExists($offset): bool
{
+ return false;
}
- public function offsetGet($offset)
+ public function offsetGet($offset): mixed
{
return $offset;
}
- public function offsetSet($offset, $value)
- {
- }
+ public function offsetSet($offset, $value): void {}
- public function offsetUnset($offset)
- {
- }
+ public function offsetUnset($offset): void {}
}
diff --git a/tests/Expr/HtmlExpressionBuilderTest.php b/tests/Expr/HtmlExpressionBuilderTest.php
index 66ee6d7..fb555c8 100644
--- a/tests/Expr/HtmlExpressionBuilderTest.php
+++ b/tests/Expr/HtmlExpressionBuilderTest.php
@@ -1,424 +1,381 @@
closureExpressionBuilder = new HtmlExpressionBuilder();
- }
+ private HtmlExpressionBuilder $htmlExpressionBuilder;
- public function testGetSupportedTokenType()
+ protected function setUp(): void
{
- $this->assertEquals(Lexer::T_ALL, $this->closureExpressionBuilder->getSupportedTokenType());
+ $this->htmlExpressionBuilder = new HtmlExpressionBuilder();
}
- public function testParameter()
+ public function testGetSupportedTokenType(): void
{
- $this->assertEquals('my_fake_data', $this->closureExpressionBuilder->parameter('my_fake_data'));
- $this->assertEquals('my_fake_data', $this->closureExpressionBuilder->parameter('my_fake_data', true));
+ self::assertSame(Lexer::T_ALL, $this->htmlExpressionBuilder->getSupportedTokenType());
}
- public function testString()
+ public function testParameter(): void
{
- $this->assertEquals('"my_fake_data"', $this->closureExpressionBuilder->string('my_fake_data'));
+ self::assertSame('my_fake_data', $this->htmlExpressionBuilder->parameter('my_fake_data'));
+ self::assertSame('my_fake_data', $this->htmlExpressionBuilder->parameter('my_fake_data', true));
}
- public function isNullDataProvider()
+ public function testString(): void
{
- return array(
- array('field_null', 'field_null is null
'),
- array('field_number_5', 'field_number_5 is null
'),
- );
+ self::assertSame('"my_fake_data"', $this->htmlExpressionBuilder->string('my_fake_data'));
}
/**
- * @dataProvider isNullDataProvider
- *
- * @param $field
- * @param $expectedResult
+ * @dataProvider provideIsNullCases
*/
- public function testIsNull($field, $expectedResult)
+ public function testIsNull(string $field, string $expectedResult): void
{
- $this->assertEquals(
+ self::assertSame(
$expectedResult,
- $this->closureExpressionBuilder->isNull($field)
+ $this->htmlExpressionBuilder->isNull($field)
);
}
- public function eqDataProvider()
+ public static function provideIsNullCases(): iterable
{
- return array(
- array('field_number_5', 1, 'field_number_5 = 1
'),
- array('field_number_5', 5, 'field_number_5 = 5
'),
- array('field_number_5', 10, 'field_number_5 = 10
'),
- );
+ yield ['field_null', 'field_null is null
'];
+
+ yield ['field_number_5', 'field_number_5 is null
'];
}
/**
- * @dataProvider eqDataProvider
- *
- * @param $field
- * @param $value
- * @param $expectedResult
+ * @dataProvider provideEqCases
*/
- public function testEq($field, $value, $expectedResult)
+ public function testEq(string $field, mixed $value, string $expectedResult): void
{
- $this->assertEquals(
+ self::assertSame(
$expectedResult,
- $this->closureExpressionBuilder->eq($field, $value)
+ $this->htmlExpressionBuilder->eq($field, $value)
);
}
- public function neqDataProvider()
+ public static function provideEqCases(): iterable
{
- return array(
- array('field_number_5', 1, 'field_number_5 ≠ 1
'),
- array('field_number_5', 5, 'field_number_5 ≠ 5
'),
- array('field_number_5', 10, 'field_number_5 ≠ 10
'),
- );
+ return [
+ ['field_number_5', 1, 'field_number_5 = 1
'],
+ ['field_number_5', 5, 'field_number_5 = 5
'],
+ ['field_number_5', 10, 'field_number_5 = 10
'],
+ ];
}
/**
- * @dataProvider neqDataProvider
- *
- * @param $field
- * @param $value
- * @param $expectedResult
+ * @dataProvider provideNeqCases
*/
- public function testNeq($field, $value, $expectedResult)
+ public function testNeq(string $field, mixed $value, string $expectedResult): void
{
- $this->assertEquals(
+ self::assertSame(
$expectedResult,
- $this->closureExpressionBuilder->neq($field, $value)
+ $this->htmlExpressionBuilder->neq($field, $value)
);
}
- public function gtDataProvider()
+ public static function provideNeqCases(): iterable
{
- return array(
- array('field_number_5', 1, 'field_number_5 > 1
'),
- array('field_number_5', 5, 'field_number_5 > 5
'),
- array('field_number_5', 10, 'field_number_5 > 10
'),
- );
+ yield ['field_number_5', 1, 'field_number_5 ≠ 1
'];
+
+ yield ['field_number_5', 5, 'field_number_5 ≠ 5
'];
+
+ yield ['field_number_5', 10, 'field_number_5 ≠ 10
'];
}
/**
- * @dataProvider gtDataProvider
- *
- * @param $field
- * @param $value
- * @param $expectedResult
+ * @dataProvider provideGtCases
*/
- public function testGt($field, $value, $expectedResult)
+ public function testGt(string $field, mixed $value, string $expectedResult): void
{
- $this->assertEquals(
+ self::assertSame(
$expectedResult,
- $this->closureExpressionBuilder->gt($field, $value)
+ $this->htmlExpressionBuilder->gt($field, $value)
);
}
- public function gteDataProvider()
+ public static function provideGtCases(): iterable
{
- return array(
- array('field_number_5', 1, 'field_number_5 ≥ 1
'),
- array('field_number_5', 5, 'field_number_5 ≥ 5
'),
- array('field_number_5', 10, 'field_number_5 ≥ 10
'),
- );
+ yield ['field_number_5', 1, 'field_number_5 > 1
'];
+
+ yield ['field_number_5', 5, 'field_number_5 > 5
'];
+
+ yield ['field_number_5', 10, 'field_number_5 > 10
'];
}
/**
- * @dataProvider gteDataProvider
- *
- * @param $field
- * @param $value
- * @param $expectedResult
+ * @dataProvider provideGteCases
*/
- public function testGte($field, $value, $expectedResult)
+ public function testGte(string $field, mixed $value, string $expectedResult): void
{
- $this->assertEquals(
+ self::assertSame(
$expectedResult,
- $this->closureExpressionBuilder->gte($field, $value)
+ $this->htmlExpressionBuilder->gte($field, $value)
);
}
- public function ltDataProvider()
+ public static function provideGteCases(): iterable
{
- return array(
- array('field_number_5', 1, 'field_number_5 < 1
'),
- array('field_number_5', 5, 'field_number_5 < 5
'),
- array('field_number_5', 10, 'field_number_5 < 10
'),
- );
+ yield ['field_number_5', 1, 'field_number_5 ≥ 1
'];
+
+ yield ['field_number_5', 5, 'field_number_5 ≥ 5
'];
+
+ yield ['field_number_5', 10, 'field_number_5 ≥ 10
'];
}
/**
- * @dataProvider ltDataProvider
- *
- * @param $field
- * @param $value
- * @param $expectedResult
+ * @dataProvider provideLtCases
*/
- public function testLt($field, $value, $expectedResult)
+ public function testLt(string $field, mixed $value, string $expectedResult): void
{
- $this->assertEquals(
+ self::assertSame(
$expectedResult,
- $this->closureExpressionBuilder->lt($field, $value)
+ $this->htmlExpressionBuilder->lt($field, $value)
);
}
- public function lteDataProvider()
+ public static function provideLtCases(): iterable
{
- return array(
- array('field_number_5', 1, 'field_number_5 ≤ 1
'),
- array('field_number_5', 5, 'field_number_5 ≤ 5
'),
- array('field_number_5', 10, 'field_number_5 ≤ 10
'),
- );
+ yield ['field_number_5', 1, 'field_number_5 < 1
'];
+
+ yield ['field_number_5', 5, 'field_number_5 < 5
'];
+
+ yield ['field_number_5', 10, 'field_number_5 < 10
'];
}
/**
- * @dataProvider lteDataProvider
- *
- * @param $field
- * @param $value
- * @param $expectedResult
+ * @dataProvider provideLteCases
*/
- public function testLte($field, $value, $expectedResult)
+ public function testLte(string $field, mixed $value, string $expectedResult): void
{
- $this->assertEquals(
+ self::assertSame(
$expectedResult,
- $this->closureExpressionBuilder->lte($field, $value)
+ $this->htmlExpressionBuilder->lte($field, $value)
);
}
- public function inDataProvider()
+ public static function provideLteCases(): iterable
{
- return array(
- array('field_number_5', array(1), 'field_number_5 value in 1
'),
- array('field_number_5', array(1, 2, 3, 4, 5), 'field_number_5 value in 1, 2, 3, 4, 5
'),
- );
+ yield ['field_number_5', 1, 'field_number_5 ≤ 1
'];
+
+ yield ['field_number_5', 5, 'field_number_5 ≤ 5
'];
+
+ yield ['field_number_5', 10, 'field_number_5 ≤ 10
'];
}
/**
- * @dataProvider inDataProvider
- *
- * @param $field
- * @param $value
- * @param $expectedResult
+ * @dataProvider provideInCases
*/
- public function testIn($field, $value, $expectedResult)
+ public function testIn(string $field, mixed $value, string $expectedResult): void
{
- $this->assertEquals(
+ self::assertSame(
$expectedResult,
- $this->closureExpressionBuilder->in($field, $value)
+ $this->htmlExpressionBuilder->in($field, $value)
);
}
- public function notInDataProvider()
+ public static function provideInCases(): iterable
{
- return array(
- array('field_number_5', array(1), 'field_number_5 value not in 1
'),
- array('field_number_5', array(1, 2, 3, 4, 5), 'field_number_5 value not in 1, 2, 3, 4, 5
'),
- );
+ yield ['field_number_5', [1], 'field_number_5 value in 1
'];
+
+ yield ['field_number_5', [1, 2, 3, 4, 5], 'field_number_5 value in 1, 2, 3, 4, 5
'];
}
/**
- * @dataProvider notInDataProvider
- *
- * @param $field
- * @param $value
- * @param $expectedResult
+ * @dataProvider provideNotInCases
*/
- public function testNotIn($field, $value, $expectedResult)
+ public function testNotIn(string $field, mixed $value, string $expectedResult): void
{
- $this->assertEquals(
+ self::assertSame(
$expectedResult,
- $this->closureExpressionBuilder->notIn($field, $value)
+ $this->htmlExpressionBuilder->notIn($field, $value)
);
}
- public function containsDataProvider()
+ public static function provideNotInCases(): iterable
{
- return array(
- array('field_string', 'toto', 'field_string contains toto
'),
- array('field_string', 'fake', 'field_string contains fake
'),
- );
+ yield ['field_number_5', [1], 'field_number_5 value not in 1
'];
+
+ yield ['field_number_5', [1, 2, 3, 4, 5], 'field_number_5 value not in 1, 2, 3, 4, 5
'];
}
/**
- * @dataProvider containsDataProvider
+ * @dataProvider provideContainsCases
*
- * @param $field
- * @param $value
- * @param $expectedResult
+ * @param mixed $field
+ * @param mixed $value
+ * @param mixed $expectedResult
*/
- public function testContains($field, $value, $expectedResult)
+ public function testContains($field, $value, $expectedResult): void
{
- $this->assertEquals(
+ self::assertSame(
$expectedResult,
- $this->closureExpressionBuilder->contains($field, $value)
+ $this->htmlExpressionBuilder->contains($field, $value)
);
}
- public function notContainsDataProvider()
+ public static function provideContainsCases(): iterable
{
- return array(
- array('field_string', 'toto', 'field_string notContains toto
'),
- array('field_string', 'fake', 'field_string notContains fake
'),
- );
+ yield ['field_string', 'toto', 'field_string contains toto
'];
+
+ yield ['field_string', 'fake', 'field_string contains fake
'];
}
/**
- * @dataProvider notContainsDataProvider
- *
- * @param $field
- * @param $value
- * @param $expectedResult
+ * @dataProvider provideNotContainsCases
*/
- public function testNotContains($field, $value, $expectedResult)
+ public function testNotContains(string $field, mixed $value, string $expectedResult): void
{
- $this->assertEquals(
+ self::assertSame(
$expectedResult,
- $this->closureExpressionBuilder->notContains($field, $value)
+ $this->htmlExpressionBuilder->notContains($field, $value)
);
}
- public function andXDataProvider()
+ public static function provideNotContainsCases(): iterable
{
- return array(
- array(array('false', 'false'), ''),
- array(array('false', 'true'), ''),
- array(array('true', 'false'), ''),
- array(array('true', 'true'), ''),
- );
+ return [
+ ['field_string', 'toto', 'field_string notContains toto
'],
+ ['field_string', 'fake', 'field_string notContains fake
'],
+ ];
}
/**
- * @dataProvider andXDataProvider
- *
- * @param array $expressions
- * @param $expectedResult
+ * @dataProvider provideAndXCases
*/
- public function testAndX(array $expressions, $expectedResult)
+ public function testAndX(array $expressions, string $expectedResult): void
{
- $this->assertEquals(
+ self::assertSame(
$expectedResult,
- $this->closureExpressionBuilder->andX($expressions)
+ $this->htmlExpressionBuilder->andX($expressions)
);
}
- public function nandXDataProvider()
+ public static function provideAndXCases(): iterable
{
- return array(
- array(array('false', 'false'), ''),
- array(array('false', 'true'), ''),
- array(array('true', 'false'), ''),
- array(array('true', 'true'), ''),
- );
+ yield [['false', 'false'], ''];
+
+ yield [['false', 'true'], ''];
+
+ yield [['true', 'false'], ''];
+
+ yield [['true', 'true'], ''];
}
/**
- * @dataProvider nandXDataProvider
- *
- * @param array $expressions
- * @param $expectedResult
+ * @dataProvider provideNandXCases
*/
- public function testNandX(array $expressions, $expectedResult)
+ public function testNandX(array $expressions, string $expectedResult): void
{
- $this->assertEquals(
+ self::assertSame(
$expectedResult,
- $this->closureExpressionBuilder->nandX($expressions)
+ $this->htmlExpressionBuilder->nandX($expressions)
);
}
- public function orXDataProvider()
+ public static function provideNandXCases(): iterable
{
- return array(
- array(array('false', 'false'), ''),
- array(array('false', 'true'), ''),
- array(array('true', 'false'), ''),
- array(array('true', 'true'), ''),
- );
+ yield [['false', 'false'], ''];
+
+ yield [['false', 'true'], ''];
+
+ yield [['true', 'false'], ''];
+
+ yield [['true', 'true'], ''];
}
/**
- * @dataProvider orXDataProvider
- *
- * @param array $expressions
- * @param $expectedResult
+ * @dataProvider provideOrXCases
*/
- public function testOrX(array $expressions, $expectedResult)
+ public function testOrX(array $expressions, string $expectedResult): void
{
- $this->assertEquals(
+ self::assertSame(
$expectedResult,
- $this->closureExpressionBuilder->orX($expressions)
+ $this->htmlExpressionBuilder->orX($expressions)
);
}
- public function norXDataProvider()
+ public static function provideOrXCases(): iterable
{
- return array(
- array(array('false', 'false'), ''),
- array(array('false', 'true'), ''),
- array(array('true', 'false'), ''),
- array(array('true', 'true'), ''),
- );
+ yield [['false', 'false'], ''];
+
+ yield [['false', 'true'], ''];
+
+ yield [['true', 'false'], ''];
+
+ yield [['true', 'true'], ''];
}
/**
- * @dataProvider norXDataProvider
- *
- * @param array $expressions
- * @param $expectedResult
+ * @dataProvider provideNorXCases
*/
- public function testNorX(array $expressions, $expectedResult)
+ public function testNorX(array $expressions, string $expectedResult): void
{
- $this->assertEquals(
+ self::assertSame(
$expectedResult,
- $this->closureExpressionBuilder->norX($expressions)
+ $this->htmlExpressionBuilder->norX($expressions)
);
}
- public function xorXDataProvider()
+ public static function provideNorXCases(): iterable
{
- return array(
- array(array('false', 'false'), ''),
- array(array('false', 'true'), ''),
- array(array('true', 'false'), ''),
- array(array('true', 'true'), ''),
+ yield [['false', 'false'], ''];
- array(array('false', 'false', 'false'), ''),
- array(array('false', 'false', 'true'), ''),
- array(array('false', 'true', 'false'), ''),
- array(array('false', 'true', 'true'), ''),
- array(array('true', 'false', 'false'), ''),
- array(array('true', 'false', 'true'), ''),
- array(array('true', 'true', 'false'), ''),
- array(array('true', 'true', 'true'), ''),
- );
+ yield [['false', 'true'], ''];
+
+ yield [['true', 'false'], ''];
+
+ yield [['true', 'true'], ''];
}
/**
- * @dataProvider xorXDataProvider
- *
- * @param array $expressions
- * @param $expectedResult
+ * @dataProvider provideXorXCases
*/
- public function testXorX(array $expressions, $expectedResult)
+ public function testXorX(array $expressions, string $expectedResult): void
{
- $this->assertEquals(
+ self::assertSame(
$expectedResult,
- $this->closureExpressionBuilder->xorX($expressions)
+ $this->htmlExpressionBuilder->xorX($expressions)
);
}
+
+ public static function provideXorXCases(): iterable
+ {
+ yield [['false', 'false'], ''];
+
+ yield [['false', 'true'], ''];
+
+ yield [['true', 'false'], ''];
+
+ yield [['true', 'true'], ''];
+
+ yield [['false', 'false', 'false'], ''];
+
+ yield [['false', 'false', 'true'], ''];
+
+ yield [['false', 'true', 'false'], ''];
+
+ yield [['false', 'true', 'true'], ''];
+
+ yield [['true', 'false', 'false'], ''];
+
+ yield [['true', 'false', 'true'], ''];
+
+ yield [['true', 'true', 'false'], ''];
+
+ yield [['true', 'true', 'true'], ''];
+ }
}
diff --git a/tests/Expr/MapperExpressionBuilderTest.php b/tests/Expr/MapperExpressionBuilderTest.php
index a290a1d..85ca977 100644
--- a/tests/Expr/MapperExpressionBuilderTest.php
+++ b/tests/Expr/MapperExpressionBuilderTest.php
@@ -1,347 +1,315 @@
expressionBuilderMock = $this->prophesize(ExpressionBuilderInterface::class);
+ private Prophet $prophet;
+ protected function setUp(): void
+ {
+ $this->prophet = new Prophet();
+ $this->expressionBuilderMock = $this->prophet->prophesize(ExpressionBuilderInterface::class);
$this->mapperExpressionBuilder = new MapperExpressionBuilder($this->expressionBuilderMock->reveal());
}
- public function testGetSupportedTokenType()
+ protected function tearDown(): void
{
+ $this->prophet->checkPredictions();
+ }
+
+ public function testGetSupportedTokenType(): void
+ {
+ $this->expectNotToPerformAssertions();
$this->expressionBuilderMock->getSupportedTokenType()->shouldBeCalled();
$this->mapperExpressionBuilder->getSupportedTokenType();
}
- public function testParameter()
+ public function testParameter(): void
{
$this->expressionBuilderMock->parameter('fake_field', false)->willReturn('fake_return')->shouldBeCalled();
- $this->assertEquals(
+ self::assertSame(
'fake_return',
$this->mapperExpressionBuilder->parameter('fake_field')
);
}
- public function testParameterAsValue()
+ public function testParameterAsValue(): void
{
$this->expressionBuilderMock->parameter('fake_field', true)->willReturn('fake_return')->shouldBeCalled();
- $this->assertEquals(
+ self::assertSame(
'fake_return',
$this->mapperExpressionBuilder->parameter('fake_field', true)
);
}
- public function testString()
+ public function testString(): void
{
$this->expressionBuilderMock->string('fake_field')->willReturn('fake_return')->shouldBeCalled();
- $this->assertEquals(
+ self::assertSame(
'fake_return',
$this->mapperExpressionBuilder->string('fake_field')
);
}
/**
- * @dataProvider fieldMappingProvider
- *
- * @param $fieldMapping
- * @param $field
- * @param $expectedMappedField
+ * @dataProvider fieldMappingDataProvider
*/
- public function testIsNull($fieldMapping, $field, $expectedMappedField)
+ public function testIsNull(array $fieldMapping, mixed $field, mixed $expectedMappedField): void
{
$mapperExpressionBuilder = new MapperExpressionBuilder($this->expressionBuilderMock->reveal(), $fieldMapping);
$this->expressionBuilderMock->isNull($expectedMappedField)->willReturn('fake_return')->shouldBeCalled();
- $this->assertEquals(
+ self::assertSame(
'fake_return',
$mapperExpressionBuilder->isNull($field)
);
}
/**
- * @dataProvider fieldMappingProvider
- *
- * @param $fieldMapping
- * @param $field
- * @param $expectedMappedField
+ * @dataProvider fieldMappingDataProvider
*/
- public function testEq($fieldMapping, $field, $expectedMappedField)
+ public function testEq(array $fieldMapping, mixed $field, mixed $expectedMappedField): void
{
$mapperExpressionBuilder = new MapperExpressionBuilder($this->expressionBuilderMock->reveal(), $fieldMapping);
$this->expressionBuilderMock->eq($expectedMappedField, 'fake_value')->willReturn('fake_return')->shouldBeCalled();
- $this->assertEquals(
+ self::assertSame(
'fake_return',
$mapperExpressionBuilder->eq($field, 'fake_value')
);
}
/**
- * @dataProvider fieldMappingProvider
- *
- * @param $fieldMapping
- * @param $field
- * @param $expectedMappedField
+ * @dataProvider fieldMappingDataProvider
*/
- public function testNeq($fieldMapping, $field, $expectedMappedField)
+ public function testNeq(array $fieldMapping, mixed $field, mixed $expectedMappedField): void
{
$mapperExpressionBuilder = new MapperExpressionBuilder($this->expressionBuilderMock->reveal(), $fieldMapping);
$this->expressionBuilderMock->neq($expectedMappedField, 'fake_value')->willReturn('fake_return')->shouldBeCalled();
- $this->assertEquals(
+ self::assertSame(
'fake_return',
$mapperExpressionBuilder->neq($field, 'fake_value')
);
}
/**
- * @dataProvider fieldMappingProvider
- *
- * @param $fieldMapping
- * @param $field
- * @param $expectedMappedField
+ * @dataProvider fieldMappingDataProvider
*/
- public function testGt($fieldMapping, $field, $expectedMappedField)
+ public function testGt(array $fieldMapping, mixed $field, mixed $expectedMappedField): void
{
$mapperExpressionBuilder = new MapperExpressionBuilder($this->expressionBuilderMock->reveal(), $fieldMapping);
$this->expressionBuilderMock->gt($expectedMappedField, 'fake_value')->willReturn('fake_return')->shouldBeCalled();
- $this->assertEquals(
+ self::assertSame(
'fake_return',
$mapperExpressionBuilder->gt($field, 'fake_value')
);
}
/**
- * @dataProvider fieldMappingProvider
- *
- * @param $fieldMapping
- * @param $field
- * @param $expectedMappedField
+ * @dataProvider fieldMappingDataProvider
*/
- public function testGte($fieldMapping, $field, $expectedMappedField)
+ public function testGte(array $fieldMapping, mixed $field, mixed $expectedMappedField): void
{
$mapperExpressionBuilder = new MapperExpressionBuilder($this->expressionBuilderMock->reveal(), $fieldMapping);
$this->expressionBuilderMock->gte($expectedMappedField, 'fake_value')->willReturn('fake_return')->shouldBeCalled();
- $this->assertEquals(
+ self::assertSame(
'fake_return',
$mapperExpressionBuilder->gte($field, 'fake_value')
);
}
/**
- * @dataProvider fieldMappingProvider
- *
- * @param $fieldMapping
- * @param $field
- * @param $expectedMappedField
+ * @dataProvider fieldMappingDataProvider
*/
- public function testLt($fieldMapping, $field, $expectedMappedField)
+ public function testLt(array $fieldMapping, mixed $field, mixed $expectedMappedField): void
{
$mapperExpressionBuilder = new MapperExpressionBuilder($this->expressionBuilderMock->reveal(), $fieldMapping);
$this->expressionBuilderMock->lt($expectedMappedField, 'fake_value')->willReturn('fake_return')->shouldBeCalled();
- $this->assertEquals(
+ self::assertSame(
'fake_return',
$mapperExpressionBuilder->lt($field, 'fake_value')
);
}
/**
- * @dataProvider fieldMappingProvider
- *
- * @param $fieldMapping
- * @param $field
- * @param $expectedMappedField
+ * @dataProvider fieldMappingDataProvider
*/
- public function testLte($fieldMapping, $field, $expectedMappedField)
+ public function testLte(array $fieldMapping, mixed $field, mixed $expectedMappedField): void
{
$mapperExpressionBuilder = new MapperExpressionBuilder($this->expressionBuilderMock->reveal(), $fieldMapping);
$this->expressionBuilderMock->lte($expectedMappedField, 'fake_value')->willReturn('fake_return')->shouldBeCalled();
- $this->assertEquals(
+ self::assertSame(
'fake_return',
$mapperExpressionBuilder->lte($field, 'fake_value')
);
}
/**
- * @dataProvider fieldMappingProvider
- *
- * @param $fieldMapping
- * @param $field
- * @param $expectedMappedField
+ * @dataProvider fieldMappingDataProvider
*/
- public function testIn($fieldMapping, $field, $expectedMappedField)
+ public function testIn(array $fieldMapping, mixed $field, mixed $expectedMappedField): void
{
$mapperExpressionBuilder = new MapperExpressionBuilder($this->expressionBuilderMock->reveal(), $fieldMapping);
$this->expressionBuilderMock->in($expectedMappedField, ['fake_value'])->willReturn('fake_return')->shouldBeCalled();
- $this->assertEquals(
+ self::assertSame(
'fake_return',
$mapperExpressionBuilder->in($field, ['fake_value'])
);
}
/**
- * @dataProvider fieldMappingProvider
- *
- * @param $fieldMapping
- * @param $field
- * @param $expectedMappedField
+ * @dataProvider fieldMappingDataProvider
*/
- public function testNotIn($fieldMapping, $field, $expectedMappedField)
+ public function testNotIn(array $fieldMapping, mixed $field, mixed $expectedMappedField): void
{
$mapperExpressionBuilder = new MapperExpressionBuilder($this->expressionBuilderMock->reveal(), $fieldMapping);
$this->expressionBuilderMock->notIn($expectedMappedField, ['fake_value'])->willReturn('fake_return')->shouldBeCalled();
- $this->assertEquals(
+ self::assertSame(
'fake_return',
$mapperExpressionBuilder->notIn($field, ['fake_value'])
);
}
/**
- * @dataProvider fieldMappingProvider
- *
- * @param $fieldMapping
- * @param $field
- * @param $expectedMappedField
+ * @dataProvider fieldMappingDataProvider
*/
- public function testContains($fieldMapping, $field, $expectedMappedField)
+ public function testContains(array $fieldMapping, mixed $field, mixed $expectedMappedField): void
{
$mapperExpressionBuilder = new MapperExpressionBuilder($this->expressionBuilderMock->reveal(), $fieldMapping);
$this->expressionBuilderMock->contains($expectedMappedField, 'fake_value')->willReturn('fake_return')->shouldBeCalled();
- $this->assertEquals(
+ self::assertSame(
'fake_return',
$mapperExpressionBuilder->contains($field, 'fake_value')
);
}
/**
- * @dataProvider fieldMappingProvider
- *
- * @param $fieldMapping
- * @param $field
- * @param $expectedMappedField
+ * @dataProvider fieldMappingDataProvider
*/
- public function testNotContains($fieldMapping, $field, $expectedMappedField)
+ public function testNotContains(array $fieldMapping, mixed $field, mixed $expectedMappedField): void
{
$mapperExpressionBuilder = new MapperExpressionBuilder($this->expressionBuilderMock->reveal(), $fieldMapping);
$this->expressionBuilderMock->notContains($expectedMappedField, 'fake_value')->willReturn('fake_return')->shouldBeCalled();
- $this->assertEquals(
+ self::assertSame(
'fake_return',
$mapperExpressionBuilder->notContains($field, 'fake_value')
);
}
- public function fieldMappingProvider()
+ public static function fieldMappingDataProvider(): iterable
{
- return array(
- array(
- array(),
- 'fake_field',
- 'fake_field',
- ),
- array(
- array('*' => 'fake_%s_mapping'),
- 'fake_field',
- 'fake_fake_field_mapping',
- ),
- array(
- array('other' => 'fake_%s_mapping'),
- 'fake_field',
- 'fake_field',
- ),
- array(
- array('fake_field' => 'fake_%s_mapping'),
- 'fake_field',
- 'fake_fake_field_mapping',
- ),
- );
+ yield [
+ [],
+ 'fake_field',
+ 'fake_field',
+ ];
+
+ yield [
+ ['*' => 'fake_%s_mapping'],
+ 'fake_field',
+ 'fake_fake_field_mapping',
+ ];
+
+ yield [
+ ['other' => 'fake_%s_mapping'],
+ 'fake_field',
+ 'fake_field',
+ ];
+
+ yield [
+ ['fake_field' => 'fake_%s_mapping'],
+ 'fake_field',
+ 'fake_fake_field_mapping',
+ ];
}
- public function testAndX()
+ public function testAndX(): void
{
$this->expressionBuilderMock->andX(['fake_expression'])->willReturn('fake_return')->shouldBeCalled();
- $this->assertEquals(
+ self::assertSame(
'fake_return',
$this->mapperExpressionBuilder->andX(['fake_expression'])
);
}
- public function testNandX()
+ public function testNandX(): void
{
$this->expressionBuilderMock->nandX(['fake_expression'])->willReturn('fake_return')->shouldBeCalled();
- $this->assertEquals(
+ self::assertSame(
'fake_return',
$this->mapperExpressionBuilder->nandX(['fake_expression'])
);
}
- public function testOrX()
+ public function testOrX(): void
{
$this->expressionBuilderMock->orX(['fake_expression'])->willReturn('fake_return')->shouldBeCalled();
- $this->assertEquals(
+ self::assertSame(
'fake_return',
$this->mapperExpressionBuilder->orX(['fake_expression'])
);
}
- public function testNorX()
+ public function testNorX(): void
{
$this->expressionBuilderMock->norX(['fake_expression'])->willReturn('fake_return')->shouldBeCalled();
- $this->assertEquals(
+ self::assertSame(
'fake_return',
$this->mapperExpressionBuilder->norX(['fake_expression'])
);
}
- public function testXorX()
+ public function testXorX(): void
{
$this->expressionBuilderMock->xorX(['fake_expression'])->willReturn('fake_return')->shouldBeCalled();
- $this->assertEquals(
+ self::assertSame(
'fake_return',
$this->mapperExpressionBuilder->xorX(['fake_expression'])
);
diff --git a/tests/LexerTest.php b/tests/LexerTest.php
index d9ebac3..f8f8413 100644
--- a/tests/LexerTest.php
+++ b/tests/LexerTest.php
@@ -1,241 +1,343 @@
lexer = new Lexer();
}
- public function setInputSuccessDataProvider()
- {
- return array(
- array(
- 'a=1',
- array(
- array('value' => 'a', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 0),
- array('value' => '=', 'type' => Lexer::T_EQUALS, 'position' => 1),
- array('value' => '1', 'type' => Lexer::T_INTEGER, 'position' => 2),
- ),
- ),
- array(
- 'a.b=1',
- array(
- array('value' => 'a.b', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 0),
- array('value' => '=', 'type' => Lexer::T_EQUALS, 'position' => 3),
- array('value' => '1', 'type' => Lexer::T_INTEGER, 'position' => 4),
- ),
- ),
- array(
- 'a-b=1',
- array(
- array('value' => 'a-b', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 0),
- array('value' => '=', 'type' => Lexer::T_EQUALS, 'position' => 3),
- array('value' => '1', 'type' => Lexer::T_INTEGER, 'position' => 4),
- ),
- ),
- array(
- 'a≠1',
- array(
- array('value' => 'a', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 0),
- array('value' => '≠', 'type' => Lexer::T_NOT_EQUALS, 'position' => 1),
- array('value' => '1', 'type' => Lexer::T_INTEGER, 'position' => 4),
- ),
- ),
- array(
- 'a!=1',
- array(
- array('value' => 'a', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 0),
- array('value' => '≠', 'type' => Lexer::T_NOT_EQUALS, 'position' => 1),
- array('value' => '1', 'type' => Lexer::T_INTEGER, 'position' => 3),
- ),
- ),
- array(
- 'a="value"',
- array(
- array('value' => 'a', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 0),
- array('value' => '=', 'type' => Lexer::T_EQUALS, 'position' => 1),
- array('value' => 'value', 'type' => Lexer::T_STRING, 'position' => 2),
- ),
- ),
- array(
- "a='value'",
- array(
- array('value' => 'a', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 0),
- array('value' => '=', 'type' => Lexer::T_EQUALS, 'position' => 1),
- array('value' => 'value', 'type' => Lexer::T_STRING, 'position' => 2),
- ),
- ),
- array(
- 'a>1',
- array(
- array('value' => 'a', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 0),
- array('value' => '>', 'type' => Lexer::T_GREATER_THAN, 'position' => 1),
- array('value' => '1', 'type' => Lexer::T_INTEGER, 'position' => 2),
- ),
- ),
- array(
- 'a>=1',
- array(
- array('value' => 'a', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 0),
- array('value' => '≥', 'type' => Lexer::T_GREATER_THAN_EQUALS, 'position' => 1),
- array('value' => '1', 'type' => Lexer::T_INTEGER, 'position' => 3),
- ),
- ),
- array(
- 'a≥1',
- array(
- array('value' => 'a', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 0),
- array('value' => '≥', 'type' => Lexer::T_GREATER_THAN_EQUALS, 'position' => 1),
- array('value' => '1', 'type' => Lexer::T_INTEGER, 'position' => 4),
- ),
- ),
- array(
- 'a<1',
- array(
- array('value' => 'a', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 0),
- array('value' => '<', 'type' => Lexer::T_LOWER_THAN, 'position' => 1),
- array('value' => '1', 'type' => Lexer::T_INTEGER, 'position' => 2),
- ),
- ),
- array(
- 'a<=1',
- array(
- array('value' => 'a', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 0),
- array('value' => '≤', 'type' => Lexer::T_LOWER_THAN_EQUALS, 'position' => 1),
- array('value' => '1', 'type' => Lexer::T_INTEGER, 'position' => 3),
- ),
- ),
- array(
- 'a≤1',
- array(
- array('value' => 'a', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 0),
- array('value' => '≤', 'type' => Lexer::T_LOWER_THAN_EQUALS, 'position' => 1),
- array('value' => '1', 'type' => Lexer::T_INTEGER, 'position' => 4),
- ),
- ),
- array(
- 'a|1',
- array(
- array('value' => 'a', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 0),
- array('value' => '|', 'type' => Lexer::T_OR, 'position' => 1),
- array('value' => '1', 'type' => Lexer::T_INTEGER, 'position' => 2),
- ),
- ),
- array(
- 'a!|1',
- array(
- array('value' => 'a', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 0),
- array('value' => '!|', 'type' => Lexer::T_NOT_OR, 'position' => 1),
- array('value' => '1', 'type' => Lexer::T_INTEGER, 'position' => 3),
- ),
- ),
- array(
- 'a[1,2]',
- array(
- array('value' => 'a', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 0),
- array('value' => '[', 'type' => Lexer::T_OPEN_SQUARE_BRACKET, 'position' => 1),
- array('value' => '1', 'type' => Lexer::T_INTEGER, 'position' => 2),
- array('value' => ',', 'type' => Lexer::T_COMMA, 'position' => 3),
- array('value' => '2', 'type' => Lexer::T_INTEGER, 'position' => 4),
- array('value' => ']', 'type' => Lexer::T_CLOSE_SQUARE_BRACKET, 'position' => 5),
- ),
- ),
- array(
- 'a![1,2]',
- array(
- array('value' => 'a', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 0),
- array('value' => '![', 'type' => Lexer::T_NOT_OPEN_SQUARE_BRACKET, 'position' => 1),
- array('value' => '1', 'type' => Lexer::T_INTEGER, 'position' => 3),
- array('value' => ',', 'type' => Lexer::T_COMMA, 'position' => 4),
- array('value' => '2', 'type' => Lexer::T_INTEGER, 'position' => 5),
- array('value' => ']', 'type' => Lexer::T_CLOSE_SQUARE_BRACKET, 'position' => 6),
- ),
- ),
- array(
- 'a{{1}}',
- array(
- array('value' => 'a', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 0),
- array('value' => '{{', 'type' => Lexer::T_DOUBLE_OPEN_CURLY_BRACKET, 'position' => 1),
- array('value' => '1', 'type' => Lexer::T_INTEGER, 'position' => 3),
- array('value' => '}}', 'type' => Lexer::T_DOUBLE_CLOSE_CURLY_BRACKET, 'position' => 4),
- ),
- ),
- array(
- 'a!{{1}}',
- array(
- array('value' => 'a', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 0),
- array('value' => '!{{', 'type' => Lexer::T_NOT_DOUBLE_OPEN_CURLY_BRACKET, 'position' => 1),
- array('value' => '1', 'type' => Lexer::T_INTEGER, 'position' => 4),
- array('value' => '}}', 'type' => Lexer::T_DOUBLE_CLOSE_CURLY_BRACKET, 'position' => 5),
- ),
- ),
- );
- }
-
/**
- * @dataProvider setInputSuccessDataProvider
- *
- * @param $input
- * @param $expectedTokens
+ * @dataProvider provideSetInputSuccessCases
*/
- public function testSetInputSuccess($input, $expectedTokens)
+ public function testSetInputSuccess(string $input, array $expectedTokens): void
{
$this->lexer->setInput($input);
$this->lexer->moveNext();
$this->lexer->moveNext();
$i = 0;
while ($currentToken = $this->lexer->token) {
- $this->assertEquals($expectedTokens[$i], $currentToken);
+ self::assertSame($expectedTokens[$i], $currentToken);
$this->lexer->moveNext();
- $i++;
+ ++$i;
}
}
- public function unexpectedValueExceptionProvider()
+ public static function provideSetInputSuccessCases(): iterable
{
- return array(
- array(
- '!',
- ),
- array(
- '§',
- ),
- array(
- '^',
- ),
- array(
- ';',
- ),
- array(
- ':',
- ),
- array(
- '/',
- ),
- );
+ yield [
+ 'a=1',
+ [
+ ['value' => 'a', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 0],
+ ['value' => '=', 'type' => Lexer::T_EQUALS, 'position' => 1],
+ ['value' => 1, 'type' => Lexer::T_INTEGER, 'position' => 2],
+ ],
+ ];
+
+ yield [
+ 'a=1.5',
+ [
+ ['value' => 'a', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 0],
+ ['value' => '=', 'type' => Lexer::T_EQUALS, 'position' => 1],
+ ['value' => 1.5, 'type' => Lexer::T_FLOAT, 'position' => 2],
+ ],
+ ];
+
+ yield [
+ 'a.b=1',
+ [
+ ['value' => 'a.b', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 0],
+ ['value' => '=', 'type' => Lexer::T_EQUALS, 'position' => 3],
+ ['value' => 1, 'type' => Lexer::T_INTEGER, 'position' => 4],
+ ],
+ ];
+
+ yield [
+ 'a-b=1',
+ [
+ ['value' => 'a-b', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 0],
+ ['value' => '=', 'type' => Lexer::T_EQUALS, 'position' => 3],
+ ['value' => 1, 'type' => Lexer::T_INTEGER, 'position' => 4],
+ ],
+ ];
+
+ yield [
+ 'a≠1',
+ [
+ ['value' => 'a', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 0],
+ ['value' => '≠', 'type' => Lexer::T_NOT_EQUALS, 'position' => 1],
+ ['value' => 1, 'type' => Lexer::T_INTEGER, 'position' => 4],
+ ],
+ ];
+
+ yield [
+ 'a!=1',
+ [
+ ['value' => 'a', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 0],
+ ['value' => '≠', 'type' => Lexer::T_NOT_EQUALS, 'position' => 1],
+ ['value' => 1, 'type' => Lexer::T_INTEGER, 'position' => 3],
+ ],
+ ];
+
+ yield [
+ 'a="value"',
+ [
+ ['value' => 'a', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 0],
+ ['value' => '=', 'type' => Lexer::T_EQUALS, 'position' => 1],
+ ['value' => 'value', 'type' => Lexer::T_STRING, 'position' => 2],
+ ],
+ ];
+
+ yield [
+ "a='value'",
+ [
+ ['value' => 'a', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 0],
+ ['value' => '=', 'type' => Lexer::T_EQUALS, 'position' => 1],
+ ['value' => 'value', 'type' => Lexer::T_STRING, 'position' => 2],
+ ],
+ ];
+
+ yield [
+ 'a>1',
+ [
+ ['value' => 'a', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 0],
+ ['value' => '>', 'type' => Lexer::T_GREATER_THAN, 'position' => 1],
+ ['value' => 1, 'type' => Lexer::T_INTEGER, 'position' => 2],
+ ],
+ ];
+
+ yield [
+ 'a>=1',
+ [
+ ['value' => 'a', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 0],
+ ['value' => '≥', 'type' => Lexer::T_GREATER_THAN_EQUALS, 'position' => 1],
+ ['value' => 1, 'type' => Lexer::T_INTEGER, 'position' => 3],
+ ],
+ ];
+
+ yield [
+ 'a≥1',
+ [
+ ['value' => 'a', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 0],
+ ['value' => '≥', 'type' => Lexer::T_GREATER_THAN_EQUALS, 'position' => 1],
+ ['value' => 1, 'type' => Lexer::T_INTEGER, 'position' => 4],
+ ],
+ ];
+
+ yield [
+ 'a<1',
+ [
+ ['value' => 'a', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 0],
+ ['value' => '<', 'type' => Lexer::T_LOWER_THAN, 'position' => 1],
+ ['value' => 1, 'type' => Lexer::T_INTEGER, 'position' => 2],
+ ],
+ ];
+
+ yield [
+ 'a<=1',
+ [
+ ['value' => 'a', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 0],
+ ['value' => '≤', 'type' => Lexer::T_LOWER_THAN_EQUALS, 'position' => 1],
+ ['value' => 1, 'type' => Lexer::T_INTEGER, 'position' => 3],
+ ],
+ ];
+
+ yield [
+ 'a≤1',
+ [
+ ['value' => 'a', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 0],
+ ['value' => '≤', 'type' => Lexer::T_LOWER_THAN_EQUALS, 'position' => 1],
+ ['value' => 1, 'type' => Lexer::T_INTEGER, 'position' => 4],
+ ],
+ ];
+
+ yield [
+ 'a|1',
+ [
+ ['value' => 'a', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 0],
+ ['value' => '|', 'type' => Lexer::T_OR, 'position' => 1],
+ ['value' => 1, 'type' => Lexer::T_INTEGER, 'position' => 2],
+ ],
+ ];
+
+ yield [
+ 'a!|1',
+ [
+ ['value' => 'a', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 0],
+ ['value' => '!|', 'type' => Lexer::T_NOT_OR, 'position' => 1],
+ ['value' => 1, 'type' => Lexer::T_INTEGER, 'position' => 3],
+ ],
+ ];
+
+ yield [
+ 'a[1,2]',
+ [
+ ['value' => 'a', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 0],
+ ['value' => '[', 'type' => Lexer::T_OPEN_SQUARE_BRACKET, 'position' => 1],
+ ['value' => 1, 'type' => Lexer::T_INTEGER, 'position' => 2],
+ ['value' => ',', 'type' => Lexer::T_COMMA, 'position' => 3],
+ ['value' => 2, 'type' => Lexer::T_INTEGER, 'position' => 4],
+ ['value' => ']', 'type' => Lexer::T_CLOSE_SQUARE_BRACKET, 'position' => 5],
+ ],
+ ];
+
+ yield [
+ 'a![1,2]',
+ [
+ ['value' => 'a', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 0],
+ ['value' => '![', 'type' => Lexer::T_NOT_OPEN_SQUARE_BRACKET, 'position' => 1],
+ ['value' => 1, 'type' => Lexer::T_INTEGER, 'position' => 3],
+ ['value' => ',', 'type' => Lexer::T_COMMA, 'position' => 4],
+ ['value' => 2, 'type' => Lexer::T_INTEGER, 'position' => 5],
+ ['value' => ']', 'type' => Lexer::T_CLOSE_SQUARE_BRACKET, 'position' => 6],
+ ],
+ ];
+
+ yield [
+ 'a{{1}}',
+ [
+ ['value' => 'a', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 0],
+ ['value' => '{{', 'type' => Lexer::T_DOUBLE_OPEN_CURLY_BRACKET, 'position' => 1],
+ ['value' => 1, 'type' => Lexer::T_INTEGER, 'position' => 3],
+ ['value' => '}}', 'type' => Lexer::T_DOUBLE_CLOSE_CURLY_BRACKET, 'position' => 4],
+ ],
+ ];
+
+ yield [
+ 'a!{{1}}',
+ [
+ ['value' => 'a', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 0],
+ ['value' => '!{{', 'type' => Lexer::T_NOT_DOUBLE_OPEN_CURLY_BRACKET, 'position' => 1],
+ ['value' => 1, 'type' => Lexer::T_INTEGER, 'position' => 4],
+ ['value' => '}}', 'type' => Lexer::T_DOUBLE_CLOSE_CURLY_BRACKET, 'position' => 5],
+ ],
+ ];
+
+ yield [
+ '(a=1)',
+ [
+ ['value' => '(', 'type' => Lexer::T_OPEN_PARENTHESIS, 'position' => 0],
+ ['value' => 'a', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 1],
+ ['value' => '=', 'type' => Lexer::T_EQUALS, 'position' => 2],
+ ['value' => 1, 'type' => Lexer::T_INTEGER, 'position' => 3],
+ ['value' => ')', 'type' => Lexer::T_CLOSE_PARENTHESIS, 'position' => 4],
+ ],
+ ];
+
+ yield [
+ '(a=1)',
+ [
+ ['value' => '(', 'type' => Lexer::T_OPEN_PARENTHESIS, 'position' => 0],
+ ['value' => 'a', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 1],
+ ['value' => '=', 'type' => Lexer::T_EQUALS, 'position' => 2],
+ ['value' => 1, 'type' => Lexer::T_INTEGER, 'position' => 3],
+ ['value' => ')', 'type' => Lexer::T_CLOSE_PARENTHESIS, 'position' => 4],
+ ],
+ ];
+
+ yield [
+ 'a=1&b=2',
+ [
+ ['value' => 'a', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 0],
+ ['value' => '=', 'type' => Lexer::T_EQUALS, 'position' => 1],
+ ['value' => 1, 'type' => Lexer::T_INTEGER, 'position' => 2],
+ ['value' => '&', 'type' => Lexer::T_AND, 'position' => 3],
+ ['value' => 'b', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 4],
+ ['value' => '=', 'type' => Lexer::T_EQUALS, 'position' => 5],
+ ['value' => 2, 'type' => Lexer::T_INTEGER, 'position' => 6],
+ ],
+ ];
+
+ yield [
+ 'a=1!&b=2',
+ [
+ ['value' => 'a', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 0],
+ ['value' => '=', 'type' => Lexer::T_EQUALS, 'position' => 1],
+ ['value' => 1, 'type' => Lexer::T_INTEGER, 'position' => 2],
+ ['value' => '!&', 'type' => Lexer::T_NOT_AND, 'position' => 3],
+ ['value' => 'b', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 5],
+ ['value' => '=', 'type' => Lexer::T_EQUALS, 'position' => 6],
+ ['value' => 2, 'type' => Lexer::T_INTEGER, 'position' => 7],
+ ],
+ ];
+
+ yield [
+ 'a=1⊕b=2',
+ [
+ ['value' => 'a', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 0],
+ ['value' => '=', 'type' => Lexer::T_EQUALS, 'position' => 1],
+ ['value' => 1, 'type' => Lexer::T_INTEGER, 'position' => 2],
+ ['value' => '⊕', 'type' => Lexer::T_XOR, 'position' => 3],
+ ['value' => 'b', 'type' => Lexer::T_INPUT_PARAMETER, 'position' => 6],
+ ['value' => '=', 'type' => Lexer::T_EQUALS, 'position' => 7],
+ ['value' => 2, 'type' => Lexer::T_INTEGER, 'position' => 8],
+ ],
+ ];
}
/**
- * @dataProvider unexpectedValueExceptionProvider
- *
- * @expectedException \Symftony\Xpression\Exception\Lexer\UnknownTokenTypeException
- * @expectedExceptionMessageRegExp /Unknown token type ".+"\./
- *
- * @param $input
+ * @dataProvider provideUnexpectedValueExceptionCases
*/
- public function testUnexpectedValueException($input)
+ public function testUnexpectedValueException(string $input): void
{
+ $this->expectException(UnknownTokenTypeException::class);
+ $this->expectExceptionMessageMatches('/Unknown token type ".+"\./');
$this->lexer->setInput($input);
}
+
+ public static function provideUnexpectedValueExceptionCases(): iterable
+ {
+ yield ['!'];
+
+ yield ['§'];
+
+ yield ['^'];
+
+ yield [';'];
+
+ yield [':'];
+
+ yield ['/'];
+ }
+
+ /**
+ * @dataProvider getTokenSyntaxDataProvider
+ */
+ public function testGetTokenSyntax(mixed $tokenType, array $expectedTokenSyntax): void
+ {
+ $this->assertSame($expectedTokenSyntax, Lexer::getTokenSyntax($tokenType));
+ }
+
+ public static function getTokenSyntaxDataProvider(): iterable
+ {
+ yield [
+ Lexer::T_NONE,
+ [],
+ ];
+
+ yield [
+ Lexer::T_ALL,
+ [',', 'simple float', 'simple integer', '/[a-z_][a-z0-9_]*/', '"value" or \'value\'', '=', '≠ or !=', '>', '≥ or >=', '<', '≤ or <=', '&', '!&', '|', '!|', '⊕ or ^|', '(', ')', '[', '![', ']', '{{', '!{{', '}}'],
+ ];
+
+ yield [
+ Lexer::T_OPERAND,
+ ['simple float', 'simple integer', '/[a-z_][a-z0-9_]*/', '"value" or \'value\''],
+ ];
+ }
}
diff --git a/tests/ParserTest.php b/tests/ParserTest.php
index 363e74f..3f81bfa 100644
--- a/tests/ParserTest.php
+++ b/tests/ParserTest.php
@@ -1,440 +1,459 @@
expressionBuilderMock = $this->prophesize('Symftony\Xpression\Expr\ExpressionBuilderInterface');
+ $this->expressionBuilderMock = (new Prophet())->prophesize(ExpressionBuilderInterface::class);
$this->expressionBuilderMock->getSupportedTokenType()->willReturn(Lexer::T_ALL);
$this->parser = new Parser($this->expressionBuilderMock->reveal());
}
- public function parseSuccessDataProvider()
- {
- return array(
- array(
- 'fieldA=1',
- array(array('eq', 'fieldA', 1, 'my_fake_comparison_A')),
- array(),
- 'my_fake_comparison_A',
- ),
- array(
- 'fieldA="string"',
- array(array('eq', 'fieldA', 'my_fake_string', 'my_fake_comparison_A')),
- array(array('valueAsString', 'string', 'my_fake_string')),
- 'my_fake_comparison_A',
- ),
- array(
- 'fieldA>1',
- array(array('gt', 'fieldA', 1, 'my_fake_comparison_A')),
- array(),
- 'my_fake_comparison_A',
- ),
- array(
- 'fieldA≥1',
- array(
- array('gte', 'fieldA', 1, 'my_fake_comparison_A')
- ),
- array(),
- 'my_fake_comparison_A',
- ),
- array(
- 'fieldA>=1',
- array(
- array('gte', 'fieldA', 1, 'my_fake_comparison_A')
- ),
- array(),
- 'my_fake_comparison_A',
- ),
- array(
- 'fieldA<1',
- array(
- array('lt', 'fieldA', 1, 'my_fake_comparison_A')
- ),
- array(),
- 'my_fake_comparison_A',
- ),
- array(
- 'fieldA≤1',
- array(
- array('lte', 'fieldA', 1, 'my_fake_comparison_A')
- ),
- array(),
- 'my_fake_comparison_A',
- ),
- array(
- 'fieldA<=1',
- array(
- array('lte', 'fieldA', 1, 'my_fake_comparison_A')
- ),
- array(),
- 'my_fake_comparison_A',
- ),
- array(
- 'fieldA≠1',
- array(
- array('neq', 'fieldA', 1, 'my_fake_comparison_A')
- ),
- array(),
- 'my_fake_comparison_A',
- ),
- array(
- 'fieldA!=1',
- array(
- array('neq', 'fieldA', 1, 'my_fake_comparison_A')
- ),
- array(),
- 'my_fake_comparison_A',
- ),
- array(
- 'fieldA[1,2]',
- array(
- array('in', 'fieldA', array(1, 2), 'my_fake_comparison_A')
- ),
- array(),
- 'my_fake_comparison_A',
- ),
- array(
- 'fieldA![1,2]',
- array(
- array('notIn', 'fieldA', array(1, 2), 'my_fake_comparison_A')
- ),
- array(),
- 'my_fake_comparison_A'
- ),
- array(
- 'fieldA{{1}}',
- array(
- array('contains', 'fieldA', 1, 'my_fake_comparison_A')
- ),
- array(),
- 'my_fake_comparison_A',
- ),
- array(
- 'fieldA!{{1}}',
- array(
- array('notContains', 'fieldA', 1, 'my_fake_comparison_A')
- ),
- array(),
- 'my_fake_comparison_A'
- ),
-
- // Composite
- array(
- 'fieldA=1|fieldB=2|fieldC=3',
- array(
- array('eq', 'fieldA', 1, 'my_fake_comparison_A'),
- array('eq', 'fieldB', 2, 'my_fake_comparison_B'),
- array('eq', 'fieldC', 3, 'my_fake_comparison_C'),
- ),
- array(
- array('orX', array('my_fake_comparison_A', 'my_fake_comparison_B', 'my_fake_comparison_C'), 'my_fake_orX_composite'),
- ),
- 'my_fake_orX_composite'
- ),
- array(
- 'fieldA=1!|fieldB=2!|fieldC=3',
- array(
- array('eq', 'fieldA', 1, 'my_fake_comparison_A'),
- array('eq', 'fieldB', 2, 'my_fake_comparison_B'),
- array('eq', 'fieldC', 3, 'my_fake_comparison_C'),
- ),
- array(
- array('norX', array('my_fake_comparison_A', 'my_fake_comparison_B', 'my_fake_comparison_C'), 'my_fake_norX_composite'),
- ),
- 'my_fake_norX_composite'
- ),
- array(
- 'fieldA=1^|fieldB=2^|fieldC=3',
- array(
- array('eq', 'fieldA', 1, 'my_fake_comparison_A'),
- array('eq', 'fieldB', 2, 'my_fake_comparison_B'),
- array('eq', 'fieldC', 3, 'my_fake_comparison_C'),
- ),
- array(
- array('xorX', array('my_fake_comparison_A', 'my_fake_comparison_B', 'my_fake_comparison_C'), 'my_fake_xorX_composite'),
- ),
- 'my_fake_xorX_composite'
- ),
- array(
- 'fieldA=1⊕fieldB=2⊕fieldC=3',
- array(
- array('eq', 'fieldA', 1, 'my_fake_comparison_A'),
- array('eq', 'fieldB', 2, 'my_fake_comparison_B'),
- array('eq', 'fieldC', 3, 'my_fake_comparison_C'),
- ),
- array(
- array('xorX', array('my_fake_comparison_A', 'my_fake_comparison_B', 'my_fake_comparison_C'), 'my_fake_xorX_composite'),
- ),
- 'my_fake_xorX_composite'
- ),
- array(
- 'fieldA=1&fieldB=2&fieldC=3',
- array(
- array('eq', 'fieldA', 1, 'my_fake_comparison_A'),
- array('eq', 'fieldB', 2, 'my_fake_comparison_B'),
- array('eq', 'fieldC', 3, 'my_fake_comparison_C'),
- ),
- array(
- array('andX', array('my_fake_comparison_A', 'my_fake_comparison_B', 'my_fake_comparison_C'), 'my_fake_andX_composite'),
- ),
- 'my_fake_andX_composite'
- ),
- array(
- 'fieldA{{value}}&fieldB=2',
- array(
- array('contains', 'fieldA', 'value', 'my_fake_comparison_A'),
- array('eq', 'fieldB', 2, 'my_fake_comparison_B'),
- ),
- array(
- array('andX', array('my_fake_comparison_A', 'my_fake_comparison_B'), 'my_fake_andX_composite'),
- ),
- 'my_fake_andX_composite'
- ),
- array(
- 'fieldA=1!&fieldB=2!&fieldC=3',
- array(
- array('eq', 'fieldA', 1, 'my_fake_comparison_A'),
- array('eq', 'fieldB', 2, 'my_fake_comparison_B'),
- array('eq', 'fieldC', 3, 'my_fake_comparison_C'),
- ),
- array(
- array('nandX', array('my_fake_comparison_A', 'my_fake_comparison_B', 'my_fake_comparison_C'), 'my_fake_nandX_composite'),
- ),
- 'my_fake_nandX_composite'
- ),
-
- // Precedences
- array(
- 'fieldA=1|fieldB=2|fieldC=3&fieldD=4',
- array(
- array('eq', 'fieldA', 1, 'my_fake_comparison_A'),
- array('eq', 'fieldB', 2, 'my_fake_comparison_B'),
- array('eq', 'fieldC', 3, 'my_fake_comparison_C'),
- array('eq', 'fieldD', 4, 'my_fake_comparison_D'),
- ),
- array(
- array('andX', array('my_fake_comparison_C', 'my_fake_comparison_D'), 'my_fake_andX_composite'),
- array('orX', array('my_fake_comparison_A', 'my_fake_comparison_B', 'my_fake_andX_composite'), 'my_fake_orX_composite'),
- ),
- 'my_fake_orX_composite'
- ),
- array(
- 'fieldA=1&fieldB=2&fieldC=3!&fieldD=4',
- array(
- array('eq', 'fieldA', 1, 'my_fake_comparison_A'),
- array('eq', 'fieldB', 2, 'my_fake_comparison_B'),
- array('eq', 'fieldC', 3, 'my_fake_comparison_C'),
- array('eq', 'fieldD', 4, 'my_fake_comparison_D'),
- ),
- array(
- array('andX', array('my_fake_comparison_A', 'my_fake_comparison_B', 'my_fake_comparison_C'), 'my_fake_andX_composite'),
- array('nandX', array('my_fake_andX_composite', 'my_fake_comparison_D'), 'my_fake_orX_composite'),
- ),
- 'my_fake_orX_composite'
- ),
- array(
- 'fieldA=1|fieldB=2|fieldC=3!|fieldD=4',
- array(
- array('eq', 'fieldA', 1, 'my_fake_comparison_A'),
- array('eq', 'fieldB', 2, 'my_fake_comparison_B'),
- array('eq', 'fieldC', 3, 'my_fake_comparison_C'),
- array('eq', 'fieldD', 4, 'my_fake_comparison_D'),
- ),
- array(
- array('orX', array('my_fake_comparison_A', 'my_fake_comparison_B', 'my_fake_comparison_C'), 'my_fake_orX_composite'),
- array('norX', array('my_fake_orX_composite', 'my_fake_comparison_D'), 'my_fake_norX_composite'),
- ),
- 'my_fake_norX_composite'
- ),
- array(
- 'fieldA=1&fieldB=2&fieldC=3|fieldD=4',
- array(
- array('eq', 'fieldA', 1, 'my_fake_comparison_A'),
- array('eq', 'fieldB', 2, 'my_fake_comparison_B'),
- array('eq', 'fieldC', 3, 'my_fake_comparison_C'),
- array('eq', 'fieldD', 4, 'my_fake_comparison_D'),
- ),
- array(
- array('andX', array('my_fake_comparison_A', 'my_fake_comparison_B', 'my_fake_comparison_C'), 'my_fake_andX_composite'),
- array('orX', array('my_fake_andX_composite', 'my_fake_comparison_D'), 'my_fake_orX_composite'),
- ),
- 'my_fake_orX_composite'
- ),
- array(
- 'fieldA=1&fieldB=2|fieldC=3&fieldD=4',
- array(
- array('eq', 'fieldA', 1, 'my_fake_comparison_A'),
- array('eq', 'fieldB', 2, 'my_fake_comparison_B'),
- array('eq', 'fieldC', 3, 'my_fake_comparison_C'),
- array('eq', 'fieldD', 4, 'my_fake_comparison_D'),
- ),
- array(
- array('andX', array('my_fake_comparison_A', 'my_fake_comparison_B'), 'my_fake_andX_composite_1'),
- array('andX', array('my_fake_comparison_C', 'my_fake_comparison_D'), 'my_fake_andX_composite_2'),
- array('orX', array('my_fake_andX_composite_1', 'my_fake_andX_composite_2'), 'my_fake_orX_composite'),
- ),
- 'my_fake_orX_composite'
- ),
- array(
- 'fieldA=1|fieldB=2|fieldC=3⊕fieldD=4',
- array(
- array('eq', 'fieldA', 1, 'my_fake_comparison_A'),
- array('eq', 'fieldB', 2, 'my_fake_comparison_B'),
- array('eq', 'fieldC', 3, 'my_fake_comparison_C'),
- array('eq', 'fieldD', 4, 'my_fake_comparison_D'),
- ),
- array(
- array('orX', array('my_fake_comparison_A', 'my_fake_comparison_B', 'my_fake_comparison_C'), 'my_fake_orX_composite'),
- array('xorX', array('my_fake_orX_composite', 'my_fake_comparison_D'), 'my_fake_xorX_composite'),
- ),
- 'my_fake_xorX_composite'
- ),
-
- //Parenthesis
- array(
- '((fieldA=1))',
- array(
- array('eq', 'fieldA', 1, 'my_fake_comparison_A'),
- ),
- array(),
- 'my_fake_comparison_A'
- ),
- array(
- '(fieldA=1|fieldB=2)&fieldC=3',
- array(
- array('eq', 'fieldA', 1, 'my_fake_comparison_A'),
- array('eq', 'fieldB', 2, 'my_fake_comparison_B'),
- array('eq', 'fieldC', 3, 'my_fake_comparison_C'),
- ),
- array(
- array('orX', array('my_fake_comparison_A', 'my_fake_comparison_B'), 'my_fake_orX_composite'),
- array('andX', array('my_fake_orX_composite', 'my_fake_comparison_C'), 'my_fake_andX_composite'),
- ),
- 'my_fake_andX_composite'
- ),
- array(
- 'fieldA=1|(fieldB=2&fieldC=3)',
- array(
- array('eq', 'fieldA', 1, 'my_fake_comparison_A'),
- array('eq', 'fieldB', 2, 'my_fake_comparison_B'),
- array('eq', 'fieldC', 3, 'my_fake_comparison_C'),
- ),
- array(
- array('andX', array('my_fake_comparison_B', 'my_fake_comparison_C'), 'my_fake_andX_composite'),
- array('orX', array('my_fake_comparison_A', 'my_fake_andX_composite'), 'my_fake_orX_composite'),
- ),
- 'my_fake_orX_composite'
- ),
- );
- }
-
/**
- * @dataProvider parseSuccessDataProvider
+ * @dataProvider provideParseSuccessCases
*
- * @param $input
- * @param $comparisonMethods
- * @param $compositeMethods
- * @param $expectedResult
+ * @param mixed $expectedResult
*/
- public function testParseSuccess($input, $comparisonMethods, $compositeMethods, $expectedResult)
+ public function testParseSuccess(string $input, callable $configureExpressionBuilderMock, $expectedResult): void
{
- foreach ($comparisonMethods as $comparisonMethod) {
- $this->expressionBuilderMock
- ->{$comparisonMethod[0]}($comparisonMethod[1], $comparisonMethod[2])
- ->willReturn($comparisonMethod[3])
- ->shouldBeCalled();
- }
-
- foreach ($compositeMethods as $compositeMethod) {
- $this->expressionBuilderMock
- ->{$compositeMethod[0]}($compositeMethod[1])
- ->willReturn($compositeMethod[2])
- ->shouldBeCalled();
- }
+ $configureExpressionBuilderMock($this->expressionBuilderMock);
- $this->assertEquals($expectedResult, $this->parser->parse($input));
+ self::assertSame($expectedResult, $this->parser->parse($input));
}
- public function forbiddenTokenDataProvider()
+ public static function provideParseSuccessCases(): iterable
{
- return array(
- array(','),
- array('9'),
- array('"string"'),
- array("'string'"),
- array('param'),
- array('4.5'),
- array('='),
- array('≠'),
- array('>'),
- array('≥'),
- array('<'),
- array('≤'),
- array('&'),
- array('!&'),
- array('|'),
- array('!|'),
- array('^|'),
- array('⊕'),
- array('('),
- array(')'),
- array('['),
- array('!['),
- array(']'),
- array('{{'),
- array('!{{'),
- array('}}'),
- );
+ $prophet = new Prophet();
+
+ $expr1 = $prophet->prophesize(Expression::class)->reveal();
+ $expr2 = $prophet->prophesize(Expression::class)->reveal();
+ $expr3 = $prophet->prophesize(Expression::class)->reveal();
+ $expr4 = $prophet->prophesize(Expression::class)->reveal();
+ $composite1 = $prophet->prophesize(CompositeExpression::class)->reveal();
+ $composite2 = $prophet->prophesize(CompositeExpression::class)->reveal();
+ $composite3 = $prophet->prophesize(CompositeExpression::class)->reveal();
+
+ yield [
+ 'fieldA=1',
+ static function (ExpressionBuilderInterface|ObjectProphecy $mock) use ($expr1): void {
+ $mock->eq('fieldA', 1)->willReturn($expr1)->shouldBeCalled();
+ },
+ $expr1,
+ ];
+
+ // [
+ // 'fieldA="string"',
+ // [['eq', 'fieldA', 'my_fake_string', 'my_fake_comparison_A']],
+ // [['valueAsString', 'string', 'my_fake_string']],
+ // 'my_fake_comparison_A',
+ // ],
+ yield [
+ 'fieldA>1',
+ static function (ExpressionBuilderInterface|ObjectProphecy $mock) use ($expr1): void {
+ $mock->gt('fieldA', 1)->willReturn($expr1)->shouldBeCalled();
+ },
+ $expr1,
+ ];
+
+ yield [
+ 'fieldA≥1',
+ static function (ExpressionBuilderInterface|ObjectProphecy $mock) use ($expr1): void {
+ $mock->gte('fieldA', 1)->willReturn($expr1)->shouldBeCalled();
+ },
+ $expr1,
+ ];
+
+ yield [
+ 'fieldA>=1',
+ static function (ExpressionBuilderInterface|ObjectProphecy $mock) use ($expr1): void {
+ $mock->gte('fieldA', 1)->willReturn($expr1)->shouldBeCalled();
+ },
+ $expr1,
+ ];
+
+ yield [
+ 'fieldA<1',
+ static function (ExpressionBuilderInterface|ObjectProphecy $mock) use ($expr1): void {
+ $mock->lt('fieldA', 1)->willReturn($expr1)->shouldBeCalled();
+ },
+ $expr1,
+ ];
+
+ yield [
+ 'fieldA≤1',
+ static function (ExpressionBuilderInterface|ObjectProphecy $mock) use ($expr1): void {
+ $mock->lte('fieldA', 1)->willReturn($expr1)->shouldBeCalled();
+ },
+ $expr1,
+ ];
+
+ yield [
+ 'fieldA<=1',
+ static function (ExpressionBuilderInterface|ObjectProphecy $mock) use ($expr1): void {
+ $mock->lte('fieldA', 1)->willReturn($expr1)->shouldBeCalled();
+ },
+ $expr1,
+ ];
+
+ yield [
+ 'fieldA≠1',
+ static function (ExpressionBuilderInterface|ObjectProphecy $mock) use ($expr1): void {
+ $mock->neq('fieldA', 1)->willReturn($expr1)->shouldBeCalled();
+ },
+ $expr1,
+ ];
+
+ yield [
+ 'fieldA!=1',
+ static function (ExpressionBuilderInterface|ObjectProphecy $mock) use ($expr1): void {
+ $mock->neq('fieldA', 1)->willReturn($expr1)->shouldBeCalled();
+ },
+ $expr1,
+ ];
+
+ yield [
+ 'fieldA[1,2]',
+ static function (ExpressionBuilderInterface|ObjectProphecy $mock) use ($expr1): void {
+ $mock->in('fieldA', [1, 2])->willReturn($expr1)->shouldBeCalled();
+ },
+ $expr1,
+ ];
+
+ yield [
+ 'fieldA![1,2]',
+ static function (ExpressionBuilderInterface|ObjectProphecy $mock) use ($expr1): void {
+ $mock->notIn('fieldA', [1, 2])->willReturn($expr1)->shouldBeCalled();
+ },
+ $expr1,
+ ];
+
+ yield [
+ 'fieldA{{1}}',
+ static function (ExpressionBuilderInterface|ObjectProphecy $mock) use ($expr1): void {
+ $mock->contains('fieldA', 1)->willReturn($expr1)->shouldBeCalled();
+ },
+ $expr1,
+ ];
+
+ yield [
+ 'fieldA!{{1}}',
+ static function (ExpressionBuilderInterface|ObjectProphecy $mock) use ($expr1): void {
+ $mock->notContains('fieldA', 1)->willReturn($expr1)->shouldBeCalled();
+ },
+ $expr1,
+ ];
+
+ // Composite
+ yield [
+ 'fieldA=1|fieldB=2|fieldC=3',
+ static function (ExpressionBuilderInterface|ObjectProphecy $mock) use ($expr1, $expr2, $expr3, $composite1): void {
+ $mock->eq('fieldA', 1)->willReturn($expr1)->shouldBeCalled();
+ $mock->eq('fieldB', 2)->willReturn($expr2)->shouldBeCalled();
+ $mock->eq('fieldC', 3)->willReturn($expr3)->shouldBeCalled();
+ $mock->orX([$expr1, $expr2, $expr3])->willReturn($composite1)->shouldBeCalled();
+ },
+ $composite1,
+ ];
+
+ yield [
+ 'fieldA=1!|fieldB=2!|fieldC=3',
+ static function (ExpressionBuilderInterface|ObjectProphecy $mock) use ($expr1, $expr2, $expr3, $composite1): void {
+ $mock->eq('fieldA', 1)->willReturn($expr1)->shouldBeCalled();
+ $mock->eq('fieldB', 2)->willReturn($expr2)->shouldBeCalled();
+ $mock->eq('fieldC', 3)->willReturn($expr3)->shouldBeCalled();
+ $mock->norX([$expr1, $expr2, $expr3])->willReturn($composite1)->shouldBeCalled();
+ },
+ $composite1,
+ ];
+
+ yield [
+ 'fieldA=1^|fieldB=2^|fieldC=3',
+ static function (ExpressionBuilderInterface|ObjectProphecy $mock) use ($expr1, $expr2, $expr3, $composite1): void {
+ $mock->eq('fieldA', 1)->willReturn($expr1)->shouldBeCalled();
+ $mock->eq('fieldB', 2)->willReturn($expr2)->shouldBeCalled();
+ $mock->eq('fieldC', 3)->willReturn($expr3)->shouldBeCalled();
+ $mock->xorX([$expr1, $expr2, $expr3])->willReturn($composite1)->shouldBeCalled();
+ },
+ $composite1,
+ ];
+
+ yield [
+ 'fieldA=1⊕fieldB=2⊕fieldC=3',
+ static function (ExpressionBuilderInterface|ObjectProphecy $mock) use ($expr1, $expr2, $expr3, $composite1): void {
+ $mock->eq('fieldA', 1)->willReturn($expr1)->shouldBeCalled();
+ $mock->eq('fieldB', 2)->willReturn($expr2)->shouldBeCalled();
+ $mock->eq('fieldC', 3)->willReturn($expr3)->shouldBeCalled();
+ $mock->xorX([$expr1, $expr2, $expr3])->willReturn($composite1)->shouldBeCalled();
+ },
+ $composite1,
+ ];
+
+ yield [
+ 'fieldA=1&fieldB=2&fieldC=3',
+ static function (ExpressionBuilderInterface|ObjectProphecy $mock) use ($expr1, $expr2, $expr3, $composite1): void {
+ $mock->eq('fieldA', 1)->willReturn($expr1)->shouldBeCalled();
+ $mock->eq('fieldB', 2)->willReturn($expr2)->shouldBeCalled();
+ $mock->eq('fieldC', 3)->willReturn($expr3)->shouldBeCalled();
+ $mock->andX([$expr1, $expr2, $expr3])->willReturn($composite1)->shouldBeCalled();
+ },
+ $composite1,
+ ];
+
+ yield [
+ 'fieldA{{value}}&fieldB=2',
+ static function (ExpressionBuilderInterface|ObjectProphecy $mock) use ($expr1, $expr2, $composite1): void {
+ $mock->contains('fieldA', 'value')->willReturn($expr1)->shouldBeCalled();
+ $mock->eq('fieldB', 2)->willReturn($expr2)->shouldBeCalled();
+ $mock->andX([$expr1, $expr2])->willReturn($composite1)->shouldBeCalled();
+ },
+ $composite1,
+ ];
+
+ yield [
+ 'fieldA=1!&fieldB=2!&fieldC=3',
+ static function (ExpressionBuilderInterface|ObjectProphecy $mock) use ($expr1, $expr2, $expr3, $composite1): void {
+ $mock->eq('fieldA', 1)->willReturn($expr1)->shouldBeCalled();
+ $mock->eq('fieldB', 2)->willReturn($expr2)->shouldBeCalled();
+ $mock->eq('fieldC', 3)->willReturn($expr3)->shouldBeCalled();
+ $mock->nandX([$expr1, $expr2, $expr3])->willReturn($composite1)->shouldBeCalled();
+ },
+ $composite1,
+ ];
+
+ // Precedences
+ yield [
+ 'fieldA=1|fieldB=2|fieldC=3&fieldD=4',
+ static function (ExpressionBuilderInterface|ObjectProphecy $mock) use ($expr1, $expr2, $expr3, $expr4, $composite1, $composite2): void {
+ $mock->eq('fieldA', 1)->willReturn($expr1)->shouldBeCalled();
+ $mock->eq('fieldB', 2)->willReturn($expr2)->shouldBeCalled();
+ $mock->eq('fieldC', 3)->willReturn($expr3)->shouldBeCalled();
+ $mock->eq('fieldD', 4)->willReturn($expr4)->shouldBeCalled();
+ // And was before OR
+ $mock->andX([$expr3, $expr4])->willReturn($composite1)->shouldBeCalled();
+ $mock->orX([$expr1, $expr2, $composite1])->willReturn($composite2)->shouldBeCalled();
+ },
+ $composite2,
+ ];
+
+ yield [
+ 'fieldA=1&fieldB=2&fieldC=3!&fieldD=4',
+ static function (ExpressionBuilderInterface|ObjectProphecy $mock) use ($expr1, $expr2, $expr3, $expr4, $composite1, $composite2): void {
+ $mock->eq('fieldA', 1)->willReturn($expr1)->shouldBeCalled();
+ $mock->eq('fieldB', 2)->willReturn($expr2)->shouldBeCalled();
+ $mock->eq('fieldC', 3)->willReturn($expr3)->shouldBeCalled();
+ $mock->eq('fieldD', 4)->willReturn($expr4)->shouldBeCalled();
+ $mock->andX([$expr1, $expr2, $expr3])->willReturn($composite1)->shouldBeCalled();
+ $mock->nandX([$composite1, $expr4])->willReturn($composite2)->shouldBeCalled();
+ },
+ $composite2,
+ ];
+
+ yield [
+ 'fieldA=1|fieldB=2|fieldC=3!|fieldD=4',
+ static function (ExpressionBuilderInterface|ObjectProphecy $mock) use ($expr1, $expr2, $expr3, $expr4, $composite1, $composite2): void {
+ $mock->eq('fieldA', 1)->willReturn($expr1)->shouldBeCalled();
+ $mock->eq('fieldB', 2)->willReturn($expr2)->shouldBeCalled();
+ $mock->eq('fieldC', 3)->willReturn($expr3)->shouldBeCalled();
+ $mock->eq('fieldD', 4)->willReturn($expr4)->shouldBeCalled();
+ $mock->orX([$expr1, $expr2, $expr3])->willReturn($composite1)->shouldBeCalled();
+ $mock->norX([$composite1, $expr4])->willReturn($composite2)->shouldBeCalled();
+ },
+ $composite2,
+ ];
+
+ yield [
+ 'fieldA=1&fieldB=2&fieldC=3|fieldD=4',
+ static function (ExpressionBuilderInterface|ObjectProphecy $mock) use ($expr1, $expr2, $expr3, $expr4, $composite1, $composite2): void {
+ $mock->eq('fieldA', 1)->willReturn($expr1)->shouldBeCalled();
+ $mock->eq('fieldB', 2)->willReturn($expr2)->shouldBeCalled();
+ $mock->eq('fieldC', 3)->willReturn($expr3)->shouldBeCalled();
+ $mock->eq('fieldD', 4)->willReturn($expr4)->shouldBeCalled();
+ $mock->andX([$expr1, $expr2, $expr3])->willReturn($composite1)->shouldBeCalled();
+ $mock->orX([$composite1, $expr4])->willReturn($composite2)->shouldBeCalled();
+ },
+ $composite2,
+ ];
+
+ yield [
+ 'fieldA=1&fieldB=2|fieldC=3&fieldD=4',
+ static function (ExpressionBuilderInterface|ObjectProphecy $mock) use ($expr1, $expr2, $expr3, $expr4, $composite1, $composite2, $composite3): void {
+ $mock->eq('fieldA', 1)->willReturn($expr1)->shouldBeCalled();
+ $mock->eq('fieldB', 2)->willReturn($expr2)->shouldBeCalled();
+ $mock->eq('fieldC', 3)->willReturn($expr3)->shouldBeCalled();
+ $mock->eq('fieldD', 4)->willReturn($expr4)->shouldBeCalled();
+ $mock->andX([$expr1, $expr2])->willReturn($composite1)->shouldBeCalled();
+ $mock->andX([$expr3, $expr4])->willReturn($composite2)->shouldBeCalled();
+ $mock->orX([$composite1, $composite2])->willReturn($composite3)->shouldBeCalled();
+ },
+ $composite3,
+ ];
+
+ yield [
+ 'fieldA=1|fieldB=2|fieldC=3⊕fieldD=4',
+ static function (ExpressionBuilderInterface|ObjectProphecy $mock) use ($expr1, $expr2, $expr3, $expr4, $composite1, $composite2): void {
+ $mock->eq('fieldA', 1)->willReturn($expr1)->shouldBeCalled();
+ $mock->eq('fieldB', 2)->willReturn($expr2)->shouldBeCalled();
+ $mock->eq('fieldC', 3)->willReturn($expr3)->shouldBeCalled();
+ $mock->eq('fieldD', 4)->willReturn($expr4)->shouldBeCalled();
+ $mock->orX([$expr1, $expr2, $expr3])->willReturn($composite1)->shouldBeCalled();
+ $mock->xorX([$composite1, $expr4])->willReturn($composite2)->shouldBeCalled();
+ },
+ $composite2,
+ ];
+
+ // Parenthesis
+ yield [
+ '((fieldA=1))',
+ static function (ExpressionBuilderInterface|ObjectProphecy $mock) use ($expr1): void {
+ $mock->eq('fieldA', 1)->willReturn($expr1)->shouldBeCalled();
+ },
+ $expr1,
+ ];
+
+ yield [
+ '(fieldA=1|fieldB=2)&fieldC=3',
+ static function (ExpressionBuilderInterface|ObjectProphecy $mock) use ($expr1, $expr2, $expr3, $composite1, $composite2): void {
+ $mock->eq('fieldA', 1)->willReturn($expr1)->shouldBeCalled();
+ $mock->eq('fieldB', 2)->willReturn($expr2)->shouldBeCalled();
+ $mock->eq('fieldC', 3)->willReturn($expr3)->shouldBeCalled();
+ $mock->orX([$expr1, $expr2])->willReturn($composite1)->shouldBeCalled();
+ $mock->andX([$composite1, $expr3])->willReturn($composite2)->shouldBeCalled();
+ },
+ $composite2,
+ ];
+
+ yield [
+ 'fieldA=1|(fieldB=2&fieldC=3)',
+ static function (ExpressionBuilderInterface|ObjectProphecy $mock) use ($expr1, $expr2, $expr3, $composite1, $composite2): void {
+ $mock->eq('fieldA', 1)->willReturn($expr1)->shouldBeCalled();
+ $mock->eq('fieldB', 2)->willReturn($expr2)->shouldBeCalled();
+ $mock->eq('fieldC', 3)->willReturn($expr3)->shouldBeCalled();
+ $mock->andX([$expr2, $expr3])->willReturn($composite1)->shouldBeCalled();
+ $mock->orX([$expr1, $composite1])->willReturn($composite2)->shouldBeCalled();
+ },
+ $composite2,
+ ];
}
/**
- * @dataProvider forbiddenTokenDataProvider
- * @expectedException \Symftony\Xpression\Exception\Parser\InvalidExpressionException
- *
- * @param $input
+ * @dataProvider provideForbiddenTokenCases
*/
- public function testForbiddenToken($input)
+ public function testForbiddenToken(string $input): void
{
+ $this->expectException(InvalidExpressionException::class);
+ $this->expectExceptionMessage('Invalid expression.');
$this->parser->parse($input, Lexer::T_NONE);
}
- /**
- * @expectedException \Symftony\Xpression\Exception\Parser\InvalidExpressionException
- */
- public function testUnexpectedToken()
+ public static function provideForbiddenTokenCases(): iterable
{
- $this->expressionBuilderMock->eq('fieldA', 'foo')->willReturn('fake_return');
+ yield [','];
+
+ yield ['9'];
+
+ yield ['"string"'];
+
+ yield ["'string'"];
+
+ yield ['param'];
+
+ yield ['4.5'];
+
+ yield ['='];
+
+ yield ['≠'];
+
+ yield ['>'];
+
+ yield ['≥'];
+
+ yield ['<'];
+
+ yield ['≤'];
+
+ yield ['&'];
+
+ yield ['!&'];
+
+ yield ['|'];
+
+ yield ['!|'];
+
+ yield ['^|'];
- $this->parser->parse('fieldA=foo=1');
+ yield ['⊕'];
+
+ yield ['('];
+
+ yield [')'];
+
+ yield ['['];
+
+ yield ['!['];
+
+ yield [']'];
+
+ yield ['{{'];
+
+ yield ['!{{'];
+
+ yield ['}}'];
}
- /**
- * @expectedException \Symftony\Xpression\Exception\Parser\InvalidExpressionException
- */
- public function testUnsupportedToken()
+ public function testUnexpectedToken(): void
{
+ $this->expectException(InvalidExpressionException::class);
+ $this->expectExceptionMessage('Invalid expression.');
+ $this->parser->parse('fieldA==foo=1');
+ }
+
+ public function testUnsupportedToken(): void
+ {
+ $this->expectException(InvalidExpressionException::class);
+ $this->expectExceptionMessage('Invalid expression.');
$this->expressionBuilderMock->getSupportedTokenType()->willReturn(Lexer::T_NONE)->shouldBeCalled();
$this->parser->parse('fieldA=1');
}
+
+ public function testTokenPrecedenceError(): void
+ {
+ $this->expectException(InvalidExpressionException::class);
+ $this->expectExceptionMessage('Invalid expression.');
+ $this->expressionBuilderMock->getSupportedTokenType()->willReturn(Lexer::T_ALL)->shouldBeCalled();
+
+ try {
+ $this->parser->parse('a&b', Lexer::T_NONE);
+ } catch (\Throwable $e) {
+ $this->assertInstanceOf(ForbiddenTokenException::class, $e->getPrevious());
+ $this->assertEquals('Forbidden token "a". Allowed was .', $e->getPrevious()->getMessage());
+
+ throw $e;
+ }
+ }
}
diff --git a/tests/QueryStringParserTest.php b/tests/QueryStringParserTest.php
index 6c4beed..b648ea8 100644
--- a/tests/QueryStringParserTest.php
+++ b/tests/QueryStringParserTest.php
@@ -1,205 +1,226 @@
'',
- )
- ),
- array(
- 'param-A=',
- 'param-A=',
- array(
- 'param-A' => '',
- )
- ),
- array(
- 'param-A=valueA',
- 'param-A=valueA',
- array(
- 'param-A' => 'valueA',
- )
- ),
- array(
- 'param-A[]=valueA',
- 'param-A[]=valueA',
- array(
- 'param-A' => array('valueA'),
- )
- ),
- array(
- 'param-A[subA]=valueA',
- 'param-A[subA]=valueA',
- array(
- 'param-A' => array('subA' => 'valueA'),
- )
- ),
- array(
- 'param-A¶m-B',
- 'param-A¶m-B',
- array(
- 'param-A' => '',
- 'param-B' => '',
- )
- ),
- array(
- 'param-A=¶m-B',
- 'param-A=¶m-B',
- array(
- 'param-A' => '',
- 'param-B' => '',
- )
- ),
- array(
- 'param-A=valueA¶m-B',
- 'param-A=valueA¶m-B',
- array(
- 'param-A' => 'valueA',
- 'param-B' => '',
- )
- ),
- array(
- 'param-A[]=valueA¶m-B',
- 'param-A[]=valueA¶m-B',
- array(
- 'param-A' => array('valueA'),
- 'param-B' => '',
- )
- ),
- array(
- 'param-A[subA]=valueA¶m-B',
- 'param-A[subA]=valueA¶m-B',
- array(
- 'param-A' => array('subA' => 'valueA'),
- 'param-B' => '',
- )
- ),
-
- // With Xpression
- array(
- 'query{{valueA}}',
- 'query{{valueA}}',
- array(
- 'query{{valueA}}' => '',
- )
- ),
- array(
- 'query={price{{test}}&price=6}',
- 'query=price%7B%7Btest%7D%7D%26price%3D6',
- array(
- 'query' => 'price{{test}}&price=6',
- )
- ),
- array(
- 'query={name{{test 2}}}',
- 'query=name%7B%7Btest+2%7D%7D',
- array(
- 'query' => 'name{{test 2}}',
- )
- ),
- array(
- 'query={valueA}',
- 'query=valueA',
- array(
- 'query' => 'valueA',
- )
- ),
- array(
- 'query[]={valueA}',
- 'query[]=valueA',
- array(
- 'query' => array('valueA'),
- )
- ),
- array(
- 'query[subA]={valueA}',
- 'query[subA]=valueA',
- array(
- 'query' => array('subA' => 'valueA'),
- )
- ),
- array(
- 'query-A={valueA}&query-B={valueB}',
- 'query-A=valueA&query-B=valueB',
- array(
- 'query-A' => 'valueA',
- 'query-B' => 'valueB',
- )
- ),
- array(
- 'query-A[]={valueA1}&query-A[]={valueA2}&query-B={valueB}',
- 'query-A[]=valueA1&query-A[]=valueA2&query-B=valueB',
- array(
- 'query-A' => array('valueA1', 'valueA2'),
- 'query-B' => 'valueB',
- )
- ),
- array(
- 'query-A[subA]={valueA}&query-B={valueB}',
- 'query-A[subA]=valueA&query-B=valueB',
- array(
- 'query-A' => array('subA' => 'valueA'),
- 'query-B' => 'valueB',
- )
- ),
-
- // Fail
- array(
- 'query-A=valueA}',
- 'query-A=valueA}',
- array(
- 'query-A' => 'valueA}',
- )
- ),
- array(
- 'query-A={valueA',
- 'query-A={valueA',
- array(
- 'query-A' => '{valueA',
- )
- ),
- array(
- 'query-A={}valueA',
- 'query-A={}valueA',
- array(
- 'query-A' => '{}valueA',
- )
- ),
- array(
- 'query-A={{valueA}}',
- 'query-A={{valueA}}',
- array(
- 'query-A' => '{{valueA}}',
- )
- ),
- );
- }
-
/**
- * @dataProvider parseDataProvider
- *
- * @param $queryString
- * @param $expectedQueryString
- * @param $expectedGET
+ * @dataProvider provideParseCases
*/
- public function testParse($queryString, $expectedQueryString, $expectedGET)
+ public function testParse(string $queryString, string $expectedQueryString, array $expectedGET): void
{
$_SERVER['QUERY_STRING'] = $queryString;
QueryStringParser::correctServerQueryString();
- $this->assertEquals($expectedQueryString, $_SERVER['QUERY_STRING']);
- $this->assertEquals($expectedGET, $_GET);
+ self::assertSame($expectedQueryString, $_SERVER['QUERY_STRING']);
+ self::assertSame($expectedGET, $_GET);
+ }
+
+ public static function provideParseCases(): iterable
+ {
+ // Default querystring
+ yield [
+ 'param-A',
+ 'param-A',
+ [
+ 'param-A' => '',
+ ],
+ ];
+
+ yield [
+ 'param-A=',
+ 'param-A=',
+ [
+ 'param-A' => '',
+ ],
+ ];
+
+ yield [
+ 'param-A=valueA',
+ 'param-A=valueA',
+ [
+ 'param-A' => 'valueA',
+ ],
+ ];
+
+ yield [
+ 'param-A[]=valueA',
+ 'param-A[]=valueA',
+ [
+ 'param-A' => ['valueA'],
+ ],
+ ];
+
+ yield [
+ 'param-A[subA]=valueA',
+ 'param-A[subA]=valueA',
+ [
+ 'param-A' => ['subA' => 'valueA'],
+ ],
+ ];
+
+ yield [
+ 'param-A¶m-B',
+ 'param-A¶m-B',
+ [
+ 'param-A' => '',
+ 'param-B' => '',
+ ],
+ ];
+
+ yield [
+ 'param-A=¶m-B',
+ 'param-A=¶m-B',
+ [
+ 'param-A' => '',
+ 'param-B' => '',
+ ],
+ ];
+
+ yield [
+ 'param-A=valueA¶m-B',
+ 'param-A=valueA¶m-B',
+ [
+ 'param-A' => 'valueA',
+ 'param-B' => '',
+ ],
+ ];
+
+ yield [
+ 'param-A[]=valueA¶m-B',
+ 'param-A[]=valueA¶m-B',
+ [
+ 'param-A' => ['valueA'],
+ 'param-B' => '',
+ ],
+ ];
+
+ yield [
+ 'param-A[subA]=valueA¶m-B',
+ 'param-A[subA]=valueA¶m-B',
+ [
+ 'param-A' => ['subA' => 'valueA'],
+ 'param-B' => '',
+ ],
+ ];
+
+ // With Xpression
+ yield [
+ 'query{{valueA}}',
+ 'query{{valueA}}',
+ [
+ 'query{{valueA}}' => '',
+ ],
+ ];
+
+ yield [
+ 'query={price{{test}}&price=6}',
+ 'query=price%7B%7Btest%7D%7D%26price%3D6',
+ [
+ 'query' => 'price{{test}}&price=6',
+ ],
+ ];
+
+ yield [
+ 'query={name{{test 2}}}',
+ 'query=name%7B%7Btest+2%7D%7D',
+ [
+ 'query' => 'name{{test 2}}',
+ ],
+ ];
+
+ yield [
+ 'query={valueA}',
+ 'query=valueA',
+ [
+ 'query' => 'valueA',
+ ],
+ ];
+
+ yield [
+ 'query[]={valueA}',
+ 'query[]=valueA',
+ [
+ 'query' => ['valueA'],
+ ],
+ ];
+
+ yield [
+ 'query[subA]={valueA}',
+ 'query[subA]=valueA',
+ [
+ 'query' => ['subA' => 'valueA'],
+ ],
+ ];
+
+ yield [
+ 'query-A={valueA}&query-B={valueB}',
+ 'query-A=valueA&query-B=valueB',
+ [
+ 'query-A' => 'valueA',
+ 'query-B' => 'valueB',
+ ],
+ ];
+
+ yield [
+ 'query-A[]={valueA1}&query-A[]={valueA2}&query-B={valueB}',
+ 'query-A[]=valueA1&query-A[]=valueA2&query-B=valueB',
+ [
+ 'query-A' => ['valueA1', 'valueA2'],
+ 'query-B' => 'valueB',
+ ],
+ ];
+
+ yield [
+ 'query-A[subA]={valueA}&query-B={valueB}',
+ 'query-A[subA]=valueA&query-B=valueB',
+ [
+ 'query-A' => ['subA' => 'valueA'],
+ 'query-B' => 'valueB',
+ ],
+ ];
+
+ // Fail
+ yield [
+ 'query-A=valueA}',
+ 'query-A=valueA}',
+ [
+ 'query-A' => 'valueA}',
+ ],
+ ];
+
+ yield [
+ 'query-A={valueA',
+ 'query-A={valueA',
+ [
+ 'query-A' => '{valueA',
+ ],
+ ];
+
+ yield [
+ 'query-A={}valueA',
+ 'query-A={}valueA',
+ [
+ 'query-A' => '{}valueA',
+ ],
+ ];
+
+ yield [
+ 'query-A={{valueA}}',
+ 'query-A={{valueA}}',
+ [
+ 'query-A' => '{{valueA}}',
+ ],
+ ];
}
}