diff --git a/.codeclimate.yml b/.codeclimate.yml
deleted file mode 100644
index a4067ef..0000000
--- a/.codeclimate.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-exclude_paths:
- - '/vendor/*'
-
-engines:
- phpcodesniffer:
- enabled: true
- config:
- file_extensions: 'php'
- standard: 'PSR1,PSR2'
- phpmd:
- enabled: true
- config:
- file_extensions: 'php'
- rulesets: 'cleancode,codesize,design,naming,unusedcode'
-
-ratings:
- paths:
- - '**.php'
diff --git a/.travis.yml b/.travis.yml
index b9b08fb..9acee62 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,8 +1,7 @@
language: php
php:
- - 7.1
- - 7.2
+ - 7.4
before_script:
- composer self-update
diff --git a/CHANGELOG-2.x.md b/CHANGELOG-2.x.md
new file mode 100644
index 0000000..b3e598d
--- /dev/null
+++ b/CHANGELOG-2.x.md
@@ -0,0 +1,10 @@
+# CHANGELOG for 2.x
+This changelog references the relevant changes done in 2.x versions.
+
+
+## v2.0.0
+__BREAKING CHANGES__
+
+* Require php `>=7.4`
+* Uses php7 type hinting throughout with `declare(strict_types=1);`
+* Uses `"ruflin/elastica": "^7.0"`
diff --git a/README.md b/README.md
index 4e604a7..e7126f8 100644
--- a/README.md
+++ b/README.md
@@ -2,8 +2,6 @@ query-parser-php
=============
[![Build Status](https://api.travis-ci.org/gdbots/query-parser-php.svg)](https://travis-ci.org/gdbots/query-parser-php)
-[![Code Climate](https://codeclimate.com/github/gdbots/query-parser-php/badges/gpa.svg)](https://codeclimate.com/github/gdbots/query-parser-php)
-[![Test Coverage](https://codeclimate.com/github/gdbots/query-parser-php/badges/coverage.svg)](https://codeclimate.com/github/gdbots/query-parser-php/coverage)
Php library that converts search queries into words, phrases, hashtags, mentions, etc.
diff --git a/composer.json b/composer.json
index 1518098..4dae53c 100755
--- a/composer.json
+++ b/composer.json
@@ -5,12 +5,11 @@
"type": "library",
"license": "Apache-2.0",
"require": {
- "php": ">=7.1",
- "gdbots/common": "~0.1 || ^1.0"
+ "php": ">=7.4"
},
"require-dev": {
- "phpunit/phpunit": "~6.4",
- "ruflin/elastica": "~5.3"
+ "phpunit/phpunit": "^9.2",
+ "ruflin/elastica": "^7.0"
},
"autoload": {
"psr-4": {
@@ -24,10 +23,5 @@
},
"scripts": {
"test": "vendor/bin/phpunit"
- },
- "extra": {
- "branch-alias": {
- "dev-master": "0.3.x-dev"
- }
}
}
diff --git a/src/Builder/AbstractQueryBuilder.php b/src/Builder/AbstractQueryBuilder.php
index 6767f3e..e430322 100755
--- a/src/Builder/AbstractQueryBuilder.php
+++ b/src/Builder/AbstractQueryBuilder.php
@@ -21,20 +21,11 @@
abstract class AbstractQueryBuilder implements QueryBuilder
{
- /** @var Field */
- private $currentField;
-
- /** @var bool */
- private $queryOnFieldIsCacheable = false;
-
- /** @var bool */
- private $inField = false;
-
- /** @var bool */
- private $inRange = false;
-
- /** @var bool */
- private $inSubquery = false;
+ private ?Field $currentField = null;
+ private bool $queryOnFieldIsCacheable = false;
+ private bool $inField = false;
+ private bool $inRange = false;
+ private bool $inSubquery = false;
/**
* Array of field names which support full text queries. This value is
@@ -42,7 +33,8 @@ abstract class AbstractQueryBuilder implements QueryBuilder
*
* @var array
*/
- private $fullTextSearchFields = [
+ private array $fullTextSearchFields = [
+ 'd__all' => true,
'_all' => true,
'title' => true,
'tiny_title' => true,
@@ -101,133 +93,83 @@ abstract class AbstractQueryBuilder implements QueryBuilder
'ctx_ip_geo.city' => true,
];
- /** @var string */
- protected $defaultFieldName;
-
- /** @var string */
- protected $emojiFieldName;
-
- /** @var string */
- protected $emoticonFieldName;
-
- /** @var string */
- protected $hashtagFieldName;
+ protected string $defaultFieldName = '_all';
+ protected ?string $emojiFieldName = null;
+ protected ?string $emoticonFieldName = null;
+ protected ?string $hashtagFieldName = null;
+ protected ?string $mentionFieldName = null;
+ protected ?\DateTimeZone $localTimeZone = null;
- /** @var string */
- protected $mentionFieldName;
-
- /** @var \DateTimeZone */
- protected $localTimeZone;
-
- /**
- * {@inheritdoc}
- */
- public function clear(): QueryBuilder
+ public function clear(): self
{
return $this;
}
- /**
- * {@inheritdoc}
- */
- final public function setFullTextSearchFields(array $fields): QueryBuilder
+ final public function setFullTextSearchFields(array $fields): self
{
$this->fullTextSearchFields = array_flip($fields);
return $this;
}
- /**
- * {@inheritdoc}
- */
- final public function addFullTextSearchField(string $fieldName): QueryBuilder
+ final public function addFullTextSearchField(string $fieldName): self
{
$this->fullTextSearchFields[$fieldName] = true;
return $this;
}
- /**
- * {@inheritdoc}
- */
- final public function removeFullTextSearchField(string $fieldName): QueryBuilder
+ final public function removeFullTextSearchField(string $fieldName): self
{
unset($this->fullTextSearchFields[$fieldName]);
return $this;
}
- /**
- * {@inheritdoc}
- */
final public function getFullTextSearchFields(): array
{
return array_keys($this->fullTextSearchFields);
}
- /**
- * {@inheritdoc}
- */
final public function supportsFullTextSearch(string $fieldName): bool
{
return isset($this->fullTextSearchFields[trim(strtolower($fieldName))]);
}
- /**
- * {@inheritdoc}
- */
- final public function setDefaultFieldName(string $fieldName): QueryBuilder
+ final public function setDefaultFieldName(string $fieldName): self
{
$this->defaultFieldName = $fieldName;
return $this;
}
- /**
- * {@inheritdoc}
- */
- final public function setEmojiFieldName(string $fieldName): QueryBuilder
+ final public function setEmojiFieldName(string $fieldName): self
{
$this->emojiFieldName = $fieldName;
return $this;
}
- /**
- * {@inheritdoc}
- */
- final public function setEmoticonFieldName(string $fieldName): QueryBuilder
+ final public function setEmoticonFieldName(string $fieldName): self
{
$this->emoticonFieldName = $fieldName;
return $this;
}
- /**
- * {@inheritdoc}
- */
- final public function setHashtagFieldName(string $fieldName): QueryBuilder
+ final public function setHashtagFieldName(string $fieldName): self
{
$this->hashtagFieldName = $fieldName;
return $this;
}
- /**
- * {@inheritdoc}
- */
- final public function setMentionFieldName(string $fieldName): QueryBuilder
+ final public function setMentionFieldName(string $fieldName): self
{
$this->mentionFieldName = $fieldName;
return $this;
}
- /**
- * {@inheritdoc}
- */
- final public function setLocalTimeZone(\DateTimeZone $timeZone): QueryBuilder
+ final public function setLocalTimeZone(\DateTimeZone $timeZone): self
{
$this->localTimeZone = $timeZone;
return $this;
}
- /**
- * {@inheritdoc}
- */
- final public function addParsedQuery(ParsedQuery $parsedQuery): QueryBuilder
+ final public function addParsedQuery(ParsedQuery $parsedQuery): self
{
foreach ($parsedQuery->getNodes() as $node) {
$node->acceptBuilder($this);
@@ -236,19 +178,13 @@ final public function addParsedQuery(ParsedQuery $parsedQuery): QueryBuilder
return $this;
}
- /**
- * {@inheritdoc}
- */
- final public function addDate(Date $date): QueryBuilder
+ final public function addDate(Date $date): self
{
$this->handleTerm($date);
return $this;
}
- /**
- * {@inheritdoc}
- */
- final public function addEmoji(Emoji $emoji): QueryBuilder
+ final public function addEmoji(Emoji $emoji): self
{
if ($this->inField || null === $this->emojiFieldName) {
$this->handleTerm($emoji);
@@ -266,10 +202,7 @@ final public function addEmoji(Emoji $emoji): QueryBuilder
return $this->addField($field);
}
- /**
- * {@inheritdoc}
- */
- final public function addEmoticon(Emoticon $emoticon): QueryBuilder
+ final public function addEmoticon(Emoticon $emoticon): self
{
if ($this->inField || null === $this->emoticonFieldName) {
$this->handleTerm($emoticon);
@@ -287,10 +220,7 @@ final public function addEmoticon(Emoticon $emoticon): QueryBuilder
return $this->addField($field);
}
- /**
- * {@inheritdoc}
- */
- final public function addField(Field $field): QueryBuilder
+ final public function addField(Field $field): self
{
if ($this->inField || $this->inRange) {
throw new \LogicException('A Field cannot be nested in another Field or Range.');
@@ -308,10 +238,7 @@ final public function addField(Field $field): QueryBuilder
return $this;
}
- /**
- * {@inheritdoc}
- */
- final public function addHashtag(Hashtag $hashtag): QueryBuilder
+ final public function addHashtag(Hashtag $hashtag): self
{
if ($this->inField || null === $this->hashtagFieldName) {
$this->handleTerm($hashtag);
@@ -329,10 +256,7 @@ final public function addHashtag(Hashtag $hashtag): QueryBuilder
return $this->addField($field);
}
- /**
- * {@inheritdoc}
- */
- final public function addMention(Mention $mention): QueryBuilder
+ final public function addMention(Mention $mention): self
{
if ($this->inField || null === $this->mentionFieldName) {
$this->handleTerm($mention);
@@ -350,28 +274,19 @@ final public function addMention(Mention $mention): QueryBuilder
return $this->addField($field);
}
- /**
- * {@inheritdoc}
- */
- final public function addNumber(Numbr $number): QueryBuilder
+ final public function addNumber(Numbr $number): self
{
$this->handleTerm($number);
return $this;
}
- /**
- * {@inheritdoc}
- */
- final public function addPhrase(Phrase $phrase): QueryBuilder
+ final public function addPhrase(Phrase $phrase): self
{
$this->handleText($phrase);
return $this;
}
- /**
- * {@inheritdoc}
- */
- final public function addRange(Range $range): QueryBuilder
+ final public function addRange(Range $range): self
{
if (!$this->inField || $this->inRange || $this->inSubquery) {
throw new \LogicException('A Range can only be used within a field. e.g. rating:[1..5]');
@@ -383,10 +298,7 @@ final public function addRange(Range $range): QueryBuilder
return $this;
}
- /**
- * {@inheritdoc}
- */
- final public function addSubquery(Subquery $subquery): QueryBuilder
+ final public function addSubquery(Subquery $subquery): self
{
if ($this->inRange || $this->inSubquery) {
throw new \LogicException('A Subquery cannot be nested or within a Range.');
@@ -405,51 +317,33 @@ final public function addSubquery(Subquery $subquery): QueryBuilder
return $this;
}
- /**
- * {@inheritdoc}
- */
- final public function addUrl(Url $url): QueryBuilder
+ final public function addUrl(Url $url): self
{
$this->handleTerm($url);
return $this;
}
- /**
- * {@inheritdoc}
- */
- final public function addWord(Word $word): QueryBuilder
+ final public function addWord(Word $word): self
{
$this->handleText($word);
return $this;
}
- /**
- * @return bool
- */
final protected function inField(): bool
{
return $this->inField;
}
- /**
- * @return bool
- */
final protected function inRange(): bool
{
return $this->inRange;
}
- /**
- * @return bool
- */
final protected function inSubquery(): bool
{
return $this->inSubquery;
}
- /**
- * @param Node $node
- */
private function handleText(Node $node): void
{
if ($this->inField && !$this->supportsFullTextSearch($this->currentField->getName())) {
@@ -484,9 +378,6 @@ private function handleText(Node $node): void
$this->mustNotMatch($node, $this->currentField);
}
- /**
- * @param Node $node
- */
private function handleTerm(Node $node): void
{
/*
@@ -548,80 +439,33 @@ protected function queryOnFieldIsCacheable(Field $field): bool
return true;
}
- /**
- * @param Field $field
- * @param bool $cacheable
- */
protected function startField(Field $field, bool $cacheable = false): void
{
}
- /**
- * @param Field $field
- * @param bool $cacheable
- */
protected function endField(Field $field, bool $cacheable = false): void
{
}
- /**
- * @param Subquery $subquery
- * @param Field $field
- */
protected function startSubquery(Subquery $subquery, ?Field $field = null): void
{
}
- /**
- * @param Subquery $subquery
- * @param Field $field
- */
protected function endSubquery(Subquery $subquery, ?Field $field = null): void
{
}
- /**
- * @param Range $range
- * @param Field $field
- * @param bool $cacheable
- */
abstract protected function handleRange(Range $range, Field $field, bool $cacheable = false): void;
- /**
- * @param Node $node
- * @param Field $field
- */
abstract protected function mustMatch(Node $node, ?Field $field = null): void;
- /**
- * @param Node $node
- * @param Field $field
- */
abstract protected function shouldMatch(Node $node, ?Field $field = null): void;
- /**
- * @param Node $node
- * @param Field $field
- */
abstract protected function mustNotMatch(Node $node, ?Field $field = null): void;
- /**
- * @param Node $node
- * @param Field $field
- * @param bool $cacheable
- */
abstract protected function mustMatchTerm(Node $node, ?Field $field = null, bool $cacheable = false): void;
- /**
- * @param Node $node
- * @param Field $field
- */
abstract protected function shouldMatchTerm(Node $node, ?Field $field = null): void;
- /**
- * @param Node $node
- * @param Field $field
- * @param bool $cacheable
- */
abstract protected function mustNotMatchTerm(Node $node, ?Field $field = null, bool $cacheable = false): void;
}
diff --git a/src/Builder/ElasticaQueryBuilder.php b/src/Builder/ElasticaQueryBuilder.php
index 4bbd09e..74cdf44 100755
--- a/src/Builder/ElasticaQueryBuilder.php
+++ b/src/Builder/ElasticaQueryBuilder.php
@@ -25,11 +25,8 @@
class ElasticaQueryBuilder extends AbstractQueryBuilder
{
- /** @var RuflinQueryBuilder */
- protected $qb;
-
- /** @var BoolQuery */
- protected $boolQuery;
+ protected RuflinQueryBuilder $qb;
+ protected BoolQuery $boolQuery;
/**
* When a subquery is entered we'll take the current query
@@ -38,19 +35,11 @@ class ElasticaQueryBuilder extends AbstractQueryBuilder
*
* @var BoolQuery
*/
- protected $outerBoolQuery;
-
- /** @var bool */
- protected $ignoreEmojis = true;
-
- /** @var bool */
- protected $ignoreEmoticons = true;
-
- /** @var bool */
- protected $ignoreStopWords = true;
-
- /** @var bool */
- protected $lowerCaseTerms = true;
+ protected BoolQuery $outerBoolQuery;
+ protected bool $ignoreEmojis = true;
+ protected bool $ignoreEmoticons = true;
+ protected bool $ignoreStopWords = true;
+ protected bool $lowerCaseTerms = true;
/**
* Array of field names which are nested objects in ElasticSearch and
@@ -60,7 +49,7 @@ class ElasticaQueryBuilder extends AbstractQueryBuilder
*
* @var string[]
*/
- protected $nestedFields = [];
+ protected array $nestedFields = [];
/**
* Any fields encountered that are nested are stored as a nested query
@@ -71,21 +60,16 @@ class ElasticaQueryBuilder extends AbstractQueryBuilder
*
* @var Nested[]
*/
- protected $nestedQueries = [];
+ protected array $nestedQueries = [];
- /**
- * ElasticaQueryBuilder constructor.
- */
public function __construct()
{
+ $this->defaultFieldName = '_all';
$this->qb = new RuflinQueryBuilder();
$this->clear();
}
- /**
- * {@inheritdoc}
- */
- public function clear(): QueryBuilder
+ public function clear(): self
{
$this->boolQuery = $this->qb->query()->bool();
$this->outerBoolQuery = $this->boolQuery;
@@ -93,94 +77,53 @@ public function clear(): QueryBuilder
return $this;
}
- /**
- * @param bool $ignoreEmojis
- *
- * @return static
- */
public function ignoreEmojis(bool $ignoreEmojis = true): self
{
$this->ignoreEmojis = $ignoreEmojis;
return $this;
}
- /**
- * @param bool $ignoreEmoticons
- *
- * @return static
- */
public function ignoreEmoticons(bool $ignoreEmoticons = true): self
{
$this->ignoreEmoticons = $ignoreEmoticons;
return $this;
}
- /**
- * @param bool $ignoreStopWords
- *
- * @return static
- */
public function ignoreStopWords(bool $ignoreStopWords = true): self
{
$this->ignoreStopWords = $ignoreStopWords;
return $this;
}
- /**
- * @param bool $lowerCaseTerms
- *
- * @return static
- */
public function lowerCaseTerms(bool $lowerCaseTerms = true): self
{
$this->lowerCaseTerms = $lowerCaseTerms;
return $this;
}
- /**
- * @param string[] $fields
- *
- * @return static
- */
public function setNestedFields(array $fields): self
{
$this->nestedFields = array_flip($fields);
return $this;
}
- /**
- * @param string $fieldName
- *
- * @return static
- */
public function addNestedField(string $fieldName): self
{
$this->nestedFields[$fieldName] = true;
return $this;
}
- /**
- * @param string $fieldName
- *
- * @return static
- */
public function removeNestedField(string $fieldName): self
{
unset($this->nestedFields[$fieldName]);
return $this;
}
- /**
- * @return array
- */
public function getNestedFields(): array
{
return array_keys($this->nestedFields);
}
- /**
- * @return BoolQuery
- */
public function getBoolQuery(): BoolQuery
{
if ($this->boolQuery->hasParam('must')) {
@@ -191,9 +134,6 @@ public function getBoolQuery(): BoolQuery
return $this->boolQuery->setMinimumShouldMatch('2<80%');
}
- /**
- * {@inheritdoc}
- */
protected function handleRange(Range $range, Field $field, bool $cacheable = false): void
{
$useBoost = $field->useBoost();
@@ -256,18 +196,12 @@ protected function handleRange(Range $range, Field $field, bool $cacheable = fal
$this->addToBoolQuery($method, $field->getName(), $this->qb->query()->range($field->getName(), $data));
}
- /**
- * {@inheritdoc}
- */
protected function startSubquery(Subquery $subquery, ?Field $field = null): void
{
$this->outerBoolQuery = $this->boolQuery;
$this->boolQuery = $this->qb->query()->bool();
}
- /**
- * {@inheritdoc}
- */
protected function endSubquery(Subquery $subquery, ?Field $field = null): void
{
$params = $this->boolQuery->getParams();
@@ -300,32 +234,23 @@ protected function endSubquery(Subquery $subquery, ?Field $field = null): void
$this->boolQuery = $this->outerBoolQuery;
}
- /**
- * {@inheritdoc}
- */
protected function mustMatch(Node $node, ?Field $field = null): void
{
$this->addTextToQuery('addMust', $node, $field);
}
- /**
- * {@inheritdoc}
- */
protected function shouldMatch(Node $node, ?Field $field = null): void
{
$this->addTextToQuery('addShould', $node, $field);
}
- /**
- * {@inheritdoc}
- */
protected function mustNotMatch(Node $node, ?Field $field = null): void
{
$this->addTextToQuery('addMustNot', $node, $field);
}
/**
- * Adds a text node to the active query. These all use the "match" when full
+ * Adds a text node to the active query. These all use the "match" when full
* text searching is needed/supported.
*
* @param string $method
@@ -365,31 +290,31 @@ protected function addTextToQuery(string $method, Node $node, ?Field $field = nu
$fuzzy = 1;
}
- if ($useFuzzy && $node instanceof Phrase) {
- $data = [
- 'query' => $node->getValue(),
- 'type' => Phrase::NODE_TYPE,
- 'lenient' => true,
- 'phrase_slop' => $fuzzy,
- ];
+ if ($node instanceof Phrase) {
+ $data = ['query' => $node->getValue()];
if ($useBoost) {
$data['boost'] = $boost;
}
- $query = $this->qb->query()->match();
- $query->setField($fieldName, $data);
+ if ($useFuzzy) {
+ $data['slop'] = $fuzzy;
+ }
+
+ $query = $this->qb->query()->match_phrase($fieldName, $data);
} elseif ($useFuzzy) {
- $query = $this->qb->query()->fuzzy();
- $query->setField($fieldName, $node->getValue());
+ $query = $this->qb->query()->fuzzy($fieldName, $node->getValue());
$query->setFieldOption('fuzziness', $fuzzy);
if ($useBoost) {
$query->setFieldOption('boost', $boost);
}
} elseif ($node instanceof Word && $node->hasTrailingWildcard()) {
- $query = $this->qb->query()->wildcard();
- $query->setValue($fieldName, strtolower($node->getValue()) . '*', $useBoost ? $boost : Word::DEFAULT_BOOST);
+ $query = $this->qb->query()->wildcard(
+ $fieldName,
+ strtolower($node->getValue()) . '*',
+ $useBoost ? $boost : Word::DEFAULT_BOOST
+ );
} else {
$data = ['query' => $node->getValue(), 'operator' => 'and', 'lenient' => true];
@@ -397,43 +322,29 @@ protected function addTextToQuery(string $method, Node $node, ?Field $field = nu
$data['boost'] = $boost;
}
- if ($node instanceof Phrase) {
- $data['type'] = Phrase::NODE_TYPE;
- }
-
- $query = $this->qb->query()->match();
- $query->setField($fieldName, $data);
+ $query = $this->qb->query()->match($fieldName, $data);
}
$this->addToBoolQuery($method, $fieldName, $query);
}
- /**
- * {@inheritdoc}
- */
protected function mustMatchTerm(Node $node, ?Field $field = null, bool $cacheable = false): void
{
$this->addTermToQuery('addMust', $node, $field, $cacheable);
}
- /**
- * {@inheritdoc}
- */
protected function shouldMatchTerm(Node $node, ?Field $field = null): void
{
$this->addTermToQuery('addShould', $node, $field);
}
- /**
- * {@inheritdoc}
- */
protected function mustNotMatchTerm(Node $node, ?Field $field = null, bool $cacheable = false): void
{
$this->addTermToQuery('addMustNot', $node, $field, $cacheable);
}
/**
- * Adds a term to the bool query or filter context. Filter context is used when the
+ * Adds a term to the bool query or filter context. Filter context is used when the
* request for that item could be cached, like documents with hashtag of cats.
*
* @param string $method
@@ -540,11 +451,6 @@ protected function createDateRangeForSingleNode(
return $this->qb->query()->range($fieldName, $data);
}
- /**
- * @param string $method
- * @param string $fieldName
- * @param AbstractQuery $query
- */
protected function addToBoolQuery(string $method, string $fieldName, AbstractQuery $query): void
{
if (false === strpos($fieldName, '.')) {
@@ -563,7 +469,8 @@ protected function addToBoolQuery(string $method, string $fieldName, AbstractQue
if (!isset($this->nestedQueries[$nestedQuery])) {
$this->nestedQueries[$nestedQuery] = (new Nested())
->setQuery($this->qb->query()->bool()->setMinimumShouldMatch('2<80%'))
- ->setPath($nestedPath);
+ ->setPath($nestedPath)
+ ->setParam('ignore_unmapped', true);
$this->boolQuery->$method($this->nestedQueries[$nestedQuery]);
}
diff --git a/src/Builder/QueryBuilder.php b/src/Builder/QueryBuilder.php
index 3896ce8..e9fd771 100755
--- a/src/Builder/QueryBuilder.php
+++ b/src/Builder/QueryBuilder.php
@@ -26,7 +26,7 @@ interface QueryBuilder
*
* @return static
*/
- public function clear(): QueryBuilder;
+ public function clear(): self;
/**
* Sets the fields that this builder will enable for full text search.
@@ -35,7 +35,7 @@ public function clear(): QueryBuilder;
*
* @return static
*/
- public function setFullTextSearchFields(array $fields): QueryBuilder;
+ public function setFullTextSearchFields(array $fields): self;
/**
* Adds a field that this builder will enable for full text search.
@@ -44,7 +44,7 @@ public function setFullTextSearchFields(array $fields): QueryBuilder;
*
* @return static
*/
- public function addFullTextSearchField(string $fieldName): QueryBuilder;
+ public function addFullTextSearchField(string $fieldName): self;
/**
* Removes a field that was previously enabled for full text search.
@@ -53,7 +53,7 @@ public function addFullTextSearchField(string $fieldName): QueryBuilder;
*
* @return static
*/
- public function removeFullTextSearchField(string $fieldName): QueryBuilder;
+ public function removeFullTextSearchField(string $fieldName): self;
/**
* Gets the fields enabled for full text search.
@@ -79,70 +79,70 @@ public function supportsFullTextSearch(string $fieldName): bool;
*
* @return static
*/
- public function setDefaultFieldName(string $fieldName): QueryBuilder;
+ public function setDefaultFieldName(string $fieldName): self;
/**
* @param string $fieldName
*
* @return static
*/
- public function setEmojiFieldName(string $fieldName): QueryBuilder;
+ public function setEmojiFieldName(string $fieldName): self;
/**
* @param string $fieldName
*
* @return static
*/
- public function setEmoticonFieldName(string $fieldName): QueryBuilder;
+ public function setEmoticonFieldName(string $fieldName): self;
/**
* @param string $fieldName
*
* @return static
*/
- public function setHashtagFieldName(string $fieldName): QueryBuilder;
+ public function setHashtagFieldName(string $fieldName): self;
/**
* @param string $fieldName
*
* @return static
*/
- public function setMentionFieldName(string $fieldName): QueryBuilder;
+ public function setMentionFieldName(string $fieldName): self;
/**
* @param \DateTimeZone $timeZone
*
* @return static
*/
- public function setLocalTimeZone(\DateTimeZone $timeZone): QueryBuilder;
+ public function setLocalTimeZone(\DateTimeZone $timeZone): self;
/**
* @param ParsedQuery $parsedQuery
*
* @return static
*/
- public function addParsedQuery(ParsedQuery $parsedQuery): QueryBuilder;
+ public function addParsedQuery(ParsedQuery $parsedQuery): self;
/**
* @param Date $date
*
* @return static
*/
- public function addDate(Date $date): QueryBuilder;
+ public function addDate(Date $date): self;
/**
* @param Emoji $emoji
*
* @return static
*/
- public function addEmoji(Emoji $emoji): QueryBuilder;
+ public function addEmoji(Emoji $emoji): self;
/**
* @param Emoticon $emoticon
*
* @return static
*/
- public function addEmoticon(Emoticon $emoticon): QueryBuilder;
+ public function addEmoticon(Emoticon $emoticon): self;
/**
* @param Field $field
@@ -151,35 +151,35 @@ public function addEmoticon(Emoticon $emoticon): QueryBuilder;
*
* @throws \LogicException
*/
- public function addField(Field $field): QueryBuilder;
+ public function addField(Field $field): self;
/**
* @param Hashtag $hashtag
*
* @return static
*/
- public function addHashtag(Hashtag $hashtag): QueryBuilder;
+ public function addHashtag(Hashtag $hashtag): self;
/**
* @param Mention $mention
*
* @return static
*/
- public function addMention(Mention $mention): QueryBuilder;
+ public function addMention(Mention $mention): self;
/**
* @param Numbr $number
*
* @return static
*/
- public function addNumber(Numbr $number): QueryBuilder;
+ public function addNumber(Numbr $number): self;
/**
* @param Phrase $phrase
*
* @return static
*/
- public function addPhrase(Phrase $phrase): QueryBuilder;
+ public function addPhrase(Phrase $phrase): self;
/**
* @param Range $range
@@ -188,7 +188,7 @@ public function addPhrase(Phrase $phrase): QueryBuilder;
*
* @throws \LogicException
*/
- public function addRange(Range $range): QueryBuilder;
+ public function addRange(Range $range): self;
/**
* @param Subquery $subquery
@@ -197,19 +197,19 @@ public function addRange(Range $range): QueryBuilder;
*
* @throws \LogicException
*/
- public function addSubquery(Subquery $subquery): QueryBuilder;
+ public function addSubquery(Subquery $subquery): self;
/**
* @param Url $url
*
* @return static
*/
- public function addUrl(Url $url): QueryBuilder;
+ public function addUrl(Url $url): self;
/**
* @param Word $word
*
* @return static
*/
- public function addWord(Word $word): QueryBuilder;
+ public function addWord(Word $word): self;
}
diff --git a/src/Builder/XmlQueryBuilder.php b/src/Builder/XmlQueryBuilder.php
index 5bae0e4..142bd31 100755
--- a/src/Builder/XmlQueryBuilder.php
+++ b/src/Builder/XmlQueryBuilder.php
@@ -3,7 +3,6 @@
namespace Gdbots\QueryParser\Builder;
-use Gdbots\Common\Util\StringUtils;
use Gdbots\QueryParser\Enum\ComparisonOperator;
use Gdbots\QueryParser\Node\Date;
use Gdbots\QueryParser\Node\Field;
@@ -24,38 +23,26 @@
*/
class XmlQueryBuilder extends AbstractQueryBuilder
{
- /** @var string */
- protected $result;
+ protected string $result = '';
+ protected int $indent = 2;
- /** @var int */
- protected $indent = 2;
-
- /**
- * {@inheritdoc}
- */
- public function clear(): QueryBuilder
+ public function clear(): self
{
$this->result = '';
$this->indent = 2;
return $this;
}
- /**
- * @return string
- */
public function toXmlString(): string
{
return '' . PHP_EOL . '' . PHP_EOL . rtrim((string)$this->result) . PHP_EOL . '';
}
- /**
- * @return \SimpleXMLElement
- */
public function toSimpleXmlElement(): \SimpleXMLElement
{
try {
$xml = new \SimpleXMLElement($this->toXmlString());
- } catch (\Exception $e) {
+ } catch (\Throwable $e) {
$xml = null;
}
@@ -66,9 +53,6 @@ public function toSimpleXmlElement(): \SimpleXMLElement
return new \SimpleXMLElement('');
}
- /**
- * {@inheritdoc}
- */
protected function startField(Field $field, bool $cacheable = false): void
{
$tag = sprintf('field name="%s"', $field->getName());
@@ -89,18 +73,12 @@ protected function startField(Field $field, bool $cacheable = false): void
$this->indent();
}
- /**
- * {@inheritdoc}
- */
protected function endField(Field $field, bool $cacheable = false): void
{
$this->outdent();
$this->printLine('');
}
- /**
- * {@inheritdoc}
- */
protected function handleRange(Range $range, Field $field, bool $cacheable = false): void
{
$this->printLine(
@@ -134,9 +112,6 @@ protected function handleRange(Range $range, Field $field, bool $cacheable = fal
$this->printLine('' . $range::NODE_TYPE . '>');
}
- /**
- * {@inheritdoc}
- */
protected function startSubquery(Subquery $subquery, ?Field $field = null): void
{
$tag = $subquery::NODE_TYPE;
@@ -150,68 +125,42 @@ protected function startSubquery(Subquery $subquery, ?Field $field = null): void
$this->indent();
}
- /**
- * {@inheritdoc}
- */
protected function endSubquery(Subquery $subquery, ?Field $field = null): void
{
$this->outdent();
$this->printLine('');
}
- /**
- * {@inheritdoc}
- */
protected function mustMatch(Node $node, ?Field $field = null): void
{
$this->printSimpleNode(__FUNCTION__, $node, $field);
}
- /**
- * {@inheritdoc}
- */
protected function shouldMatch(Node $node, ?Field $field = null): void
{
$this->printSimpleNode(__FUNCTION__, $node, $field);
}
- /**
- * {@inheritdoc}
- */
protected function mustNotMatch(Node $node, ?Field $field = null): void
{
$this->printSimpleNode(__FUNCTION__, $node, $field);
}
- /**
- * {@inheritdoc}
- */
protected function mustMatchTerm(Node $node, ?Field $field = null, bool $cacheable = false): void
{
$this->printSimpleNode(__FUNCTION__, $node, $field);
}
- /**
- * {@inheritdoc}
- */
protected function shouldMatchTerm(Node $node, ?Field $field = null): void
{
$this->printSimpleNode(__FUNCTION__, $node, $field);
}
- /**
- * {@inheritdoc}
- */
protected function mustNotMatchTerm(Node $node, ?Field $field = null, bool $cacheable = false): void
{
$this->printSimpleNode(__FUNCTION__, $node, $field);
}
- /**
- * @param string $rule
- * @param Node $node
- * @param Field $field
- */
protected function printSimpleNode(string $rule, Node $node, ?Field $field = null): void
{
if ($this->inRange()) {
@@ -235,7 +184,8 @@ protected function printSimpleNode(string $rule, Node $node, ?Field $field = nul
}
}
- $tag .= sprintf(' rule="%s"', StringUtils::toSnakeFromCamel($rule));
+ $snaked = trim(strtolower(preg_replace('/([A-Z])/', '_$1', $rule)), '_');
+ $tag .= sprintf(' rule="%s"', $snaked);
if ($node instanceof Numbr || $node instanceof Date) {
switch ($node->getComparisonOperator()->getValue()) {
@@ -273,26 +223,16 @@ protected function printSimpleNode(string $rule, Node $node, ?Field $field = nul
$this->printLine(sprintf('<%s>%s%s>', $tag, $value, $node::NODE_TYPE));
}
- /**
- * @param string $line
- * @param bool $newLine
- */
protected function printLine(string $line, bool $newLine = true): void
{
$this->result .= str_repeat(' ', $this->indent) . $line . ($newLine ? PHP_EOL : '');
}
- /**
- * @param int $step
- */
protected function indent(int $step = 2): void
{
$this->indent += $step;
}
- /**
- * @param int $step
- */
protected function outdent(int $step = 2): void
{
$this->indent -= $step;
diff --git a/src/Enum/AbstractEnum.php b/src/Enum/AbstractEnum.php
new file mode 100644
index 0000000..7ec84fd
--- /dev/null
+++ b/src/Enum/AbstractEnum.php
@@ -0,0 +1,157 @@
+value = $value;
+ }
+
+ /**
+ * @param string|int $value
+ *
+ * @return static
+ * @throws \UnexpectedValueException
+ */
+ final public static function create($value): self
+ {
+ $key = static::class . $value;
+
+ if (isset(self::$instances[$key])) {
+ return self::$instances[$key];
+ }
+
+ $values = static::values();
+ if (!in_array($value, $values)) {
+ throw new \UnexpectedValueException("Value '$value' is not part of the enum " . static::class);
+ }
+
+ self::$instances[$key] = new static($value);
+ return self::$instances[$key];
+ }
+
+ /**
+ * Returns the name/key of the constant this enum value matches. Note that this
+ * may not return the exact constant name you'd expect if you have multiple
+ * constants that share the same value.
+ *
+ * @return string
+ */
+ final public function getName(): string
+ {
+ return array_flip(static::values())[$this->value];
+ }
+
+ /**
+ * @return int|string
+ */
+ final public function getValue()
+ {
+ return $this->value;
+ }
+
+ final public function __toString()
+ {
+ return (string)$this->value;
+ }
+
+ final public function jsonSerialize()
+ {
+ return $this->value;
+ }
+
+ /**
+ * Returns the names (or keys) of all of constants in the enum
+ *
+ * @return string[]
+ */
+ final public static function keys(): array
+ {
+ return array_keys(static::values());
+ }
+
+ /**
+ * Return the names and values of all the constants in the enum
+ *
+ * @return array
+ */
+ final public static function values(): array
+ {
+ $class = static::class;
+
+ if (!isset(self::$values[$class])) {
+ self::$values[$class] = (new \ReflectionClass($class))->getConstants();
+ }
+
+ return self::$values[$class];
+ }
+
+ /**
+ * Compares this enum (which has a value) to the value provided. If the value
+ * is itself an Enum then we'll get the value of the provided enum and compare
+ * it to our value.
+ *
+ * @param self|int|string $value
+ *
+ * @return bool
+ */
+ final public function equals($value): bool
+ {
+ if ($value instanceof AbstractEnum) {
+ return $this->value == $value->getValue();
+ }
+
+ return $this->value == $value;
+ }
+
+ /**
+ * Returns a value when called statically like so: MyEnum::SOME_VALUE() given SOME_VALUE is a class constant
+ *
+ * @param string $name
+ * @param array $arguments
+ *
+ * @return static
+ * @throws \BadMethodCallException
+ */
+ final public static function __callStatic($name, $arguments)
+ {
+ if (defined("static::$name")) {
+ return static::create(constant("static::$name"));
+ }
+
+ throw new \BadMethodCallException("No static method or enum constant '$name' in class " . static::class);
+ }
+}
diff --git a/src/Enum/BoolOperator.php b/src/Enum/BoolOperator.php
index bdf983a..aa42681 100644
--- a/src/Enum/BoolOperator.php
+++ b/src/Enum/BoolOperator.php
@@ -3,14 +3,12 @@
namespace Gdbots\QueryParser\Enum;
-use Gdbots\Common\Enum;
-
/**
* @method static BoolOperator OPTIONAL()
* @method static BoolOperator REQUIRED()
* @method static BoolOperator PROHIBITED()
*/
-final class BoolOperator extends Enum
+final class BoolOperator extends AbstractEnum
{
const OPTIONAL = 0;
const REQUIRED = 1;
diff --git a/src/Enum/ComparisonOperator.php b/src/Enum/ComparisonOperator.php
index ae4e1ca..a114e45 100644
--- a/src/Enum/ComparisonOperator.php
+++ b/src/Enum/ComparisonOperator.php
@@ -3,8 +3,6 @@
namespace Gdbots\QueryParser\Enum;
-use Gdbots\Common\Enum;
-
/**
* @method static ComparisonOperator EQ()
* @method static ComparisonOperator GT()
@@ -12,7 +10,7 @@
* @method static ComparisonOperator LT()
* @method static ComparisonOperator LTE()
*/
-final class ComparisonOperator extends Enum
+final class ComparisonOperator extends AbstractEnum
{
const EQ = 'eq';
const GT = 'gt';
diff --git a/src/Node/Date.php b/src/Node/Date.php
index 93d393f..3c6fc45 100755
--- a/src/Node/Date.php
+++ b/src/Node/Date.php
@@ -17,23 +17,9 @@ final class Date extends Node
const MAX_FUZZY = 5;
*/
- /** @var \DateTimeZone */
- private static $utc;
+ private static ?\DateTimeZone $utc = null;
+ private ComparisonOperator $comparisonOperator;
- /** @var ComparisonOperator */
- private $comparisonOperator;
-
- /**
- * Date constructor.
- *
- * @param string $value
- * @param BoolOperator $boolOperator
- * @param bool $useBoost
- * @param float $boost
- * @param bool $useFuzzy
- * @param int $fuzzy
- * @param ComparisonOperator $comparisonOperator
- */
public function __construct(
string $value,
?BoolOperator $boolOperator = null,
@@ -47,38 +33,30 @@ public function __construct(
$this->comparisonOperator = $comparisonOperator ?: ComparisonOperator::EQ();
}
- /**
- * @param array $data
- *
- * @return self
- */
- public static function fromArray(array $data = [])
+ public static function fromArray(array $data = []): self
{
- $value = isset($data['value']) ? $data['value'] : '';
- $useBoost = isset($data['use_boost']) ? (bool)$data['use_boost'] : false;
- $boost = isset($data['boost']) ? (float)$data['boost'] : self::DEFAULT_BOOST;
- $useFuzzy = isset($data['use_fuzzy']) ? (bool)$data['use_fuzzy'] : false;
- $fuzzy = isset($data['fuzzy']) ? (int)$data['fuzzy'] : self::DEFAULT_FUZZY;
+ $value = $data['value'] ?? '';
+ $useBoost = (bool)($data['use_boost'] ?? false);
+ $boost = (float)($data['boost'] ?? self::DEFAULT_BOOST);
+ $useFuzzy = (bool)($data['use_fuzzy'] ?? false);
+ $fuzzy = (int)($data['fuzzy'] ?? self::DEFAULT_FUZZY);
try {
$boolOperator = isset($data['bool_operator']) ? BoolOperator::create($data['bool_operator']) : null;
- } catch (\Exception $e) {
+ } catch (\Throwable $e) {
$boolOperator = null;
}
try {
$comparisonOperator = isset($data['comparison_operator']) ? ComparisonOperator::create($data['comparison_operator']) : null;
- } catch (\Exception $e) {
+ } catch (\Throwable $e) {
$comparisonOperator = null;
}
return new self($value, $boolOperator, $useBoost, $boost, $useFuzzy, $fuzzy, $comparisonOperator);
}
- /**
- * @return array
- */
- public function toArray()
+ public function toArray(): array
{
$array = parent::toArray();
if ($this->comparisonOperator->equals(ComparisonOperator::EQ())) {
@@ -89,17 +67,11 @@ public function toArray()
return $array;
}
- /**
- * @return bool
- */
public function useComparisonOperator(): bool
{
return !$this->comparisonOperator->equals(ComparisonOperator::EQ());
}
- /**
- * @return ComparisonOperator
- */
public function getComparisonOperator(): ComparisonOperator
{
return $this->comparisonOperator;
@@ -111,16 +83,16 @@ public function getComparisonOperator(): ComparisonOperator
*
* @param \DateTimeZone $timeZone
*
- * @return \DateTime
+ * @return \DateTimeInterface
*/
- public function toDateTime(\DateTimeZone $timeZone = null): \DateTime
+ public function toDateTime(?\DateTimeZone $timeZone = null): \DateTimeInterface
{
if (null === self::$utc) {
self::$utc = new \DateTimeZone('UTC');
}
$date = \DateTime::createFromFormat('!Y-m-d', $this->getValue(), $timeZone ?: self::$utc);
- if (!$date instanceof \DateTime) {
+ if (!$date instanceof \DateTimeInterface) {
$date = \DateTime::createFromFormat('!Y-m-d', (new \DateTime())->format('Y-m-d'), $timeZone ?: self::$utc);
}
@@ -131,9 +103,6 @@ public function toDateTime(\DateTimeZone $timeZone = null): \DateTime
return $date;
}
- /**
- * @param QueryBuilder $builder
- */
public function acceptBuilder(QueryBuilder $builder): void
{
$builder->addDate($this);
diff --git a/src/Node/DateRange.php b/src/Node/DateRange.php
index 6183642..892bdf4 100755
--- a/src/Node/DateRange.php
+++ b/src/Node/DateRange.php
@@ -8,13 +8,6 @@ final class DateRange extends Range
const NODE_TYPE = 'date_range';
const COMPOUND_NODE = true;
- /**
- * DateRange constructor.
- *
- * @param Date $lowerNode
- * @param Date $upperNode
- * @param bool $exclusive
- */
public function __construct(?Date $lowerNode = null, ?Date $upperNode = null, bool $exclusive = false)
{
parent::__construct($lowerNode, $upperNode, $exclusive);
diff --git a/src/Node/Emoji.php b/src/Node/Emoji.php
index 3efb280..918e97e 100755
--- a/src/Node/Emoji.php
+++ b/src/Node/Emoji.php
@@ -10,14 +10,6 @@ final class Emoji extends Node
{
const NODE_TYPE = 'emoji';
- /**
- * Emoji constructor.
- *
- * @param string $value
- * @param BoolOperator $boolOperator
- * @param bool $useBoost
- * @param float $boost
- */
public function __construct(
string $value,
?BoolOperator $boolOperator = null,
@@ -27,29 +19,21 @@ public function __construct(
parent::__construct($value, $boolOperator, $useBoost, $boost);
}
- /**
- * @param array $data
- *
- * @return self
- */
- public static function fromArray(array $data = [])
+ public static function fromArray(array $data = []): self
{
- $value = isset($data['value']) ? $data['value'] : '';
- $useBoost = isset($data['use_boost']) ? (bool)$data['use_boost'] : false;
- $boost = isset($data['boost']) ? (float)$data['boost'] : self::DEFAULT_BOOST;
+ $value = $data['value'] ?? '';
+ $useBoost = (bool)($data['use_boost'] ?? false);
+ $boost = (float)($data['boost'] ?? self::DEFAULT_BOOST);
try {
$boolOperator = isset($data['bool_operator']) ? BoolOperator::create($data['bool_operator']) : null;
- } catch (\Exception $e) {
+ } catch (\Throwable $e) {
$boolOperator = null;
}
return new self($value, $boolOperator, $useBoost, $boost);
}
- /**
- * @param QueryBuilder $builder
- */
public function acceptBuilder(QueryBuilder $builder): void
{
$builder->addEmoji($this);
diff --git a/src/Node/Emoticon.php b/src/Node/Emoticon.php
index 767c17c..5c84ca2 100755
--- a/src/Node/Emoticon.php
+++ b/src/Node/Emoticon.php
@@ -10,14 +10,6 @@ final class Emoticon extends Node
{
const NODE_TYPE = 'emoticon';
- /**
- * Emoticon constructor.
- *
- * @param string $value
- * @param BoolOperator $boolOperator
- * @param bool $useBoost
- * @param float $boost
- */
public function __construct(
string $value,
?BoolOperator $boolOperator = null,
@@ -27,29 +19,21 @@ public function __construct(
parent::__construct($value, $boolOperator, $useBoost, $boost);
}
- /**
- * @param array $data
- *
- * @return self
- */
- public static function fromArray(array $data = [])
+ public static function fromArray(array $data = []): self
{
- $value = isset($data['value']) ? $data['value'] : '';
- $useBoost = isset($data['use_boost']) ? (bool)$data['use_boost'] : false;
- $boost = isset($data['boost']) ? (float)$data['boost'] : self::DEFAULT_BOOST;
+ $value = $data['value'] ?? '';
+ $useBoost = (bool)($data['use_boost'] ?? false);
+ $boost = (float)($data['boost'] ?? self::DEFAULT_BOOST);
try {
$boolOperator = isset($data['bool_operator']) ? BoolOperator::create($data['bool_operator']) : null;
- } catch (\Exception $e) {
+ } catch (\Throwable $e) {
$boolOperator = null;
}
return new self($value, $boolOperator, $useBoost, $boost);
}
- /**
- * @param QueryBuilder $builder
- */
public function acceptBuilder(QueryBuilder $builder): void
{
$builder->addEmoticon($this);
diff --git a/src/Node/Field.php b/src/Node/Field.php
index 7b3da4d..b15476d 100755
--- a/src/Node/Field.php
+++ b/src/Node/Field.php
@@ -17,22 +17,9 @@ final class Field extends Node
*
* @var array
*/
- public static $aliases = [];
+ public static array $aliases = [];
+ private Node $node;
- /** @var Node */
- private $node;
-
- /**
- * Field constructor.
- *
- * @param string $fieldName
- * @param Node $node
- * @param BoolOperator $boolOperator
- * @param bool $useBoost
- * @param float $boost
- *
- * @throws \LogicException
- */
public function __construct(
string $fieldName,
Node $node,
@@ -52,20 +39,15 @@ public function __construct(
}
}
- /**
- * @param array $data
- *
- * @return static
- */
- public static function fromArray(array $data = [])
+ public static function fromArray(array $data = []): self
{
- $value = isset($data['value']) ? $data['value'] : '';
- $useBoost = isset($data['use_boost']) ? (bool)$data['use_boost'] : false;
- $boost = isset($data['boost']) ? (float)$data['boost'] : self::DEFAULT_BOOST;
+ $value = $data['value'] ?? '';
+ $useBoost = (bool)($data['use_boost'] ?? false);
+ $boost = (float)($data['boost'] ?? self::DEFAULT_BOOST);
try {
$boolOperator = isset($data['bool_operator']) ? BoolOperator::create($data['bool_operator']) : null;
- } catch (\Exception $e) {
+ } catch (\Throwable $e) {
$boolOperator = null;
}
@@ -75,45 +57,28 @@ public static function fromArray(array $data = [])
return new self($value, $node, $boolOperator, $useBoost, $boost);
}
- /**
- * @return array
- */
- public function toArray()
+ public function toArray(): array
{
$array = parent::toArray();
$array['node'] = $this->node->toArray();
return $array;
}
- /**
- * @return string
- */
public function getName(): string
{
- /** @var string $name */
- $name = $this->getValue();
- return $name;
+ return $this->getValue();
}
- /**
- * @return Node
- */
public function getNode(): Node
{
return $this->node;
}
- /**
- * @return bool
- */
public function hasCompoundNode(): bool
{
return $this->node->isCompoundNode();
}
- /**
- * @param QueryBuilder $builder
- */
public function acceptBuilder(QueryBuilder $builder): void
{
$builder->addField($this);
diff --git a/src/Node/Hashtag.php b/src/Node/Hashtag.php
index 4ebfd76..23c5192 100755
--- a/src/Node/Hashtag.php
+++ b/src/Node/Hashtag.php
@@ -10,14 +10,6 @@ final class Hashtag extends Node
{
const NODE_TYPE = 'hashtag';
- /**
- * Hashtag constructor.
- *
- * @param string $value
- * @param BoolOperator $boolOperator
- * @param bool $useBoost
- * @param float $boost
- */
public function __construct(
string $value,
?BoolOperator $boolOperator = null,
@@ -27,29 +19,21 @@ public function __construct(
parent::__construct($value, $boolOperator, $useBoost, $boost);
}
- /**
- * @param array $data
- *
- * @return self
- */
- public static function fromArray(array $data = [])
+ public static function fromArray(array $data = []): self
{
- $value = isset($data['value']) ? $data['value'] : '';
- $useBoost = isset($data['use_boost']) ? (bool)$data['use_boost'] : false;
- $boost = isset($data['boost']) ? (float)$data['boost'] : self::DEFAULT_BOOST;
+ $value = $data['value'] ?? '';
+ $useBoost = (bool)($data['use_boost'] ?? false);
+ $boost = (float)($data['boost'] ?? self::DEFAULT_BOOST);
try {
$boolOperator = isset($data['bool_operator']) ? BoolOperator::create($data['bool_operator']) : null;
- } catch (\Exception $e) {
+ } catch (\Throwable $e) {
$boolOperator = null;
}
return new self($value, $boolOperator, $useBoost, $boost);
}
- /**
- * @param QueryBuilder $builder
- */
public function acceptBuilder(QueryBuilder $builder): void
{
$builder->addHashtag($this);
diff --git a/src/Node/Mention.php b/src/Node/Mention.php
index 8b35a58..82b5cda 100755
--- a/src/Node/Mention.php
+++ b/src/Node/Mention.php
@@ -10,14 +10,6 @@ final class Mention extends Node
{
const NODE_TYPE = 'mention';
- /**
- * Mention constructor.
- *
- * @param string $value
- * @param BoolOperator $boolOperator
- * @param bool $useBoost
- * @param float $boost
- */
public function __construct(
string $value,
?BoolOperator $boolOperator = null,
@@ -27,29 +19,21 @@ public function __construct(
parent::__construct($value, $boolOperator, $useBoost, $boost);
}
- /**
- * @param array $data
- *
- * @return self
- */
- public static function fromArray(array $data = [])
+ public static function fromArray(array $data = []): self
{
- $value = isset($data['value']) ? $data['value'] : '';
- $useBoost = isset($data['use_boost']) ? (bool)$data['use_boost'] : false;
- $boost = isset($data['boost']) ? (float)$data['boost'] : self::DEFAULT_BOOST;
+ $value = $data['value'] ?? '';
+ $useBoost = (bool)($data['use_boost'] ?? false);
+ $boost = (float)($data['boost'] ?? self::DEFAULT_BOOST);
try {
$boolOperator = isset($data['bool_operator']) ? BoolOperator::create($data['bool_operator']) : null;
- } catch (\Exception $e) {
+ } catch (\Throwable $e) {
$boolOperator = null;
}
return new self($value, $boolOperator, $useBoost, $boost);
}
- /**
- * @param QueryBuilder $builder
- */
public function acceptBuilder(QueryBuilder $builder): void
{
$builder->addMention($this);
diff --git a/src/Node/Node.php b/src/Node/Node.php
index e99c0e9..b14595b 100755
--- a/src/Node/Node.php
+++ b/src/Node/Node.php
@@ -3,14 +3,10 @@
namespace Gdbots\QueryParser\Node;
-use Gdbots\Common\FromArray;
-use Gdbots\Common\ToArray;
-use Gdbots\Common\Util\NumberUtils;
-use Gdbots\Common\Util\StringUtils;
use Gdbots\QueryParser\Builder\QueryBuilder;
use Gdbots\QueryParser\Enum\BoolOperator;
-abstract class Node implements FromArray, ToArray, \JsonSerializable
+abstract class Node implements \JsonSerializable
{
const NODE_TYPE = 'node';
const COMPOUND_NODE = false;
@@ -30,31 +26,12 @@ abstract class Node implements FromArray, ToArray, \JsonSerializable
/** @var mixed */
private $value = null;
- /** @var BoolOperator */
- private $boolOperator;
+ private BoolOperator $boolOperator;
+ private bool $useBoost = false;
+ private float $boost = self::DEFAULT_BOOST;
+ private bool $useFuzzy = false;
+ private int $fuzzy = self::DEFAULT_FUZZY;
- /** @var bool */
- private $useBoost = false;
-
- /** @var float */
- private $boost = self::DEFAULT_BOOST;
-
- /** @var bool */
- private $useFuzzy = false;
-
- /** @var int */
- private $fuzzy = self::DEFAULT_FUZZY;
-
- /**
- * Node constructor.
- *
- * @param mixed $value
- * @param BoolOperator $boolOperator
- * @param bool $useBoost
- * @param float $boost
- * @param bool $useFuzzy
- * @param int $fuzzy
- */
public function __construct(
$value,
?BoolOperator $boolOperator = null,
@@ -80,16 +57,10 @@ public function __construct(
$this->useFuzzy = $useFuzzy && static::SUPPORTS_FUZZY && $this->boolOperator === BoolOperator::OPTIONAL();
if ($this->useFuzzy) {
- $this->fuzzy = NumberUtils::bound($fuzzy, static::MIN_FUZZY, static::MAX_FUZZY);
+ $this->fuzzy = min(max($fuzzy, static::MIN_FUZZY), static::MAX_FUZZY);
}
}
- /**
- * @param array $data
- *
- * @return static
- * @throws \InvalidArgumentException
- */
public static function factory(array $data = []): self
{
$type = $data['type'];
@@ -99,7 +70,8 @@ public static function factory(array $data = []): self
}
/** @var Node $class */
- $class = 'Gdbots\QueryParser\Node\\' . StringUtils::toCamelFromSnake($type);
+ $camel = str_replace(' ', '', ucwords(str_replace('_', ' ', $type)));
+ $class = 'Gdbots\QueryParser\Node\\' . $camel;
if (!class_exists($class)) {
throw new \InvalidArgumentException(sprintf('Node type [%s] does not exist.', $type));
}
@@ -107,10 +79,7 @@ public static function factory(array $data = []): self
return $class::fromArray($data);
}
- /**
- * @return array
- */
- public function toArray()
+ public function toArray(): array
{
$array = ['type' => static::NODE_TYPE];
@@ -135,113 +104,71 @@ public function toArray()
return $array;
}
- /**
- * @return array
- */
final public function jsonSerialize()
{
return $this->toArray();
}
- /**
- * @return bool
- */
final public function hasValue(): bool
{
return null !== $this->value && '' !== $this->value;
}
- /**
- * @return mixed
- */
final public function getValue()
{
return $this->value;
}
- /**
- * @return BoolOperator
- */
final public function getBoolOperator(): BoolOperator
{
return $this->boolOperator;
}
- /**
- * @return bool
- */
final public function isOptional(): bool
{
return $this->boolOperator->equals(BoolOperator::OPTIONAL());
}
- /**
- * @return bool
- */
final public function isRequired(): bool
{
return $this->boolOperator->equals(BoolOperator::REQUIRED());
}
- /**
- * @return bool
- */
final public function isProhibited(): bool
{
return $this->boolOperator->equals(BoolOperator::PROHIBITED());
}
- /**
- * @return bool
- */
final public function isCompoundNode(): bool
{
return static::COMPOUND_NODE;
}
- /**
- * @return bool
- */
public function useComparisonOperator(): bool
{
return false;
}
- /**
- * @return bool
- */
final public function useBoost(): bool
{
return $this->useBoost;
}
- /**
- * @return float
- */
final public function getBoost(): float
{
return $this->boost;
}
- /**
- * @return bool
- */
final public function useFuzzy(): bool
{
return $this->useFuzzy;
}
- /**
- * @return int
- */
final public function getFuzzy(): int
{
return $this->fuzzy;
}
- /**
- * @param QueryBuilder $builder
- */
public function acceptBuilder(QueryBuilder $builder): void
{
// do nothing
diff --git a/src/Node/NumberRange.php b/src/Node/NumberRange.php
index c4543c2..48e238a 100755
--- a/src/Node/NumberRange.php
+++ b/src/Node/NumberRange.php
@@ -8,13 +8,6 @@ final class NumberRange extends Range
const NODE_TYPE = 'number_range';
const COMPOUND_NODE = true;
- /**
- * NumberRange constructor.
- *
- * @param Numbr $lowerNode
- * @param Numbr $upperNode
- * @param bool $exclusive
- */
public function __construct(?Numbr $lowerNode = null, ?Numbr $upperNode = null, bool $exclusive = false)
{
parent::__construct($lowerNode, $upperNode, $exclusive);
diff --git a/src/Node/Numbr.php b/src/Node/Numbr.php
index 5c5fe52..2c37df9 100755
--- a/src/Node/Numbr.php
+++ b/src/Node/Numbr.php
@@ -12,44 +12,28 @@
final class Numbr extends Node
{
const NODE_TYPE = 'number';
+ private ComparisonOperator $comparisonOperator;
- /** @var ComparisonOperator */
- private $comparisonOperator;
-
- /**
- * Numbr constructor.
- *
- * @param float $value
- * @param ComparisonOperator $comparisonOperator
- */
public function __construct(float $value, ?ComparisonOperator $comparisonOperator = null)
{
parent::__construct($value, null);
$this->comparisonOperator = $comparisonOperator ?: ComparisonOperator::EQ();
}
- /**
- * @param array $data
- *
- * @return self
- */
- public static function fromArray(array $data = [])
+ public static function fromArray(array $data = []): self
{
- $value = isset($data['value']) ? (float)$data['value'] : 0.0;
+ $value = (float)($data['value'] ?? 0.0);
try {
$comparisonOperator = isset($data['comparison_operator']) ? ComparisonOperator::create($data['comparison_operator']) : null;
- } catch (\Exception $e) {
+ } catch (\Throwable $e) {
$comparisonOperator = null;
}
return new self($value, $comparisonOperator);
}
- /**
- * @return array
- */
- public function toArray()
+ public function toArray(): array
{
$array = parent::toArray();
if ($this->comparisonOperator->equals(ComparisonOperator::EQ())) {
@@ -60,25 +44,16 @@ public function toArray()
return $array;
}
- /**
- * @return bool
- */
public function useComparisonOperator(): bool
{
return !$this->comparisonOperator->equals(ComparisonOperator::EQ());
}
- /**
- * @return ComparisonOperator
- */
public function getComparisonOperator(): ComparisonOperator
{
return $this->comparisonOperator;
}
- /**
- * @param QueryBuilder $builder
- */
public function acceptBuilder(QueryBuilder $builder): void
{
$builder->addNumber($this);
diff --git a/src/Node/Phrase.php b/src/Node/Phrase.php
index d7620e7..c836691 100755
--- a/src/Node/Phrase.php
+++ b/src/Node/Phrase.php
@@ -11,16 +11,6 @@ final class Phrase extends Node
const NODE_TYPE = 'phrase';
const SUPPORTS_FUZZY = true;
- /**
- * Phrase constructor.
- *
- * @param string $value
- * @param BoolOperator $boolOperator
- * @param bool $useBoost
- * @param float $boost
- * @param bool $useFuzzy
- * @param int $fuzzy
- */
public function __construct(
string $value,
?BoolOperator $boolOperator = null,
@@ -32,31 +22,23 @@ public function __construct(
parent::__construct($value, $boolOperator, $useBoost, $boost, $useFuzzy, $fuzzy);
}
- /**
- * @param array $data
- *
- * @return static
- */
- public static function fromArray(array $data = [])
+ public static function fromArray(array $data = []): self
{
- $value = isset($data['value']) ? $data['value'] : '';
- $useBoost = isset($data['use_boost']) ? (bool)$data['use_boost'] : false;
- $boost = isset($data['boost']) ? (float)$data['boost'] : static::DEFAULT_BOOST;
- $useFuzzy = isset($data['use_fuzzy']) ? (bool)$data['use_fuzzy'] : false;
- $fuzzy = isset($data['fuzzy']) ? (int)$data['fuzzy'] : static::DEFAULT_FUZZY;
+ $value = $data['value'] ?? '';
+ $useBoost = (bool)($data['use_boost'] ?? false);
+ $boost = (float)($data['boost'] ?? self::DEFAULT_BOOST);
+ $useFuzzy = (bool)($data['use_fuzzy'] ?? false);
+ $fuzzy = (int)($data['fuzzy'] ?? self::DEFAULT_FUZZY);
try {
$boolOperator = isset($data['bool_operator']) ? BoolOperator::create($data['bool_operator']) : null;
- } catch (\Exception $e) {
+ } catch (\Throwable $e) {
$boolOperator = null;
}
return new self($value, $boolOperator, $useBoost, $boost, $useFuzzy, $fuzzy);
}
- /**
- * @param QueryBuilder $builder
- */
public function acceptBuilder(QueryBuilder $builder): void
{
$builder->addPhrase($this);
diff --git a/src/Node/Range.php b/src/Node/Range.php
index b9964f0..b7d34b1 100755
--- a/src/Node/Range.php
+++ b/src/Node/Range.php
@@ -10,24 +10,10 @@ abstract class Range extends Node
const SUPPORTS_BOOST = false;
const COMPOUND_NODE = true;
- /** @var Node */
- private $lowerNode;
-
- /** @var Node */
- private $upperNode;
-
- /** @var bool */
- private $exclusive = false;
-
- /**
- * Range constructor.
- *
- * @param Node $lowerNode
- * @param Node $upperNode
- * @param bool $exclusive
- *
- * @throws \LogicException
- */
+ private ?Node $lowerNode = null;
+ private ?Node $upperNode = null;
+ private bool $exclusive = false;
+
public function __construct(?Node $lowerNode = null, ?Node $upperNode = null, bool $exclusive = false)
{
parent::__construct(null);
@@ -40,12 +26,7 @@ public function __construct(?Node $lowerNode = null, ?Node $upperNode = null, bo
}
}
- /**
- * @param array $data
- *
- * @return self
- */
- final public static function fromArray(array $data = [])
+ final public static function fromArray(array $data = []): self
{
$lowerNode = isset($data['lower_node']) ? self::factory($data['lower_node']) : null;
$upperNode = isset($data['upper_node']) ? self::factory($data['upper_node']) : null;
@@ -53,10 +34,7 @@ final public static function fromArray(array $data = [])
return new static($lowerNode, $upperNode, $exclusive);
}
- /**
- * @return array
- */
- final public function toArray()
+ final public function toArray(): array
{
$array = parent::toArray();
@@ -75,57 +53,36 @@ final public function toArray()
return $array;
}
- /**
- * @return bool
- */
final public function hasLowerNode(): bool
{
return null !== $this->lowerNode;
}
- /**
- * @return Node
- */
public function getLowerNode(): ?Node
{
return $this->lowerNode;
}
- /**
- * @return bool
- */
final public function hasUpperNode(): bool
{
return null !== $this->upperNode;
}
- /**
- * @return Node
- */
public function getUpperNode(): ?Node
{
return $this->upperNode;
}
- /**
- * @return bool
- */
final public function isInclusive(): bool
{
return !$this->exclusive;
}
- /**
- * @return bool
- */
final public function isExclusive(): bool
{
return $this->exclusive;
}
- /**
- * @param QueryBuilder $builder
- */
final public function acceptBuilder(QueryBuilder $builder): void
{
$builder->addRange($this);
diff --git a/src/Node/Subquery.php b/src/Node/Subquery.php
index ef48c95..16e212a 100755
--- a/src/Node/Subquery.php
+++ b/src/Node/Subquery.php
@@ -12,18 +12,8 @@ final class Subquery extends Node
const COMPOUND_NODE = true;
/** @var Node[] */
- private $nodes = [];
+ private array $nodes = [];
- /**
- * Subquery constructor.
- *
- * @param Node[] $nodes
- * @param BoolOperator $boolOperator
- * @param bool $useBoost
- * @param float $boost
- *
- * @throws \LogicException
- */
public function __construct(
array $nodes,
?BoolOperator $boolOperator = null,
@@ -40,15 +30,10 @@ public function __construct(
}
}
- /**
- * @param array $data
- *
- * @return self
- */
- public static function fromArray(array $data = [])
+ public static function fromArray(array $data = []): self
{
- $useBoost = isset($data['use_boost']) ? (bool)$data['use_boost'] : false;
- $boost = isset($data['boost']) ? (float)$data['boost'] : self::DEFAULT_BOOST;
+ $useBoost = (bool)($data['use_boost'] ?? false);
+ $boost = (float)($data['boost'] ?? self::DEFAULT_BOOST);
$nodes = [];
if (isset($data['nodes'])) {
@@ -59,17 +44,14 @@ public static function fromArray(array $data = [])
try {
$boolOperator = isset($data['bool_operator']) ? BoolOperator::create($data['bool_operator']) : null;
- } catch (\Exception $e) {
+ } catch (\Throwable $e) {
$boolOperator = null;
}
return new self($nodes, $boolOperator, $useBoost, $boost);
}
- /**
- * @return array
- */
- public function toArray()
+ public function toArray(): array
{
$array = parent::toArray();
$array['nodes'] = [];
@@ -89,9 +71,6 @@ public function getNodes(): array
return $this->nodes;
}
- /**
- * @param QueryBuilder $builder
- */
public function acceptBuilder(QueryBuilder $builder): void
{
$builder->addSubquery($this);
diff --git a/src/Node/Url.php b/src/Node/Url.php
index e31ee6f..574e50c 100755
--- a/src/Node/Url.php
+++ b/src/Node/Url.php
@@ -10,14 +10,6 @@ final class Url extends Node
{
const NODE_TYPE = 'url';
- /**
- * Url constructor.
- *
- * @param string $value
- * @param BoolOperator $boolOperator
- * @param bool $useBoost
- * @param float $boost
- */
public function __construct(
string $value,
?BoolOperator $boolOperator = null,
@@ -27,29 +19,21 @@ public function __construct(
parent::__construct($value, $boolOperator, $useBoost, $boost);
}
- /**
- * @param array $data
- *
- * @return self
- */
- public static function fromArray(array $data = [])
+ public static function fromArray(array $data = []): self
{
- $value = isset($data['value']) ? $data['value'] : '';
- $useBoost = isset($data['use_boost']) ? (bool)$data['use_boost'] : false;
- $boost = isset($data['boost']) ? (float)$data['boost'] : self::DEFAULT_BOOST;
+ $value = $data['value'] ?? '';
+ $useBoost = (bool)($data['use_boost'] ?? false);
+ $boost = (float)($data['boost'] ?? self::DEFAULT_BOOST);
try {
$boolOperator = isset($data['bool_operator']) ? BoolOperator::create($data['bool_operator']) : null;
- } catch (\Exception $e) {
+ } catch (\Throwable $e) {
$boolOperator = null;
}
return new self($value, $boolOperator, $useBoost, $boost);
}
- /**
- * @param QueryBuilder $builder
- */
public function acceptBuilder(QueryBuilder $builder): void
{
$builder->addUrl($this);
diff --git a/src/Node/Word.php b/src/Node/Word.php
index 3df27c4..f17c771 100755
--- a/src/Node/Word.php
+++ b/src/Node/Word.php
@@ -11,27 +11,14 @@ final class Word extends Node
const NODE_TYPE = 'word';
const SUPPORTS_FUZZY = true;
- /** @var array */
- public static $stopWords = [
+ public static array $stopWords = [
'a', 'an', 'and', 'are', 'as', 'at', 'be', 'but', 'by', 'for', 'if', 'in', 'into', 'is',
'it', 'no', 'not', 'of', 'on', 'or', 'such', 'that', 'the', 'their', 'then', 'there',
'these', 'they', 'this', 'to', 'was', 'will', 'with',
];
- /** @var bool */
- private $trailingWildcard = false;
+ private bool $trailingWildcard = false;
- /**
- * Word constructor.
- *
- * @param string $value
- * @param BoolOperator $boolOperator
- * @param bool $useBoost
- * @param float $boost
- * @param bool $useFuzzy
- * @param int $fuzzy
- * @param bool $trailingWildcard
- */
public function __construct(
string $value,
?BoolOperator $boolOperator = null,
@@ -45,33 +32,25 @@ public function __construct(
$this->trailingWildcard = $trailingWildcard;
}
- /**
- * @param array $data
- *
- * @return self
- */
- public static function fromArray(array $data = [])
+ public static function fromArray(array $data = []): self
{
- $value = isset($data['value']) ? $data['value'] : '';
- $useBoost = isset($data['use_boost']) ? (bool)$data['use_boost'] : false;
- $boost = isset($data['boost']) ? (float)$data['boost'] : self::DEFAULT_BOOST;
- $useFuzzy = isset($data['use_fuzzy']) ? (bool)$data['use_fuzzy'] : false;
- $fuzzy = isset($data['fuzzy']) ? (int)$data['fuzzy'] : self::DEFAULT_FUZZY;
- $trailingWildcard = isset($data['trailing_wildcard']) ? (bool)$data['trailing_wildcard'] : false;
+ $value = $data['value'] ?? '';
+ $useBoost = (bool)($data['use_boost'] ?? false);
+ $boost = (float)($data['boost'] ?? self::DEFAULT_BOOST);
+ $useFuzzy = (bool)($data['use_fuzzy'] ?? false);
+ $fuzzy = (int)($data['fuzzy'] ?? self::DEFAULT_FUZZY);
+ $trailingWildcard = (bool)($data['trailing_wildcard'] ?? false);
try {
$boolOperator = isset($data['bool_operator']) ? BoolOperator::create($data['bool_operator']) : null;
- } catch (\Exception $e) {
+ } catch (\Throwable $e) {
$boolOperator = null;
}
return new self($value, $boolOperator, $useBoost, $boost, $useFuzzy, $fuzzy, $trailingWildcard);
}
- /**
- * @return array
- */
- public function toArray()
+ public function toArray(): array
{
$array = parent::toArray();
if (!$this->trailingWildcard) {
@@ -82,25 +61,16 @@ public function toArray()
return $array;
}
- /**
- * @return bool
- */
public function hasTrailingWildcard(): bool
{
return $this->trailingWildcard;
}
- /**
- * @return bool
- */
public function isStopWord(): bool
{
return in_array(strtolower($this->getValue()), self::$stopWords);
}
- /**
- * @param QueryBuilder $builder
- */
public function acceptBuilder(QueryBuilder $builder): void
{
$builder->addWord($this);
diff --git a/src/Node/WordRange.php b/src/Node/WordRange.php
index 5d25cd9..c7afa42 100755
--- a/src/Node/WordRange.php
+++ b/src/Node/WordRange.php
@@ -8,13 +8,6 @@ final class WordRange extends Range
const NODE_TYPE = 'word_range';
const COMPOUND_NODE = true;
- /**
- * WordRange constructor.
- *
- * @param Word $lowerNode
- * @param Word $upperNode
- * @param bool $exclusive
- */
public function __construct(?Word $lowerNode = null, ?Word $upperNode = null, bool $exclusive = false)
{
parent::__construct($lowerNode, $upperNode, $exclusive);
diff --git a/src/ParsedQuery.php b/src/ParsedQuery.php
index 3bf3601..9652307 100755
--- a/src/ParsedQuery.php
+++ b/src/ParsedQuery.php
@@ -3,25 +3,15 @@
namespace Gdbots\QueryParser;
-use Gdbots\Common\FromArray;
-use Gdbots\Common\ToArray;
use Gdbots\QueryParser\Node\Field;
use Gdbots\QueryParser\Node\Node;
-class ParsedQuery implements FromArray, ToArray, \JsonSerializable
+final class ParsedQuery implements \JsonSerializable
{
- /** @var Node[] */
- private $nodes = [];
+ private array $nodes = [];
+ private array $nodesByType = [];
- /** @var array */
- private $nodesByType = [];
-
- /**
- * @param array $data
- *
- * @return static
- */
- public static function fromArray(array $data = [])
+ public static function fromArray(array $data = []): self
{
$obj = new static();
@@ -32,17 +22,11 @@ public static function fromArray(array $data = [])
return $obj;
}
- /**
- * @return array
- */
- public function toArray()
+ public function toArray(): array
{
return $this->nodes;
}
- /**
- * @return array
- */
public function jsonSerialize()
{
return $this->toArray();
@@ -51,7 +35,7 @@ public function jsonSerialize()
/**
* @param Node[] $nodes
*
- * @return static
+ * @return self
*/
public function addNodes(array $nodes): self
{
@@ -65,7 +49,7 @@ public function addNodes(array $nodes): self
/**
* @param Node $node
*
- * @return static
+ * @return self
*/
public function addNode(Node $node): self
{
@@ -114,7 +98,7 @@ public function hasAMatchableNode(): bool
* Returns an array of fields (specifically the field names) that are
* used in this query. e.g. "status:active", "status" is the field name.
*
- * @return array
+ * @return string[]
*/
public function getFieldsUsed(): array
{
diff --git a/src/QueryParser.php b/src/QueryParser.php
index 538fb5c..d5f9af9 100755
--- a/src/QueryParser.php
+++ b/src/QueryParser.php
@@ -25,16 +25,10 @@
* Parses a query and returns a ParsedQuery object with a set of
* nodes per type, i.e. words, phrases, hashtags, etc.
*/
-class QueryParser
+final class QueryParser
{
- /** @var Tokenizer */
- protected $tokenizer;
-
- /** @var TokenStream */
- protected $stream;
-
- /** @var ParsedQuery */
- protected $query;
+ private Tokenizer $tokenizer;
+ private TokenStream $stream;
/**
* Constructs a new QueryParser.
@@ -44,15 +38,10 @@ public function __construct()
$this->tokenizer = new Tokenizer();
}
- /**
- * @param string $input
- *
- * @return ParsedQuery
- */
public function parse(string $input): ParsedQuery
{
$this->stream = $this->tokenizer->scan($input);
- $this->query = new ParsedQuery();
+ $query = new ParsedQuery();
while ($this->stream->next()) {
$boolOperator = $this->getBoolOperator();
@@ -61,10 +50,10 @@ public function parse(string $input): ParsedQuery
break;
}
- $this->query->addNodes($this->createNodes($token, $boolOperator));
+ $query->addNodes($this->createNodes($token, $boolOperator));
}
- return $this->query;
+ return $query;
}
/**
@@ -74,7 +63,7 @@ public function parse(string $input): ParsedQuery
*
* @return Node[]
*/
- protected function createNodes(
+ private function createNodes(
Token $token,
BoolOperator $boolOperator,
?ComparisonOperator $comparisonOperator = null
@@ -138,7 +127,7 @@ protected function createNodes(
*
* @return Field|Node[]|Node
*/
- protected function handleField(string $fieldName, BoolOperator $boolOperator)
+ private function handleField(string $fieldName, BoolOperator $boolOperator)
{
$lookahead = $this->stream->getLookahead();
if (!$lookahead instanceof Token) {
@@ -193,7 +182,7 @@ protected function handleField(string $fieldName, BoolOperator $boolOperator)
*
* @return Field|Node[]|Node
*/
- protected function handleFieldWithRange(string $fieldName, BoolOperator $boolOperator)
+ private function handleFieldWithRange(string $fieldName, BoolOperator $boolOperator)
{
$exclusive = $this->stream->typeIs(Token::T_RANGE_EXCL_START);
$matchTypes = true;
@@ -291,7 +280,7 @@ protected function handleFieldWithRange(string $fieldName, BoolOperator $boolOpe
*
* @return Field|Node
*/
- protected function handleFieldWithSubquery(string $fieldName, BoolOperator $boolOperator): Node
+ private function handleFieldWithSubquery(string $fieldName, BoolOperator $boolOperator): Node
{
$this->stream->nextIf(Token::T_SUBQUERY_START);
$subquery = $this->handleSubquery($boolOperator);
@@ -315,7 +304,7 @@ protected function handleFieldWithSubquery(string $fieldName, BoolOperator $bool
*
* @return Subquery|Node[]|Node
*/
- protected function handleSubquery(BoolOperator $queryBoolOperator)
+ private function handleSubquery(BoolOperator $queryBoolOperator)
{
$this->stream->nextIf(Token::T_SUBQUERY_START);
/** @var Node[] $nodes */
@@ -378,14 +367,7 @@ protected function handleSubquery(BoolOperator $queryBoolOperator)
return new Subquery($nodes, $queryBoolOperator, $m['use_boost'], $m['boost']);
}
- /**
- * @param string $value
- * @param BoolOperator $boolOperator
- * @param ComparisonOperator $comparisonOperator
- *
- * @return Date
- */
- protected function createDate(
+ private function createDate(
string $value,
BoolOperator $boolOperator,
?ComparisonOperator $comparisonOperator = null
@@ -402,102 +384,54 @@ protected function createDate(
);
}
- /**
- * @param string $value
- * @param BoolOperator $boolOperator
- *
- * @return Emoji
- */
- protected function createEmoji(string $value, BoolOperator $boolOperator): Emoji
+ private function createEmoji(string $value, BoolOperator $boolOperator): Emoji
{
$boolOperator = $boolOperator->equals(BoolOperator::OPTIONAL()) ? BoolOperator::REQUIRED() : $boolOperator;
$m = $this->getModifiers();
return new Emoji($value, $boolOperator, $m['use_boost'], $m['boost']);
}
- /**
- * @param string $value
- * @param BoolOperator $boolOperator
- *
- * @return Emoticon
- */
- protected function createEmoticon(string $value, BoolOperator $boolOperator): Emoticon
+ private function createEmoticon(string $value, BoolOperator $boolOperator): Emoticon
{
$boolOperator = $boolOperator->equals(BoolOperator::OPTIONAL()) ? BoolOperator::REQUIRED() : $boolOperator;
$m = $this->getModifiers();
return new Emoticon($value, $boolOperator, $m['use_boost'], $m['boost']);
}
- /**
- * @param string $value
- * @param BoolOperator $boolOperator
- *
- * @return Hashtag
- */
- protected function createHashtag(string $value, BoolOperator $boolOperator): Hashtag
+ private function createHashtag(string $value, BoolOperator $boolOperator): Hashtag
{
$boolOperator = $boolOperator->equals(BoolOperator::OPTIONAL()) ? BoolOperator::REQUIRED() : $boolOperator;
$m = $this->getModifiers();
return new Hashtag($value, $boolOperator, $m['use_boost'], $m['boost']);
}
- /**
- * @param string $value
- * @param BoolOperator $boolOperator
- *
- * @return Mention
- */
- protected function createMention(string $value, BoolOperator $boolOperator): Mention
+ private function createMention(string $value, BoolOperator $boolOperator): Mention
{
$boolOperator = $boolOperator->equals(BoolOperator::OPTIONAL()) ? BoolOperator::REQUIRED() : $boolOperator;
$m = $this->getModifiers();
return new Mention($value, $boolOperator, $m['use_boost'], $m['boost']);
}
- /**
- * @param float $value
- * @param ComparisonOperator $comparisonOperator
- *
- * @return Numbr
- */
- protected function createNumber(float $value, ?ComparisonOperator $comparisonOperator = null): Numbr
+ private function createNumber(float $value, ?ComparisonOperator $comparisonOperator = null): Numbr
{
// move the stream and ignore them if they exist
$this->getModifiers();
return new Numbr($value, $comparisonOperator);
}
- /**
- * @param string $value
- * @param BoolOperator $boolOperator
- *
- * @return Phrase
- */
- protected function createPhrase(string $value, BoolOperator $boolOperator): Phrase
+ private function createPhrase(string $value, BoolOperator $boolOperator): Phrase
{
$m = $this->getModifiers();
return new Phrase($value, $boolOperator, $m['use_boost'], $m['boost'], $m['use_fuzzy'], $m['fuzzy']);
}
- /**
- * @param string $value
- * @param BoolOperator $boolOperator
- *
- * @return Url
- */
- protected function createUrl(string $value, BoolOperator $boolOperator): Url
+ private function createUrl(string $value, BoolOperator $boolOperator): Url
{
$m = $this->getModifiers();
return new Url($value, $boolOperator, $m['use_boost'], $m['boost']);
}
- /**
- * @param string $value
- * @param BoolOperator $boolOperator
- *
- * @return Word
- */
- protected function createWord(string $value, BoolOperator $boolOperator): Word
+ private function createWord(string $value, BoolOperator $boolOperator): Word
{
$m = $this->getModifiers();
return new Word(
@@ -511,12 +445,7 @@ protected function createWord(string $value, BoolOperator $boolOperator): Word
);
}
- /**
- * @param int $default
- *
- * @return BoolOperator
- */
- protected function getBoolOperator(int $default = BoolOperator::OPTIONAL): BoolOperator
+ private function getBoolOperator(int $default = BoolOperator::OPTIONAL): BoolOperator
{
if ($this->stream->nextIf(Token::T_REQUIRED)
|| $this->stream->lookaheadTypeIs(Token::T_AND)
@@ -532,10 +461,7 @@ protected function getBoolOperator(int $default = BoolOperator::OPTIONAL): BoolO
return BoolOperator::create($default);
}
- /**
- * @return ComparisonOperator
- */
- protected function getComparisonOperator(): ?ComparisonOperator
+ private function getComparisonOperator(): ?ComparisonOperator
{
if ($this->stream->nextIf(Token::T_GREATER_THAN)) {
$op = ComparisonOperator::GT;
@@ -552,10 +478,7 @@ protected function getComparisonOperator(): ?ComparisonOperator
return ComparisonOperator::create($op);
}
- /**
- * @return array
- */
- protected function getModifiers(): array
+ private function getModifiers(): array
{
$array = [
'trailing_wildcard' => $this->stream->nextIfLookahead(Token::T_WILDCARD),
diff --git a/src/Token.php b/src/Token.php
index 2348570..e14c9b0 100755
--- a/src/Token.php
+++ b/src/Token.php
@@ -3,7 +3,7 @@
namespace Gdbots\QueryParser;
-class Token implements \JsonSerializable
+final class Token implements \JsonSerializable
{
const T_EOI = 0; // end of input
const T_WHITE_SPACE = 1;
@@ -42,10 +42,9 @@ class Token implements \JsonSerializable
*
* @var array
*/
- private static $typeNames;
+ private static array $typeNames;
- /** @var int */
- private $type = self::T_EOI;
+ private int $type;
/** @var string|float|null */
private $value;
@@ -73,28 +72,19 @@ public static function name(int $type): string
static::$typeNames = array_flip((new \ReflectionClass(__CLASS__))->getConstants());
}
- return isset(self::$typeNames[$type]) ? self::$typeNames[$type] : (string)$type;
+ return self::$typeNames[$type] ?? (string)$type;
}
- /**
- * @return array
- */
public function jsonSerialize()
{
return ['type' => $this->type, 'value' => $this->value];
}
- /**
- * @return string
- */
public function getTypeName(): string
{
return self::name($this->type);
}
- /**
- * @return int
- */
public function getType(): int
{
return $this->type;
@@ -108,11 +98,6 @@ public function getValue()
return $this->value;
}
- /**
- * @param int $type
- *
- * @return bool
- */
public function typeEquals(int $type): bool
{
return $type === $this->type;
@@ -128,25 +113,16 @@ public function typeEqualsAnyOf(array $types): bool
return in_array($this->type, $types, true);
}
- /**
- * @return bool
- */
public function isWhiteSpace(): bool
{
return self::T_WHITE_SPACE === $this->type;
}
- /**
- * @return bool
- */
public function isIgnored(): bool
{
return self::T_IGNORED === $this->type;
}
- /**
- * @return bool
- */
public function isEndOfInput(): bool
{
return self::T_EOI === $this->type;
diff --git a/src/TokenStream.php b/src/TokenStream.php
index a7b2ac3..8f03fc8 100755
--- a/src/TokenStream.php
+++ b/src/TokenStream.php
@@ -5,17 +5,13 @@
final class TokenStream implements \JsonSerializable
{
- /** @var Token */
- private static $eoi;
+ private static ?Token $eoi = null;
/** @var Token[] */
- private $tokens = [];
+ private array $tokens = [];
- /** @var Token */
- private $current;
-
- /** @var int */
- private $position = 0;
+ private Token $current;
+ private int $position = 0;
/**
* @param Token[] $tokens
@@ -38,7 +34,7 @@ public function __construct(array $tokens)
public function reset(): self
{
$this->position = 0;
- $this->current = isset($this->tokens[$this->position]) ? $this->tokens[$this->position] : self::$eoi;
+ $this->current = $this->tokens[$this->position] ?? self::$eoi;
return $this;
}
@@ -151,7 +147,7 @@ public function typeIs(int $type): bool
/**
* Returns true if the current type equals any of the given types.
*
- * @param array $types
+ * @param int[] $types
*
* @return bool
*/
@@ -175,7 +171,7 @@ public function lookaheadTypeIs(int $type): bool
/**
* Returns true if the lookahead type equals any of the given types.
*
- * @param array $types
+ * @param int[] $types
*
* @return bool
*/
@@ -199,7 +195,7 @@ public function prevTypeIs(int $type): bool
/**
* Returns true if the previous token type equals any of the given types.
*
- * @param array $types
+ * @param int[] $types
*
* @return bool
*/
@@ -208,20 +204,14 @@ public function prevTypeIsAnyOf(array $types): bool
return isset($this->tokens[$this->position - 2]) && $this->tokens[$this->position - 2]->typeEqualsAnyOf($types);
}
- /**
- * @return Token
- */
public function getCurrent(): Token
{
return $this->current;
}
- /**
- * @return Token|null
- */
public function getLookahead(): ?Token
{
- return isset($this->tokens[$this->position]) ? $this->tokens[$this->position] : null;
+ return $this->tokens[$this->position] ?: null;
}
/**
@@ -234,9 +224,6 @@ public function getTokens(): array
return $this->tokens;
}
- /**
- * @return array
- */
public function jsonSerialize()
{
return $this->tokens;
diff --git a/src/Tokenizer.php b/src/Tokenizer.php
index 1e0af19..4cc0fa5 100755
Binary files a/src/Tokenizer.php and b/src/Tokenizer.php differ
diff --git a/tests/Builder/XmlQueryBuilderTest.php b/tests/Builder/XmlQueryBuilderTest.php
index b92d232..2a257f0 100755
--- a/tests/Builder/XmlQueryBuilderTest.php
+++ b/tests/Builder/XmlQueryBuilderTest.php
@@ -4,19 +4,16 @@
namespace Gdbots\Tests\QueryParser\Builder;
use Gdbots\QueryParser\Builder\XmlQueryBuilder;
-use Gdbots\QueryParser\QueryParser;
use Gdbots\QueryParser\Node\Node;
+use Gdbots\QueryParser\QueryParser;
use PHPUnit\Framework\TestCase;
class XmlQueryBuilderTest extends TestCase
{
- /** @var QueryParser */
- protected $parser;
-
- /** @var XmlQueryBuilder */
- protected $builder;
+ protected ?QueryParser $parser = null;
+ protected ?XmlQueryBuilder $builder = null;
- public function setUp()
+ public function setUp(): void
{
$this->parser = new QueryParser();
$this->builder = new XmlQueryBuilder();
@@ -60,9 +57,6 @@ public function testToSimpleXmlElement(string $name, string $input, $ignored, ar
}
}
- /**
- * @return array
- */
public function getTestQueries(): array
{
return require __DIR__ . '/../Fixtures/test-queries.php';
diff --git a/tests/QueryParserTest.php b/tests/QueryParserTest.php
index af59767..4824a98 100755
--- a/tests/QueryParserTest.php
+++ b/tests/QueryParserTest.php
@@ -8,10 +8,9 @@
class QueryParserTest extends TestCase
{
- /** @var QueryParser */
- protected $parser;
+ protected ?QueryParser $parser = null;
- public function setUp()
+ public function setUp(): void
{
$this->parser = new QueryParser();
}
@@ -30,9 +29,6 @@ public function testParse(string $name, string $input, $ignored, array $expected
$this->assertEquals($expectedNodes, $result->getNodes(), "Test query [{$name}] with input [{$input}] failed.");
}
- /**
- * @return array
- */
public function getTestQueries(): array
{
return require __DIR__ . '/Fixtures/test-queries.php';
diff --git a/tests/TokenizerTest.php b/tests/TokenizerTest.php
index 30a049d..a80f090 100755
--- a/tests/TokenizerTest.php
+++ b/tests/TokenizerTest.php
@@ -9,10 +9,9 @@
class TokenizerTest extends TestCase
{
- /** @var Tokenizer */
- protected $tokenizer;
+ protected ?Tokenizer $tokenizer = null;
- public function setUp()
+ public function setUp(): void
{
$this->tokenizer = new Tokenizer();
}
@@ -45,9 +44,6 @@ public function testScan(string $name, string $input, array $expectedTokens): vo
$this->assertEquals($expectedTokens, $tokenStream->getTokens(), "Test query [{$name}] with input [{$input}] failed.");
}
- /**
- * @return array
- */
public function getTestQueries(): array
{
return require __DIR__ . '/Fixtures/test-queries.php';