Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
90.91% covered (success)
90.91%
30 / 33
33.33% covered (danger)
33.33%
1 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
CompilesField
90.91% covered (success)
90.91%
30 / 33
33.33% covered (danger)
33.33%
1 / 3
16.19
0.00% covered (danger)
0.00%
0 / 1
 compileField
90.48% covered (success)
90.48%
19 / 21
0.00% covered (danger)
0.00%
0 / 1
9.07
 effectiveFieldExpression
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
4
 normalizeLocaleIds
83.33% covered (warning)
83.33%
5 / 6
0.00% covered (danger)
0.00%
0 / 1
3.04
1<?php
2
3declare(strict_types=1);
4
5namespace Cosray\Finder;
6
7use Cosray\Exception\ParserException;
8
9trait CompilesField
10{
11    /** @param list<string> $localeIds */
12    protected function compileField(
13        string $fieldName,
14        string $tableField,
15        bool $asIs = false,
16        array $localeIds = [],
17    ): string {
18        $parts = explode('.', $fieldName);
19
20        foreach ($parts as $part) {
21            if ($part === '') {
22                throw new ParserException('Invalid field name');
23            }
24        }
25
26        $field = $parts[0];
27        $localeIds = $this->normalizeLocaleIds($localeIds);
28        $arrow = $asIs ? '->' : '->>';
29
30        if (count($parts) === 1) {
31            return $this->effectiveFieldExpression($tableField, $field, $localeIds, $asIs);
32        }
33
34        if (count($parts) === 2) {
35            $accessor = $parts[1];
36
37            if ($accessor === '?') {
38                return "{$tableField}->'{$field}'->'value'{$arrow}'{$localeIds[0]}'";
39            }
40
41            if ($accessor === '*') {
42                return "{$tableField}->'{$field}'->'value'";
43            }
44
45            return "{$tableField}->'{$field}'->'value'{$arrow}'{$accessor}'";
46        }
47
48        $path = "{$tableField}->'{$field}'";
49
50        foreach (array_slice($parts, 1, -1) as $part) {
51            $path .= "->'{$part}'";
52        }
53
54        $end = array_slice($parts, -1)[0];
55
56        return "{$path}{$arrow}'{$end}'";
57    }
58
59    /** @param list<string> $localeIds */
60    protected function effectiveFieldExpression(
61        string $tableField,
62        string $field,
63        array $localeIds,
64        bool $asIs,
65    ): string {
66        $expressions = [];
67
68        foreach ($localeIds as $localeId) {
69            $operator = $asIs ? '->' : '->>';
70            $expression = "{$tableField}->'{$field}'->'value'{$operator}'{$localeId}'";
71            $expressions[] = $asIs ? $expression : "NULLIF({$expression}, '')";
72        }
73
74        return 'COALESCE(' . implode(', ', $expressions) . ')';
75    }
76
77    /** @param list<string> $localeIds */
78    protected function normalizeLocaleIds(array $localeIds): array
79    {
80        $localeIds = array_values(array_filter($localeIds, static fn(string $id): bool => $id !== ''));
81
82        if ($localeIds === []) {
83            $localeIds = ['zxx'];
84        }
85
86        if (!in_array('zxx', $localeIds, true)) {
87            $localeIds[] = 'zxx';
88        }
89
90        return array_values(array_unique($localeIds));
91    }
92}