Test Failed
Push — master ( 7228dc...961f38 )
by Bálint
12:45
created

ExpandedProjectionNode::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 6
c 0
b 0
f 0
dl 0
loc 10
rs 10
cc 1
nc 1
nop 8

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
namespace POData\UriProcessor\QueryProcessor\ExpandProjectionParser;
4
5
use POData\UriProcessor\QueryProcessor\OrderByParser\InternalOrderByInfo;
6
use POData\Providers\Metadata\ResourceType;
7
use POData\Providers\Metadata\ResourceSetWrapper;
8
use POData\Common\Messages;
9
use POData\Providers\Metadata\ResourceProperty;
10
11
/**
12
 * Class ExpandedProjectionNode
13
 *
14
 * ExpandProjectionParser will create a 'Projection Tree' from the $expand
15
 * and/or $select query options, Each path segment in the $expand/$select
16
 * will be represented by a node in the projection tree, A path segment in
17
 * $expand option will be represented using this type and a path segment in
18
 * $select option (which is not appear in expand option) will be represented
19
 * using 'ProjectionNode' (base type of this type). The root of the projection
20
 * tree will be represented using the type 'RootProjectionNode' which is
21
 * derived from this type.
22
 *
23
 * @package POData\UriProcessor\QueryProcessor\ExpandProjectionParser
24
 */
