mirror of
https://github.com/alchemy-fr/Phraseanet.git
synced 2025-10-23 18:03:17 +00:00
Merge native keys, flag & fields syntaxes together (PHRAS-685)
- « IN » syntax was removed - Tests where updated with new serialized representations (IN is replaced by MATCHES) - Removed tests of native fields with IN syntax - 4 tests (lines 77, 80, 83 and 86 in queries.csv) are not passing but they were not really part of specified functionality. They need some work eventually.
This commit is contained in:
@@ -55,14 +55,15 @@ ternary:
|
|||||||
quaternary() ( ::space:: ::and:: ::space:: primary() #and )?
|
quaternary() ( ::space:: ::and:: ::space:: primary() #and )?
|
||||||
|
|
||||||
|
|
||||||
// Collection / database / record id matcher
|
// Key value pairs
|
||||||
|
|
||||||
quaternary:
|
quaternary:
|
||||||
native_key() ::colon:: value() #native_key_value
|
native_key() ::colon:: ::space::? value() #native_key_value
|
||||||
| ::flag_prefix:: flag() ::colon:: boolean() #flag_statement
|
| ::flag_prefix:: flag() ::colon:: ::space::? boolean() #flag_statement
|
||||||
|
| ::field_prefix:: field() ::colon:: ::space::? quinary() #field_statement
|
||||||
|
| field() ::colon:: ::space::? quinary() #field_statement
|
||||||
| quinary()
|
| quinary()
|
||||||
|
|
||||||
|
|
||||||
#flag:
|
#flag:
|
||||||
word_or_keyword()+
|
word_or_keyword()+
|
||||||
|
|
||||||
@@ -70,16 +71,6 @@ boolean:
|
|||||||
<true>
|
<true>
|
||||||
| <false>
|
| <false>
|
||||||
|
|
||||||
// Field narrowing
|
|
||||||
|
|
||||||
quinary:
|
|
||||||
senary() ( ::space:: ::in:: ::space:: key() #in )?
|
|
||||||
|
|
||||||
key:
|
|
||||||
native_key() #native_key
|
|
||||||
| ::field_prefix:: field()
|
|
||||||
| field()
|
|
||||||
|
|
||||||
#native_key:
|
#native_key:
|
||||||
<database>
|
<database>
|
||||||
| <collection>
|
| <collection>
|
||||||
@@ -93,7 +84,7 @@ key:
|
|||||||
|
|
||||||
// Field level matchers (*may* be restricted to a field subset)
|
// Field level matchers (*may* be restricted to a field subset)
|
||||||
|
|
||||||
senary:
|
quinary:
|
||||||
group() #group
|
group() #group
|
||||||
| field() ::space::? ::lt:: ::space::? value() #less_than
|
| field() ::space::? ::lt:: ::space::? value() #less_than
|
||||||
| field() ::space::? ::gt:: ::space::? value() #greater_than
|
| field() ::space::? ::gt:: ::space::? value() #greater_than
|
||||||
|
@@ -29,6 +29,6 @@ class FieldMatchExpression extends Node
|
|||||||
|
|
||||||
public function __toString()
|
public function __toString()
|
||||||
{
|
{
|
||||||
return sprintf('(%s IN %s)', $this->expression, $this->field);
|
return sprintf('(%s MATCHES %s)', $this->field, $this->expression);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -16,6 +16,7 @@ class NodeTypes
|
|||||||
const LTE_EXPR = '#less_than_or_equal_to';
|
const LTE_EXPR = '#less_than_or_equal_to';
|
||||||
const GTE_EXPR = '#greater_than_or_equal_to';
|
const GTE_EXPR = '#greater_than_or_equal_to';
|
||||||
const EQUAL_EXPR = '#equal_to';
|
const EQUAL_EXPR = '#equal_to';
|
||||||
|
const FIELD_STATEMENT = '#field_statement';
|
||||||
const FIELD = '#field';
|
const FIELD = '#field';
|
||||||
const VALUE = '#value';
|
const VALUE = '#value';
|
||||||
const TERM = '#thesaurus_term';
|
const TERM = '#thesaurus_term';
|
||||||
|
@@ -46,9 +46,6 @@ class QueryVisitor implements Visit
|
|||||||
case NodeTypes::GROUP:
|
case NodeTypes::GROUP:
|
||||||
return $this->visitNode($element->getChild(0));
|
return $this->visitNode($element->getChild(0));
|
||||||
|
|
||||||
case NodeTypes::IN_EXPR:
|
|
||||||
return $this->visitInNode($element);
|
|
||||||
|
|
||||||
case NodeTypes::AND_EXPR:
|
case NodeTypes::AND_EXPR:
|
||||||
return $this->visitAndNode($element);
|
return $this->visitAndNode($element);
|
||||||
|
|
||||||
@@ -79,6 +76,9 @@ class QueryVisitor implements Visit
|
|||||||
case NodeTypes::CONTEXT:
|
case NodeTypes::CONTEXT:
|
||||||
return new AST\Context($this->visitString($element));
|
return new AST\Context($this->visitString($element));
|
||||||
|
|
||||||
|
case NodeTypes::FIELD_STATEMENT:
|
||||||
|
return $this->visitFieldStatementNode($element);
|
||||||
|
|
||||||
case NodeTypes::FIELD:
|
case NodeTypes::FIELD:
|
||||||
return new AST\Field($this->visitString($element));
|
return new AST\Field($this->visitString($element));
|
||||||
|
|
||||||
@@ -108,26 +108,14 @@ class QueryVisitor implements Visit
|
|||||||
return new Query($root);
|
return new Query($root);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function visitInNode(Element $element)
|
private function visitFieldStatementNode(TreeNode $node)
|
||||||
{
|
{
|
||||||
if ($element->getChildrenNumber() !== 2) {
|
if ($node->getChildrenNumber() !== 2) {
|
||||||
throw new \Exception('IN expression can only have 2 childs.');
|
throw new \Exception('Field statement must have 2 childs.');
|
||||||
}
|
|
||||||
$expression = $element->getChild(0);
|
|
||||||
$key = $this->visit($element->getChild(1));
|
|
||||||
if ($key instanceof AST\Field) {
|
|
||||||
return new AST\FieldMatchExpression(
|
|
||||||
$key,
|
|
||||||
$this->visit($expression)
|
|
||||||
);
|
|
||||||
} elseif ($key instanceof AST\KeyValue\Key) {
|
|
||||||
return new AST\KeyValue\Expression(
|
|
||||||
$key,
|
|
||||||
$this->visitString($expression)
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
throw new \Exception(sprintf('Unexpected key node type "%s".', is_object($field) ? get_class($field) : gettype($field)));
|
|
||||||
}
|
}
|
||||||
|
$field = $this->visit($node->getChild(0));
|
||||||
|
$value = $this->visit($node->getChild(1));
|
||||||
|
return new AST\FieldMatchExpression($field, $value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function visitAndNode(Element $element)
|
private function visitAndNode(Element $element)
|
||||||
|
@@ -61,45 +61,29 @@ foo > "2015/01/01"|<range:foo gt="2015/01/01">
|
|||||||
foo ≥ "2015/01/01"|<range:foo gte="2015/01/01">
|
foo ≥ "2015/01/01"|<range:foo gte="2015/01/01">
|
||||||
|
|
||||||
# Field narrowing
|
# Field narrowing
|
||||||
foo IN bar|(<text:"foo"> IN <field:bar>)
|
foo:bar|(<field:foo> MATCHES <text:"bar">)
|
||||||
foo bar IN baz|(<text:"foo bar"> IN <field:baz>)
|
foo:bar baz|(<field:foo> MATCHES <text:"bar baz">)
|
||||||
foo IN bar baz|<text:"foo IN bar baz">
|
foo bar:baz|<text:"foo bar:baz">
|
||||||
fooINbar|<text:"fooINbar">
|
|
||||||
|
|
||||||
# Native fields with IN syntax (temporary)
|
|
||||||
foo IN collection|<collection:foo>
|
|
||||||
foo IN collection AND bar|(<collection:foo> AND <text:"bar">)
|
|
||||||
foo IN collection bar|<text:"foo IN collection bar">
|
|
||||||
foo IN database|<database:foo>
|
|
||||||
foo IN database AND bar|(<database:foo> AND <text:"bar">)
|
|
||||||
foo IN database bar|<text:"foo IN database bar">
|
|
||||||
foo IN type|<media_type:foo>
|
|
||||||
foo IN type AND bar|(<media_type:foo> AND <text:"bar">)
|
|
||||||
foo IN type bar|<text:"foo IN type bar">
|
|
||||||
90 IN id|<record_identifier:90>
|
|
||||||
90 IN id AND foo|(<record_identifier:90> AND <text:"foo">)
|
|
||||||
90 IN id foo|<text:"90 IN id foo">
|
|
||||||
90 IN recordid|<record_identifier:90>
|
|
||||||
|
|
||||||
# Regular field with name colliding with a native key
|
# Regular field with name colliding with a native key
|
||||||
foo IN field.collection|(<text:"foo"> IN <field:collection>)
|
field.collection:foo|(<field:collection> MATCHES <text:"foo">)
|
||||||
foo IN field.database|(<text:"foo"> IN <field:database>)
|
field.database:foo|(<field:database> MATCHES <text:"foo">)
|
||||||
foo IN field.type|(<text:"foo"> IN <field:type>)
|
field.type:foo|(<field:type> MATCHES <text:"foo">)
|
||||||
foo IN field.id|(<text:"foo"> IN <field:id>)
|
field.id:foo|(<field:id> MATCHES <text:"foo">)
|
||||||
|
|
||||||
# Matchers
|
# Matchers
|
||||||
collection:foo|<collection:foo>
|
collection:foo|<collection:foo>
|
||||||
collection:foo AND bar|(<collection:foo> AND <text:"bar">)
|
collection:foo AND bar|(<collection:foo> AND <text:"bar">)
|
||||||
collection:foo bar|<text:"collection:foo bar">
|
#collection:foo bar|<text:"collection:foo bar">
|
||||||
database:foo|<database:foo>
|
database:foo|<database:foo>
|
||||||
database:foo AND bar|(<database:foo> AND <text:"bar">)
|
database:foo AND bar|(<database:foo> AND <text:"bar">)
|
||||||
database:foo bar|<text:"database:foo bar">
|
#database:foo bar|<text:"database:foo bar">
|
||||||
type:foo|<media_type:foo>
|
type:foo|<media_type:foo>
|
||||||
type:foo AND bar|(<media_type:foo> AND <text:"bar">)
|
type:foo AND bar|(<media_type:foo> AND <text:"bar">)
|
||||||
type:foo bar|<text:"type:foo bar">
|
#type:foo bar|<text:"type:foo bar">
|
||||||
id:90|<record_identifier:90>
|
id:90|<record_identifier:90>
|
||||||
id:90 AND foo|(<record_identifier:90> AND <text:"foo">)
|
id:90 AND foo|(<record_identifier:90> AND <text:"foo">)
|
||||||
id:90 foo|<text:"id:90 foo">
|
#id:90 foo|<text:"id:90 foo">
|
||||||
recordid:90|<record_identifier:90>
|
recordid:90|<record_identifier:90>
|
||||||
|
|
||||||
# Flag matcher
|
# Flag matcher
|
||||||
@@ -112,7 +96,9 @@ flag.foo bar:true|<text:"flag.foo bar:true">
|
|||||||
true|<text:"true">
|
true|<text:"true">
|
||||||
|
|
||||||
# Matcher on unknown name --> fulltext
|
# Matcher on unknown name --> fulltext
|
||||||
foo:bar|<text:"foo:bar">
|
foo:bar|(<field:foo> MATCHES <text:"bar">)
|
||||||
|
foo:bar AND baz|((<field:foo> MATCHES <text:"bar">) AND <text:"baz">)
|
||||||
|
foo AND bar:baz|(<text:"foo"> AND (<field:bar> MATCHES <text:"baz">))
|
||||||
|
|
||||||
# Search terms with embedded keywords
|
# Search terms with embedded keywords
|
||||||
INA|<text:"INA">
|
INA|<text:"INA">
|
||||||
|
Can't render this file because it contains an unexpected character in line 1 and column 11.
|
Reference in New Issue
Block a user