public function testQueryBuildWithPrivateFieldAndConcept()
 {
     $public_field = new Field('foo', Mapping::TYPE_STRING, ['private' => false]);
     $private_field = new Field('bar', Mapping::TYPE_STRING, ['private' => true, 'used_by_collections' => [1, 2, 3]]);
     $query_context = $this->prophesize(QueryContext::class);
     $query_context->getUnrestrictedFields()->willReturn([$public_field]);
     $query_context->localizeField($public_field)->willReturn(['foo.fr', 'foo.en']);
     $query_context->getPrivateFields()->willReturn([$private_field]);
     $query_context->localizeField($private_field)->willReturn(['private_caption.bar.fr', 'private_caption.bar.en']);
     $node = new TextNode('baz');
     $node->setConcepts([new Concept('/qux')]);
     $query = $node->buildQuery($query_context->reveal());
     $expected = '{
         "bool": {
             "should": [{
                 "multi_match": {
                     "fields": ["foo.fr", "foo.en"],
                     "query": "baz",
                     "type": "cross_fields",
                     "operator": "and",
                     "lenient": true
                 }
             }, {
                 "multi_match": {
                     "fields": [
                         "concept_path.foo"
                     ],
                     "query": "\\/qux"
                 }
             }, {
                 "filtered": {
                     "filter": {
                         "terms": {
                             "base_id": [1, 2, 3]
                         }
                     },
                     "query": {
                         "bool": {
                             "should": [{
                                 "multi_match": {
                                     "fields": ["private_caption.bar.fr", "private_caption.bar.en"],
                                     "query": "baz",
                                     "type": "cross_fields",
                                     "operator": "and",
                                     "lenient": true
                                 }
                             }, {
                                 "multi_match": {
                                     "fields": ["concept_path.bar"],
                                     "query": "/qux"
                                 }
                             }]
                         }
                     }
                 }
             }]
         }
     }';
     $this->assertEquals(json_decode($expected, true), $query);
 }
 private function visitText(Element $element)
 {
     $nodes = array();
     // Walk childs and merge adjacent text nodes if needed
     $last = null;
     $last_index = -1;
     foreach ($element->getChildren() as $child) {
         $node = $child->accept($this);
         // Merge text nodes together
         if ($last instanceof AST\TextNode && $node instanceof AST\TextNode) {
             // Prevent merge once a context is set
             if ($last->hasContext()) {
                 throw new Exception('Unexpected text node after context');
             }
             $nodes[$last_index] = $last = AST\TextNode::merge($last, $node);
         } else {
             $nodes[] = $node;
             $last = $node;
             $last_index++;
         }
     }
     // Once nodes are merged, we just "AND" them all together.
     $root = null;
     foreach ($nodes as $index => $node) {
         if (!$root) {
             $root = $node;
             continue;
         }
         if ($node instanceof AST\Context) {
             if ($root instanceof AST\ContextAbleInterface) {
                 $root = $root->withContext($node);
             } else {
                 throw new Exception('Unexpected context after non-contextualizable node');
             }
         } elseif ($node instanceof AST\Node) {
             $root = new AST\Boolean\AndExpression($root, $node);
         } else {
             throw new Exception('Unexpected node type inside text node.');
         }
     }
     return $root;
 }
Exemple #3
0
 /**
  * Merge two text nodes by concatenating their content.
  *
  * /!\ Text contexts are lost in the process
  *
  * @param  TextNode $a First node
  * @param  TextNode $b The other one
  * @return TextNode    Merged text node
  */
 public static function merge(TextNode $a, TextNode $b)
 {
     return new self(sprintf('%s%s', $a->getValue(), $b->getValue()));
 }