Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
68.00% covered (warning)
68.00%
17 / 25
33.33% covered (danger)
33.33%
1 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
Exists
68.00% covered (warning)
68.00%
17 / 25
33.33% covered (danger)
33.33%
1 / 3
20.42
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 get
83.33% covered (warning)
83.33%
5 / 6
0.00% covered (danger)
0.00%
0 / 1
2.02
 fieldPath
61.11% covered (warning)
61.11%
11 / 18
0.00% covered (danger)
0.00%
0 / 1
18.12
1<?php
2
3declare(strict_types=1);
4
5namespace Cosray\Finder\Output;
6
7use Cosray\Context;
8use Cosray\Exception\ParserOutputException;
9use Cosray\Finder\Input\Token;
10
11final readonly class Exists extends Expression implements Output
12{
13    public function __construct(
14        #[\SensitiveParameter]
15        private Token $token,
16        private Context $context,
17    ) {}
18
19    public function get(): string
20    {
21        if ($this->token->lexeme === '') {
22            throw new ParserOutputException($this->token, 'Invalid field name in exists condition.');
23        }
24
25        return 'n.content @? '
26        . $this->context->db->quote(
27            '$.' . $this->fieldPath($this->token->lexeme),
28        );
29    }
30
31    private function fieldPath(string $field): string
32    {
33        $parts = explode('.', $field);
34
35        foreach ($parts as $part) {
36            if ($part === '') {
37                throw new ParserOutputException($this->token, 'Invalid field name in exists condition.');
38            }
39        }
40
41        if (count($parts) === 1) {
42            return $parts[0] . '.value.*';
43        }
44
45        if (count($parts) === 2 && $parts[1] === '?') {
46            return $parts[0] . '.value.' . $this->context->localeId();
47        }
48
49        if (count($parts) > 2 && in_array('?', $parts, true)) {
50            throw new ParserOutputException(
51                $this->token,
52                'The questionmark is allowed after the first dot only.',
53            );
54        }
55
56        if (count($parts) === 2 && $parts[1] === '*') {
57            return $parts[0] . '.value.*';
58        }
59
60        if (count($parts) === 2) {
61            return $parts[0] . '.value.' . $parts[1];
62        }
63
64        return implode('.', $parts);
65    }
66}