25
class ExpandedProjectionNode extends ProjectionNode
26
{
27
    /**
28
     * An 'ExpandedProjectionNode' can represents either an expanded navigation
29
     * property or root of the 'Projection Tree', When the node represents
30
     * expanded navigation property this field holds reference to the resource
31
     * (entity) set pointed by the navigation property, when the node
32
     * represents 'Projection Tree' root, this fields holds reference to the
33
     * resource set that the uri resource path points to.
34
     *
35
     * @var ResourceSetWrapper
36
     */
37
    private $_resourceSetWrapper;
38
39
    private $_derivedType;
40
41
    /**
42
     * The sort information associated with the expanded navigation property or
43
     * root of 'Projection Tree', when this node represents root of the
44
     * projection tree then this member will be set if $top, $skip is specified
45
     * in the request uri or server side paging is enabled for the resource
46
     * identified by the request uri, when this node represents an expanded
47
     * navigation property then this member will be set if server side paging
48
     * is enabled for the resource set corresponding to the navigation
49
     * property.
50
     *
51
     * @var InternalOrderByInfo
52
     */
53
    private $_internalOrderByInfo;
54
55
    /**
56
     * Number of results to be skipped for this node, the value of this field
57
     * depends on the what this node actually represents,
58
     * (1) Node represents navigation property
59
     *     value will be always null
60
     * (2) Node represents root of the 'Projection Tree'
61
     *     value of the $skip query option, null if skip is absent
62
     * A null value for this filed means return all results.
63
     * @var int
64
     */
65
    private $_skipCount;
66
67
    /**
68
     * Maximum number of results to be returned for this node, the value of
69
     * this field depends on the what this node actually represents,
70
     * (1) Node represents navigation property
71
     *     The page size of the resource set pointed by the navigation
72
     *          property
73
     * (2) Node represents root of the 'Projection Tree'
74
     *     The minimum among the page size of the resource set that the
75
     *          uri resource path points to and the value of $top query option
76
     *          (if applied).
77
     * A null value for this filed means return all results.
78
     *
79
     * @var int
80
     */
81
    private $_takeCount;
82
83
    /**
84
     * The maximum number of results allowed for this node, taken from
85
     * ServiceConfiguration::_maxResultsPerCollection null means no limit
86
     * will be applied and thus all results availabe should be returned.
87
     *
88
     * @var int
89
     */
90
    private $_maxResultCount;
91
92
    /**
93
     * List of child nodes, array of ExpandedProjectionNode and/or
94
     * ProjectionNode.
95
     *
96
     * @var ProjectionNode[]
97
     */
98
    private $_childNodes = array();
99
100
    /**
101
     * When we have seen a $select path including this expanded property then
102
     * this field will be set to true, this field is used to eliminate nodes
103
     * representing segments in $expand option which are not selected.
104
     *
105
     * e.g:
106
     * $expand=A/B, A/B/C, A/B/D, X/Y, M/N & $select=A/B
107
     *     Here we need to consider only A/B, A/B/C and A/B/D, we can eliminate
108
     *     the nodes X/Y and M/N which are not selected. This field will be set
109
     *     to true for the nodes A and B.
110
     *
111
     * @var boolean
112
     */
113
    private $_selectionFound = false;
114
115
    /**
116
     * This field set to true when we have seen the special token '*', means
117
     * select all immediate (child) properties of this node.
118
     *
119
     * e.g:
120
     * $expand=A/B, A/B/C & $select=A/*
121
     *     Here we need to return only set of A with immediate properties,
122
     *     expand request for B, B/C will be ignored
123
     * $expand=A/B, A/B/C & $select=*
124
     *   Here we need to return only set pointed by uri path segment with
125
     *   immediate properties, expand request be ignored
126
     * $expand=A/B, A/B/C & $select=A/*, A/B
127
     *   Here we need to return set of A with immediate properties and
128
     *   associated B's.
129
     *
130
     * @var boolean
131
     */
132
    private $_selectAllImmediateProperties = false;
133
134
    /**
135
     * Flag which indicate whether the entire expanded subtree of this node
136
     * should be selected or not.
137
     *
138
     * e.g:
139
     * $expand=A/B, A/B/C/D & $select=A/B
140
     *     Here need to return all immediate properties of B, associated
141
     *     C with immediate properties and associated D of C with immediate
142
     *     properties, so for B, C and D this field will be true.
143
     *
144
     * @var boolean
145
     */
146
    private $_selectSubtree = false;
147
148
    /**
149
     * Constructs a new instance of node representing expanded navigation property
150
     *
151
     * @param string              $propertyName        The name of the property
152
     *                                                 to expand If this node
153
     *                                                 represents an expanded
154
     *                                                 navigation property then
155
     *                                                 this is the name of the
156
     *                                                 navigation property. if this
157
     *                                                 node represents root of the
158
     *                                                 projection tree then this
159
     *                                                 will be null.
160
     * @param ResourceProperty    $resourceProperty    The resource property for
161
     *                                                 the property to expand.
162
     *                                                 If this node represents an
163
     *                                                 expanded navigation property
164
     *                                                 then this is the resource
165
     *                                                 property of navigation
166
     *                                                 property, if this node
167
     *                                                 represents root of the
168
     *                                                 projection tree then
169
     *                                                 this will be null.
170
     * @param ResourceSetWrapper  $resourceSetWrapper  The resource set to which
171
     *                                                 the expansion leads, see the
172
     *                                                 comment of _resourceSetWrapper
173
     *                                                 field.
174
     * @param InternalOrderByInfo $internalOrderByInfo The sort information
175
     *                                                 associated with this node,
176
     *                                                 see the comments of
177
     *                                                 $_internalOrderByInfo field.
178
     * @param int                 $skipCount           The number of results to
179
     *                                                 skip, null means no
180
     *                                                 result to skip, see the
181
     *                                                 comments of _skipCount
182
     *                                                 field.
183
     * @param int                 $takeCount           The maximum number of results
184
     *                                                 to return, null means return
185
     *                                                 all available result, see the
186
     *                                                 comments of _takeCount field
187
     * @param int                 $maxResultCount      The maximum number of
188
     *                                                 expected result,see comment
189
     *                                                 of _maxResultCount field
190
     */
191
    public function __construct($propertyName, $resourceProperty,
192
        ResourceSetWrapper $resourceSetWrapper, $internalOrderByInfo,
193
        $skipCount, $takeCount, $maxResultCount, ResourceType $derivedType = null
0 ignored issues
show
Unused Code introduced by
The parameter $maxResultCount is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

193
        $skipCount, $takeCount, /** @scrutinizer ignore-unused */ $maxResultCount, ResourceType $derivedType = null

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
194
    ) {
195
        $this->_resourceSetWrapper = $resourceSetWrapper;
196
        $this->_internalOrderByInfo = $internalOrderByInfo;
197
        $this->_skipCount = $skipCount;
198
        $this->_takeCount = $takeCount;
199
        $this->_derivedType = $derivedType;
200
        parent::__construct($propertyName, $resourceProperty);
201
    }
202
203
    /**
204
     * Resource set to which the expansion represented by this node leads to
205
     * (An expansion means a set of entities associated with an entity,
206
     * associated set will be sub set of an resource set) If this node
207
     * represents an expanded navigation property, this is the resource set
208
     * to which the expanded navigation property points to, If this node is
209
     * the root of projection tree, this is the resource set that the uri
210
     * resource path points to.
211
     *
212
     * @return ResourceSetWrapper
213
     */
214
    public function getResourceSetWrapper()
215
    {
216
        return $this->_resourceSetWrapper;
217
    }
218
219
    public function getDerivedType()
220
    {
221
        return $this->_derivedType;
222
    }
223
224
    public function setDerivedType($derivedType)
225
    {
226
        return $this->_derivedType = $derivedType;
227
    }
228
229
    /**
230
     * An expansion leads by this node results in a collection of entities,
231
     * this is the resource type of these entities, This is usually the
232
     * resource type of the 'ResourceSetWrapper' for this node, but it can
233
     * also be a derived type of ResourceSetWrapper::ResourceType, this can
234
     * happen if navigation property points to a resource set but uses a
235
     * derived type.
236
     *
237
     * @return ResourceType
238
     */
239
    public function getResourceType()
240
    {
241
        return $this->resourceProperty->getResourceType();
242
    }
243
244
    /**
245
     * Gets array of child nodes
246
     *
247
     * @return ProjectionNode[]|ExpandedProjectionNode[]
248
     */
249
    public function getChildNodes()
250
    {
251
        return $this->_childNodes;
252
    }
253
254
    /**
255
     * Number of results to be skipped for this node, null means return all
256
     * results, when this node represents an expanded navigation property
257
     * then skip count will be null, If this node is the root of projection
258
     * tree, then skip count will be value of $skip query option.
259
     *
260
     * @return int
261
     */
262
    public function getSkipCount()
263
    {
264
        return $this->_skipCount;
265
    }
266
267
    /**
268
     * Maximum number of results to be returned for this node, null means
269
     * return all results, when this node represents an expanded navigation
270
     * property then take count will be page size defined for the resource
271
     * set pointed by the navigation property, If this node is the root of
272
     * projection tree then take count will be the minimum among the page
273
     * size of the the resource set that the uri resource path points to and
274
     * the value of $top query option.
275
     *
276
     * @return int
277
     */
278
    public function getTakeCount()
279
    {
280
        return $this->_takeCount;
281
    }
282
283
    /**
284
     * Gets the maximum number of expected result.
285
     *
286
     * @return int
287
     */
288
    public function getMaxResultCount()
289
    {
290
        return $this->_maxResultCount;
291
    }
292
293
    /**
294
     * Gets the sort information associated with the expanded navigation
295
     * property or root of 'Projection Tree'.
296
     *
297
     * @return InternalOrderByInfo|null
298
     */
299
    public function getInternalOrderByInfo()
300
    {
301
        return $this->_internalOrderByInfo;
302
    }
303
304
    /**
305
     * To set selection status of this node, When we have seen a $select
306
     * path segment that selects the expanded property represented by
307
     * this node then this function will be used to mark this node as selected.
308
     *
309
     * @param boolean $isSelectionFound True if selection found in this node
310
     *                                  False otherwise.
311
     *
312
     * @return void
313
     */
314
    public function setSelectionFound($isSelectionFound = true)
315
    {
316
        $this->_selectionFound = $isSelectionFound;
317
    }
318
319
    /**
320
     * To check whether this node is selected or not
321
     *
322
     * @return boolean
323
     */
324
    public function isSelectionFound()
325
    {
326
        return $this->_selectionFound;
327
    }
328
329
    /**
330
     * To set the flag indicating whether to include all immediate properties
331
     * of this node in the result or not, When we have seen a '*' in the
332
     * $select path segment, then this function will be used to set the flag
333
     * for immediate properties inclusion.
334
     *
335
     * @param boolean $selectAllImmediateProperties True if all immediate
336
     *                                              properties to be included
337
     *                                              False otherwise.
338
     *
339
     * @return void
340
     */
341
    public function setSelectAllImmediateProperties(
342
        $selectAllImmediateProperties = true
343
    ) {
344
        $this->_selectAllImmediateProperties = $selectAllImmediateProperties;
345
    }
346
347
    /**
348
     * To check whether immediate properties of the navigation property
349
     * represented by this node is to be included in the result or not.
350
     *
351
     * @return boolean
352
     */
353
    public function canSelectAllImmediateProperties()
354
    {
355
        return $this->_selectAllImmediateProperties;
356
    }
357
358
    /**
359
     * Whether all child properties of this node can be selected or not,
360
     * all child properties will be selected in 2 cases
361
     * (1) When flag for selection of all immediate properties is true
362
     *     $select=A/B/*
363
     *      Here 'immediate properties inclusion flag' will be true for B
364
     * (2) When flag for selection of this subtree is true
365
     *      $expand=A/B/D, A/B/C & $select = A/B
366
     *      Here 'subtree selection flag' will be true for B, C and D.
367
     *
368
     * @return boolean
369
     */
370
    public function canSelectAllProperties()
371
    {
372
        return $this->_selectSubtree || $this->_selectAllImmediateProperties;
373
    }
374
375
    /**
376
     * Find a child node with given name, if no such child node then
377
     * return NULL.
378
     *
379
     * @param string $propertyName Name of the property to get the
380
     *                             corresponding node.
381
     *
382
     * @return ProjectionNode|ExpandedProjectionNode|null
383
     */
384
    public function findNode($propertyName)
385
    {
386
        if (array_key_exists($propertyName, $this->_childNodes)) {
387
            return $this->_childNodes[$propertyName];
388
        }
389
390
        return null;
391
    }
392
393
    /**
394
     * To add a child node to the list of child nodes.
395
     *
396
     * @param ProjectionNode $node Node to add.
397
     *
398
     * @return void
399
     *
400
     * @throws InvalidArgumentException
401
     */
402
    public function addNode($node)
403
    {
404
        if (!($node instanceof ProjectionNode)
0 ignored issues
show
introduced by
$node is always a sub-type of POData\UriProcessor\Quer...onParser\ProjectionNode.
Loading history...
405
            && !($node instanceof ExpandedProjectionNode)
406
        ) {
407
            throw new \InvalidArgumentException(
408
                Messages::expandedProjectionNodeArgumentTypeShouldBeProjection()
409
            );
410
        }
411
412
        $this->_childNodes[$node->getPropertyName()] = $node;
413
    }
414
415
    /**
416
     * Mark the entire subtree as selected, for example
417
     * $expand=A/B/C/D/E & $select = A/B Here we need to select the entire
418
     * subtree of B i.e result should include all immedate properties of B
419
     * and associated C's, D's associated with each C and E's associated each D.
420
     *
421
     * @return void
422
     */
423
    public function markSubtreeAsSelected()
424
    {
425
        $this->_selectSubtree = true;
426
        $this->_selectAllImmediateProperties = false;
427
        foreach ($this->_childNodes as $node) {
428
            if ($node instanceof ExpandedProjectionNode) {
429
                    $node->markSubtreeAsSelected();
430
            }
431
        }
432
    }
433
434
    /**
435
     * Remove all child 'ExpandedProjectionNode's of this node which are
436
     * not selected, Recursively invoke the same function for selected
437
     * node, so that all unnecessary nodes will be removed from the subtree.
438
     *
439
     * @return void
440
     */
441
    public function removeNonSelectedNodes()
442
    {
443
        //Possilbe Node status flags are:
444
        //for $expand=A/B/C/D, X/Y
445
        // | SF | SST |
446
        // | T  | F   |  For $select=A/B, this is status of A
447
        // | T  | T   |  For $select=A/B, this is status of B
448
        // | F  | T   |  For $select=A/B, this is status of C and D
449
        // | F  | F   |  For $select=A/B, this is status of X and Y
450
        //
451
        foreach ($this->_childNodes as $propertyName => $node) {
452
            if ($node instanceof ExpandedProjectionNode) {
453
                if (!$this->_selectSubtree && !$node->_selectionFound) {
454
                    unset($this->_childNodes[$propertyName]);
455
                } else {
456
                    $node->removeNonSelectedNodes();
457
                }
458
            }
459
        }
460
    }
461
462
    /**
463
     * Remove explicity included nodes which already included implicitly, For
464
     * an expand navigation property, all immediate properties will be
465
     * implicitly selected if that navigation property is the last segment of
466
     * expand path or if there is a '*' token present after the naivgation
467
     * property, this function remove all explicity included 'ProjectionNode's
468
     * which already included implicitly.
469
     *
470
     * @return void
471
     */
472
    public function removeNodesAlreadyIncludedImplicitly()
473
    {
474
        //$select=A/B, A/B/guid, A/B/Name
475
        //Here A/B cause to implcilty include all immeiate properties of B
476
        //so remove explicitly included 'ProjectionNode' for guid and Name
477
        if ($this->_selectSubtree) {
478
            foreach ($this->_childNodes as $propertyName => $node) {
479
                if ($node instanceof ExpandedProjectionNode) {
480
                    $node->_selectSubtree = true;
481
                    $node->removeNodesAlreadyIncludedImplicitly();
482
                } else {
483
                    unset($this->_childNodes[$propertyName]);
484
                }
485
            }
486
487
            $this->_selectAllImmediateProperties = false;
488
            return;
489
        }
490
491
        //$select=A/B/*, A/B/guid, A/B/Name
492
        //Here A/B/* cause to implcitly include all immediate properties of B
493
        //so remove explicitly included 'ProjectionNode' for guid and Name
494
        foreach ($this->_childNodes as $propertyName => $node) {
495
            if ($node instanceof ExpandedProjectionNode) {
496
                $node->removeNodesAlreadyIncludedImplicitly();
497
            } else if ($this->_selectAllImmediateProperties) {
498
                unset($this->_childNodes[$propertyName]);
499
            }
500
        }
501
    }
502
503
    /**
504
     * Sort the selected nodes such that order is same as the order in which
505
     * the properties are appear in the owning type.
506
     *
507
     * @return void
508
     */
509
    public function sortNodes()
510
    {
511
        if (count($this->_childNodes) > 0) {
512
            foreach ($this->_childNodes as $childNode) {
513
                if ($childNode instanceof ExpandedProjectionNode) {
514
                        $childNode->sortNodes();
515
                }
516
            }
517
518
            //We are applying sorting in bottom-up fashion, do it only we have
519
            // more than 1 child
520
            if (count($this->_childNodes) > 1) {
521
                $existingNodes = $this->_childNodes;
522
                $this->_childNodes = array();
523
                foreach ($this->getResourceType()->getAllProperties()
524
                    as $resourceProperty) {
525
                    $propertyName = $resourceProperty->getName();
526
                    if (array_key_exists($propertyName, $existingNodes)) {
527
                        $this->_childNodes[$propertyName]
528
                            = $existingNodes[$propertyName];
529
                    }
530
                }
531
            }
532
        }
533
    }
534
}
535