Completed
Push — bugfix/EVO-7301 ( e01ef0...bee5aa )
by
unknown
19:11 queued 12:46
created

SelectExclusionStrategy::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 5
ccs 4
cts 4
cp 1
rs 9.4285
cc 1
eloc 3
nc 1
nop 1
crap 1
1
<?php
2
/**
3
 * Class for exclusion strategies.
4
 */
5
namespace Graviton\RestBundle\ExclusionStrategy;
6
7
use JMS\Serializer\Exclusion\ExclusionStrategyInterface;
8
use JMS\Serializer\Metadata\ClassMetadata;
9
use JMS\Serializer\Metadata\PropertyMetadata;
10
use JMS\Serializer\Context;
11
use Symfony\Component\HttpFoundation\RequestStack;
12
use Xiag\Rql\Parser\Query;
13
14
/**
15
 * In this Strategy we skip all properties on first level who are not selected if there is a select in rql.
16
 *
17
 * @author   List of contributors <https://github.com/libgraviton/graviton/graphs/contributors>
18
 * @license  http://opensource.org/licenses/gpl-license.php GNU Public License
19
 * @link     http://swisscom.ch
20
 */
21
class SelectExclusionStrategy implements ExclusionStrategyInterface
22
{
23
    /**
24
     * @var RequestStack $requestStack
25
     */
26
    protected $requestStack;
27
28
    /**
29
     * @var Array $selectedFields
30
     */
31
    protected $selectedFields;
32
33
    /**
34
     * @var Boolean $isSelect
35
     */
36
    protected $isSelect;
37
38
    /**
39
     * SelectExclusionStrategy constructor.
40
     * Comstructor Injection of the global request_stack to access the selected Fields via Query-Object
41
     * @param RequestStack $requestStack the global request_stack
42
     */
43 4
    public function __construct(RequestStack $requestStack)
44
    {
45 4
        $this->requestStack = $requestStack;
46 4
        $this->getSelectedFieldsFromRQL();
47 4
    }
48
49
    /**
50
     * Initializing $this->selectedFields and $this->isSelect
51
     * getting the fields that should be really serialized and setting the switch that there is actually a select
52
     * called once in the object, so shouldSkipProperty can use the information for every field
53
     * @return void
54
     */
55 4
    public function getSelectedFieldsFromRQL()
56
    {
57 4
        $currentRequest = $this->requestStack->getCurrentRequest();
58 4
        $this->selectedFields = [];
59 4
        $this->isSelect = false;
60 4
        if ($currentRequest) {
61
            $rqlQuery = $currentRequest->get('rqlQuery');
62
            if ($rqlQuery && $rqlQuery instanceof Query) {
63
                $select = $rqlQuery->getSelect();
64
                if ($select) {
65
                    $this->isSelect = true;
66
                    $this->selectedFields = $select->getFields();
67
                    // get the nested fields as well
68
                    $nestedFields = [];
69
                    foreach ($this->selectedFields as $key => $field) {
70
                        if (strstr($field, '.')) {
71
                            $nestedFields=array_merge($nestedFields, explode('.', $field));
72
                            unset($this->selectedFields[$key]);
73
                        }
74
                    }
75
                    $this->selectedFields = array_merge($this->selectedFields, $nestedFields);
76
                    // id is always included in response (bug/feature)?
77
                    if (! in_array('id', $this->selectedFields)) {
78
                        $this->selectedFields[] = 'id';
79
                    };
80
                }
81
            }
82
        }
83 4
    }
84
85
    /**
86
     * @InheritDoc: Whether the class should be skipped.
87
     * @param ClassMetadata $metadata         the ClassMetadata for the Class of the property to be serialized
88
     * @param Context       $navigatorContext the context for serialization
89
     * @return boolean
90
     */
91
    public function shouldSkipClass(ClassMetadata $metadata, Context $navigatorContext)
92
    {
93
        return false;
94
    }
95
96
    /**
97
     * @InheritDoc: Whether the property should be skipped.
98
     * Skipping properties on first level who are not selected if there is a select in rql.
99
     * @param PropertyMetadata $property the property to be serialized
100
     * @param Context          $context  the context for serialization
101
     * @return boolean
102
     */
103
    public function shouldSkipProperty(PropertyMetadata $property, Context $context)
104
    {
105
        // we are only dealing with the first level of the JSON here
106
        if ($context->getDepth() > 1) {
107
            return false;
108
        }
109
        // nothing selected, default serialization
110
        if (! $this->isSelect) {
111
            return false;
112
        }
113
        return ! in_array($property->name, $this->selectedFields);
114
    }
115
}
116