Completed
Push — labs ( 04d0b8...211687 )
by Christian
14:25
created

SearchCriteriaBuilder::handleRequest()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 14
c 0
b 0
f 0
rs 9.4285
cc 3
eloc 8
nc 3
nop 3
1
<?php declare(strict_types=1);
2
3
namespace Shopware\Api\Entity\Search;
4
5
use Shopware\Api\Entity\EntityDefinition;
6
use Shopware\Api\Entity\Search\Parser\QueryStringParser;
7
use Shopware\Api\Entity\Search\Query\ScoreQuery;
8
use Shopware\Api\Entity\Search\Sorting\FieldSorting;
9
use Shopware\Api\Entity\Search\Term\EntityScoreQueryBuilder;
10
use Shopware\Api\Entity\Search\Term\SearchTermInterpreter;
11
use Shopware\Context\Struct\ShopContext;
12
use Symfony\Component\HttpFoundation\Request;
13
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
14
15
class SearchCriteriaBuilder
16
{
17
    /**
18
     * @var SearchTermInterpreter
19
     */
20
    private $searchTermInterpreter;
21
    /**
22
     * @var EntityScoreQueryBuilder
23
     */
24
    private $entityScoreQueryBuilder;
25
26
    public function __construct(
27
        SearchTermInterpreter $searchTermInterpreter,
28
        EntityScoreQueryBuilder $entityScoreQueryBuilder
29
    ) {
30
        $this->searchTermInterpreter = $searchTermInterpreter;
31
        $this->entityScoreQueryBuilder = $entityScoreQueryBuilder;
32
    }
33
34
    public function handleRequest(Request $request, string $definition, ShopContext $context): Criteria
35
    {
36
        switch ($request->getMethod()) {
37
            case 'POST':
38
                $payload = json_decode($request->getContent(), true);
39
                if (!$payload) {
40
                    throw new BadRequestHttpException('Malformed JSON');
41
                }
42
43
                return $this->fromArray($payload, $definition, $context);
44
        }
45
46
        return new Criteria();
47
    }
48
49
    private function fromArray(array $payload, string $definition, ShopContext $context): Criteria
50
    {
51
        $criteria = new Criteria();
52
        $criteria->setFetchCount(Criteria::FETCH_COUNT_TOTAL);
53
        $criteria->setLimit(10);
54
55
        if (isset($payload['fetch-count'])) {
56
            $criteria->setFetchCount((int) $payload['fetch-count']);
57
        }
58
        if (isset($payload['offset'])) {
59
            $criteria->setOffset((int) $payload['offset']);
60
        }
61
        if (isset($payload['size'])) {
62
            $criteria->setLimit((int) $payload['size']);
63
        }
64
65
        if (isset($payload['filter']) && is_array($payload['filter'])) {
66
            foreach ($payload['filter'] as $query) {
67
                $criteria->addFilter(
68
                    QueryStringParser::fromArray($query)
69
                );
70
            }
71
        }
72
73
        if (isset($payload['query']) && is_array($payload['query'])) {
74
            foreach ($payload['query'] as $query) {
75
                $parsedQuery = QueryStringParser::fromArray($query['query']);
76
                $score = isset($query['score']) ? $query['score'] : 1;
77
                $scoreField = isset($query['scoreField']) ? $query['scoreField'] : null;
78
79
                $criteria->addQuery(new ScoreQuery($parsedQuery, $score, $scoreField));
80
            }
81
        }
82
83
        if (isset($payload['term'])) {
84
            $pattern = $this->searchTermInterpreter->interpret(
85
                (string) $payload['term'],
86
                $context
87
            );
88
89
            /** @var EntityDefinition|string $definition */
90
            $queries = $this->entityScoreQueryBuilder->buildScoreQueries(
91
                $pattern,
92
                $definition,
0 ignored issues
show
Bug introduced by
It seems like $definition can also be of type object<Shopware\Api\Entity\EntityDefinition>; however, Shopware\Api\Entity\Sear...er::buildScoreQueries() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
93
                $definition::getEntityName()
94
            );
95
96
            $criteria->addQueries($queries);
97
        }
98
99
        if (isset($payload['sort']) && is_array($payload['sort'])) {
100
            $criteria->addSortings($this->parseSorting($payload['sort']));
101
        }
102
103
        return $criteria;
104
    }
105
106
    private function parseSorting(array $sorting): array
107
    {
108
        $sortings = [];
109
        foreach ($sorting as $sort) {
110
            if (strcasecmp($sort['order'], 'desc') === 0) {
111
                $order = FieldSorting::DESCENDING;
112
            } else {
113
                $order = FieldSorting::ASCENDING;
114
            }
115
            $sortings[] = new FieldSorting($sort['field'], $order);
116
        }
117
118
        return $sortings;
119
    }
120
}
121