Completed
Push — master ( 9eea1d...6105f5 )
by Lucas
07:27
created

RqlTranslator::translateSearchQuery()   C

Complexity

Conditions 7
Paths 5

Size

Total Lines 35
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 35
rs 6.7272
cc 7
eloc 18
nc 5
nop 2
1
<?php
2
/**
3
 * Translator for RQL modification before execution
4
 */
5
6
namespace Graviton\RestBundle\Service;
7
8
use Graviton\Rql\Node\SearchNode;
9
use MongoDate;
10
use Xiag\Rql\Parser\AbstractNode;
11
use Xiag\Rql\Parser\DataType\Glob;
12
use Xiag\Rql\Parser\Node\AbstractQueryNode;
13
use Xiag\Rql\Parser\Node\Query\LogicOperator\AndNode;
14
use Xiag\Rql\Parser\Node\Query\LogicOperator\OrNode;
15
use Xiag\Rql\Parser\Node\Query\ScalarOperator\EqNode;
16
use Xiag\Rql\Parser\Node\Query\ScalarOperator\GeNode;
17
use Xiag\Rql\Parser\Node\Query\ScalarOperator\LeNode;
18
use Xiag\Rql\Parser\Node\Query\ScalarOperator\LikeNode;
19
use Xiag\Rql\Parser\Query;
20
21
/**
22
 * Class RqlTranslator
23
 *
24
 * @package Graviton\RestBundle\Service
25
 *
26
 * @author  List of contributors <https://github.com/libgraviton/graviton/graphs/contributors>
27
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
28
 * @link    http://swisscom.ch
29
 */
30
class RqlTranslator
31
{
32
33
    /**
34
     * Translate a search node into LikeNodes connected with an OrNode
35
     *
36
     * @param  SearchNode $searchNode   The given search node to transform
37
     * @param  array      $searchFields Which fields should be searched for all terms in SearchNode
38
     * @return SearchNode|OrNode|EqNode
39
     */
40
    public function translateSearchNode(SearchNode $searchNode, $searchFields = array())
41
    {
42
        if (sizeof($searchFields) === 0) {
43
            return new EqNode('id', "");
44
        }
45
46
        $orNode = new OrNode();
47
48
        foreach ($searchFields as $searchField) {
49
50
            foreach ($searchNode->getSearchTerms() as $searchTerm) {
51
                $searchGlob = new Glob('*' . $searchTerm . '*');
52
                $likeNode = new LikeNode($searchField, $searchGlob);
53
                $orNode->addQuery($likeNode);
54
55
                if (is_numeric($searchTerm)) {
56
                    # handle numbers
57
                    $searchNumber = (int) $searchTerm;
58
                    $numberNode = new EqNode($searchField, $searchNumber);
59
                    $orNode->addQuery($numberNode);
60
                }
61
62
                if ($this->isParsableDate($searchTerm)) {
63
                    # handle dates
64
                    $parsedDate = new \DateTime($searchTerm);
65
                    $searchDate = $parsedDate->format('Y-m-d');
66
67
                    $dateNode = new AndNode();
68
                    $searchFrom = new MongoDate(strtotime($searchDate." 00:00:00"));
69
                    $searchTo = new MongoDate(strtotime($searchDate." 23:59:59"));
70
                    $dateFrom = new GeNode($searchField, $searchFrom);
71
                    $dateTo = new LeNode($searchField, $searchTo);
72
73
                    $dateNode->addQuery($dateFrom);
74
                    $dateNode->addQuery($dateTo);
75
                    $orNode->addQuery($dateNode);
76
                }
77
            }
78
        }
79
80
        if (sizeof($orNode->getQueries()) > 0) {
81
            return $orNode;
82
        } else {
83
            return $searchNode;
84
        }
85
    }
86
87
    /**
88
     * Check Query for search nodes and translate them into corresponding like nodes
89
     *
90
     * @param AbstractNode $query        Query to translate
91
     * @param array        $searchFields Which fields should be searched for all terms in SearchNode
92
     * @return Query
93
     */
94
    public function translateSearchQuery(AbstractNode $query, $searchFields = array())
95
    {
96
        if (!($query instanceof Query)) {
97
            return $query;
98
        }
99
100
        $innerQuery = $query->getQuery();
101
102
        if ($innerQuery instanceof SearchNode) {
103
            $newNode = $this->translateSearchNode($innerQuery, $searchFields);
104
105
            if ($newNode instanceof OrNode) {
106
                $query->setQuery($newNode);
107
            }
108
        } elseif ($innerQuery instanceof AndNode) {
109
            $andNodeReplacement = new AndNode();
110
            foreach ($innerQuery->getQueries() as $innerNodeFromAnd) {
111
112
                if ($innerNodeFromAnd instanceof SearchNode) {
113
                    // Transform to OrNode with inner like queries and add to new query list
114
                    $andNodeReplacement->addQuery(
115
                        $this->translateSearchNode($innerNodeFromAnd, $searchFields)
116
                    );
117
                } else {
118
                    // Just recollect the node
119
                    $andNodeReplacement->addQuery($innerNodeFromAnd);
120
                }
121
122
            }
123
124
            $query->setQuery($andNodeReplacement);
125
        }
126
127
        return $query;
128
    }
129
130
    /**
131
     * Check if string can be parsed to date
132
     *
133
     * @param string $dateString The date string to be parsed
134
     * @return bool
135
     */
136
    protected function isParsableDate($dateString)
137
    {
138
        try {
139
            $date = new \DateTime($dateString);
0 ignored issues
show
Unused Code introduced by
$date is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
140
        } catch (\Exception $e) {
141
            // Expected here, go on
142
            return false;
143
        }
144
        return true;
145
    }
146
}
147