Test Setup Failed
Pull Request — master (#102)
by Alex
03:26
created

ProvidersWrapper::getRelatedResourceSet()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 25
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 25
rs 8.8571
c 0
b 0
f 0
cc 1
eloc 22
nc 1
nop 10

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\Providers;
4
5
use POData\Common\InvalidOperationException;
6
use POData\Common\Messages;
7
use POData\Common\ODataException;
8
use POData\Configuration\IServiceConfiguration;
9
use POData\Providers\Expression\IExpressionProvider;
10
use POData\Providers\Metadata\EdmSchemaVersion;
11
use POData\Providers\Metadata\IMetadataProvider;
12
use POData\Providers\Metadata\ResourceAssociationSet;
13
use POData\Providers\Metadata\ResourceEntityType;
14
use POData\Providers\Metadata\ResourceProperty;
15
use POData\Providers\Metadata\ResourceSet;
16
use POData\Providers\Metadata\ResourceSetWrapper;
17
use POData\Providers\Metadata\ResourceType;
18
use POData\Providers\Metadata\ResourceTypeKind;
19
use POData\Providers\Query\IQueryProvider;
20
use POData\Providers\Query\QueryResult;
21
use POData\Providers\Query\QueryType;
22
use POData\UriProcessor\QueryProcessor\ExpressionParser\FilterInfo;
23
use POData\UriProcessor\QueryProcessor\OrderByParser\InternalOrderByInfo;
24
use POData\UriProcessor\QueryProcessor\SkipTokenParser\InternalSkipTokenInfo;
25
use POData\UriProcessor\QueryProcessor\SkipTokenParser\SkipTokenInfo;
26
use POData\UriProcessor\ResourcePathProcessor\SegmentParser\KeyDescriptor;
27
28
/**
29
 * Class ProvidersWrapper.
30
 *
31
 * A wrapper class over IMetadataProvider and IQueryProvider implementations, All calls to implementation of methods
32
 * of these interfaces should go through this wrapper class so that wrapper methods of this class can perform validation
33
 */
34
class ProvidersWrapper
35
{
36
    /**
37
     * Holds reference to IMetadataProvider implementation.
38
     *
39
     * @var IMetadataProvider
40
     */
41
    private $metaProvider;
42
43
    /**
44
     * Holds reference to IServiceConfiguration implementation.
45
     *
46
     * @var IServiceConfiguration
47
     */
48
    private $config;
49
50
    /*
51
     * Holds reference to ProvidersQueryWrapper implementation
52
     *
53
     * @var ProvidersQueryWrapper
54
     */
55
    private $providerWrapper;
56
57
    /**
58
     * Cache for ResourceProperties of a resource type that belongs to a
59
     * resource set. An entry (ResourceProperty collection) in this cache
60
     * contains only the visible properties of ResourceType.
61
     *
62
     * @var array(string, array(string, ResourceProperty))
63
     */
64
    private $propertyCache;
65
66
    /**
67
     * Cache for ResourceSetWrappers. If ResourceSet is invisible value will
68
     * be null.
69
     *
70
     * @var ResourceSetWrapper[] indexed by resource set name
71
     */
72
    private $setWrapperCache;
73
74
    /**
75
     * Cache for ResourceTypes.
76
     *
77
     * @var ResourceType[] indexed by resource type name
78
     */
79
    private $typeCache;
80
81
    /**
82
     * Cache for ResourceAssociationSet. If ResourceAssociationSet is invisible
83
     * value will be null.
84
     *
85
     * @var ResourceAssociationSet[] indexed by name
86
     */
87
    private $associationSetCache;
0 ignored issues
show
Unused Code introduced by
The property $associationSetCache is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
88
89
    /**
90
     * Creates a new instance of ProvidersWrapper.
91
     *
92
     * @param IMetadataProvider     $meta   Reference to IMetadataProvider implementation
93
     * @param IQueryProvider        $query  Reference to IQueryProvider implementation
94
     * @param IServiceConfiguration $config Reference to IServiceConfiguration implementation
95
     */
96
    public function __construct(IMetadataProvider $meta, IQueryProvider $query, IServiceConfiguration $config)
97
    {
98
        $this->metaProvider = $meta;
99
        $this->config = $config;
100
        $this->providerWrapper = new ProvidersQueryWrapper($query);
101
        $this->setWrapperCache = [];
102
        $this->typeCache = [];
103
        $this->propertyCache = [];
104
    }
105
106
    //Wrappers for IMetadataProvider methods
107
108
    /**
109
     * To get the Container name for the data source,
110
     * Note: Wrapper for IMetadataProvider::getContainerName method
111
     * implementation.
112
     *
113
     * @throws ODataException Exception if implementation returns empty container name
114
     *
115
     * @return string that contains the name of the container
116
     */
117
    public function getContainerName()
118
    {
119
        $containerName = $this->metaProvider->getContainerName();
120
        if (empty($containerName)) {
121
            throw new ODataException(
122
                Messages::providersWrapperContainerNameMustNotBeNullOrEmpty(),
123
                500
124
            );
125
        }
126
127
        return $containerName;
128
    }
129
130
    /**
131
     * To get Namespace name for the data source,
132
     * Note: Wrapper for IMetadataProvider::getContainerNamespace method implementation.
133
     *
134
     * @throws ODataException Exception if implementation returns empty container namespace
135
     *
136
     * @return string that contains the namespace name
137
     */
138
    public function getContainerNamespace()
139
    {
140
        $containerNamespace = $this->metaProvider->getContainerNamespace();
141
        if (empty($containerNamespace)) {
142
            throw new ODataException(
143
                Messages::providersWrapperContainerNamespaceMustNotBeNullOrEmpty(),
144
                500
145
            );
146
        }
147
148
        return $containerNamespace;
149
    }
150
151
    /**
152
     * To get the data service configuration.
153
     *
154
     * @return IServiceConfiguration
155
     */
156
    public function getConfiguration()
157
    {
158
        return $this->config;
159
    }
160
161
    /**
162
     *  To get all entity set information,
163
     *  Note: Wrapper for IMetadataProvider::getResourceSets method implementation,
164
     *  This method returns array of ResourceSetWrapper instances but the corresponding IDSMP method
165
     *  returns array of ResourceSet instances.
166
     *
167
     *  @throws ODataException when two resource sets with the same name are encountered
168
     *
169
     *  @return ResourceSetWrapper[] The ResourceSetWrappers for the visible ResourceSets
170
     */
171
    public function getResourceSets()
172
    {
173
        $resourceSets = $this->metaProvider->getResourceSets();
174
        $resourceSetWrappers = [];
175
        $resourceSetNames = [];
176
        foreach ($resourceSets as $resourceSet) {
177
            $name = $resourceSet->getName();
178
            if (in_array($name, $resourceSetNames)) {
179
                throw new ODataException(Messages::providersWrapperEntitySetNameShouldBeUnique($name), 500);
180
            }
181
182
            $resourceSetNames[] = $name;
183
            $resourceSetWrapper = $this->_validateResourceSetAndGetWrapper($resourceSet);
184
            if (!is_null($resourceSetWrapper)) {
185
                $resourceSetWrappers[] = $resourceSetWrapper;
186
            }
187
        }
188
189
        return $resourceSetWrappers;
190
    }
191
192
    /**
193
     * This function perform the following operations
194
     *  (1) If the cache contain an entry [key, value] for the resourceset then
195
     *      return the entry-value
196
     *  (2) If the cache not contain an entry for the resourceset then validate
197
     *      the resourceset
198
     *            (a) If valid add entry as [resouceset_name, resourceSetWrapper]
199
     *            (b) if not valid add entry as [resouceset_name, null]
200
     *  Note: validating a resourceset means checking the resourceset is visible
201
     *  or not using configuration.
202
     *
203
     * @param ResourceSet $resourceSet The resourceset to validate and get the
204
     *                                 wrapper for
205
     *
206
     * @return ResourceSetWrapper|null Returns an instance if a resource set with the given name is visible
207
     */
208
    private function _validateResourceSetAndGetWrapper(ResourceSet $resourceSet)
209
    {
210
        $cacheKey = $resourceSet->getName();
211
        if (array_key_exists($cacheKey, $this->setWrapperCache)) {
212
            return $this->setWrapperCache[$cacheKey];
213
        }
214
215
        $this->validateResourceType($resourceSet->getResourceType());
216
        $wrapper = new ResourceSetWrapper($resourceSet, $this->config);
217
        $nuVal = $wrapper->isVisible() ? $wrapper : null;
218
        $this->setWrapperCache[$cacheKey] = $nuVal;
219
220
        return $this->setWrapperCache[$cacheKey];
221
    }
222
223
    /**
224
     * Validates the given instance of ResourceType.
225
     *
226
     * @param ResourceType $resourceType The ResourceType to validate
227
     *
228
     * @throws ODataException Exception if $resourceType is invalid
229
     *
230
     * @return ResourceType
231
     */
232
    private function validateResourceType(ResourceType $resourceType)
233
    {
234
        $cacheKey = $resourceType->getName();
235
        if (array_key_exists($cacheKey, $this->typeCache)) {
236
            return $this->typeCache[$cacheKey];
237
        }
238
239
        //TODO: Do validation if any for the ResourceType
240
        $this->typeCache[$cacheKey] = $resourceType;
241
242
        return $resourceType;
243
    }
244
245
    /**
246
     * To get all resource types in the data source,
247
     * Note: Wrapper for IMetadataProvider::getTypes method implementation.
248
     *
249
     * @return ResourceType[]
250
     */
251
    public function getTypes()
252
    {
253
        $resourceTypes = $this->metaProvider->getTypes();
254
        $resourceTypeNames = [];
255
        foreach ($resourceTypes as $resourceType) {
256
            if (in_array($resourceType->getName(), $resourceTypeNames)) {
257
                throw new ODataException(
258
                    Messages::providersWrapperEntityTypeNameShouldBeUnique($resourceType->getName()),
259
                    500
260
                );
261
            }
262
263
            $resourceTypeNames[] = $resourceType->getName();
264
            $this->validateResourceType($resourceType);
265
        }
266
267
        return $resourceTypes;
268
    }
269
270
    public function getSingletons()
271
    {
272
        $singletons = $this->metaProvider->getSingletons();
273
        return (null == $singletons) ? [] : $singletons;
274
    }
275
276
    /**
277
     * To get a resource set based on the specified resource set name which is
278
     * visible,
279
     * Note: Wrapper for IMetadataProvider::resolveResourceSet method
280
     * implementation.
281
     *
282
     * @param string $name Name of the resource set
283
     *
284
     * @return ResourceSetWrapper|null Returns resource set with the given name if found,
285
     *                                 NULL if resource set is set to invisible or not found
286
     */
287
    public function resolveResourceSet($name)
288
    {
289
        if (array_key_exists($name, $this->setWrapperCache)) {
290
            return $this->setWrapperCache[$name];
291
        }
292
293
        $resourceSet = $this->metaProvider->resolveResourceSet($name);
294
        if (is_null($resourceSet)) {
295
            return null;
296
        }
297
298
        return $this->_validateResourceSetAndGetWrapper($resourceSet);
299
    }
300
301
    /**
302
     * To get a resource type based on the resource set name,
303
     * Note: Wrapper for IMetadataProvider::resolveResourceType
304
     * method implementation.
305
     *
306
     * @param string $name Name of the resource set
307
     *
308
     * @throws ODataException If the ResourceType is invalid
309
     *
310
     * @return ResourceType|null resource type with the given resource set name if found else NULL
311
     */
312
    public function resolveResourceType($name)
313
    {
314
        $resourceType = $this->metaProvider->resolveResourceType($name);
315
        if (is_null($resourceType)) {
316
            return null;
317
        }
318
319
        return $this->validateResourceType($resourceType);
320
    }
321
322
323
    public function resolveSingleton($name)
324
    {
325
        $singletons = $this->metaProvider->getSingletons();
326
        if (array_key_exists($name, $singletons)) {
327
            return $singletons[$name];
328
        }
329
        return null;
330
    }
331
332
    /**
333
     * The method must return a collection of all the types derived from
334
     * $resourceType The collection returned should NOT include the type
335
     * passed in as a parameter
336
     * Note: Wrapper for IMetadataProvider::getDerivedTypes
337
     * method implementation.
338
     *
339
     * @param ResourceType $resourceType Resource to get derived resource types from
340
     *
341
     * @throws InvalidOperationException when the meat provider doesn't return an array
342
     *
343
     * @return ResourceType[]
344
     */
345
    public function getDerivedTypes(ResourceType $resourceType)
346
    {
347
        $derivedTypes = $this->metaProvider->getDerivedTypes($resourceType);
0 ignored issues
show
Compatibility introduced by
$resourceType of type object<POData\Providers\Metadata\ResourceType> is not a sub-type of object<POData\Providers\...ata\ResourceEntityType>. It seems like you assume a child class of the class POData\Providers\Metadata\ResourceType to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
348
        if (!is_array($derivedTypes)) {
349
            throw new InvalidOperationException(
350
                Messages::metadataAssociationTypeSetInvalidGetDerivedTypesReturnType($resourceType->getName())
351
            );
352
        }
353
354
        foreach ($derivedTypes as $derivedType) {
355
            $this->validateResourceType($derivedType);
356
        }
357
358
        return $derivedTypes;
359
    }
360
361
    /**
362
     * Returns true if $resourceType represents an Entity Type which has derived
363
     * Entity Types, else false.
364
     * Note: Wrapper for IMetadataProvider::hasDerivedTypes method
365
     * implementation.
366
     *
367
     * @param ResourceType $resourceType Resource to check for derived resource
368
     *                                   types
369
     *
370
     * @throws ODataException If the ResourceType is invalid
371
     *
372
     * @return bool
373
     */
374
    public function hasDerivedTypes(ResourceType $resourceType)
375
    {
376
        $this->validateResourceType($resourceType);
377
378
        return $this->metaProvider->hasDerivedTypes($resourceType);
0 ignored issues
show
Compatibility introduced by
$resourceType of type object<POData\Providers\Metadata\ResourceType> is not a sub-type of object<POData\Providers\...ata\ResourceEntityType>. It seems like you assume a child class of the class POData\Providers\Metadata\ResourceType to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
379
    }
380
381
    /**
382
     * Gets the visible resource properties for the given resource type from the given resource set wrapper.
383
     *
384
     * @param ResourceSetWrapper $setWrapper Resource set wrapper in question
385
     * @param ResourceType $resourceType Resource type in question
386
     *
387
     * @return ResourceProperty[] Collection of visible resource properties from the given resource set wrapper
388
     *                            and resource type
389
     */
390
    public function getResourceProperties(ResourceSetWrapper $setWrapper, ResourceType $resourceType)
391
    {
392
        if ($resourceType->getResourceTypeKind() != ResourceTypeKind::ENTITY) {
393
            //Complex resource type
394
            return $resourceType->getAllProperties();
395
        }
396
        //TODO: move this to doctrine annotations
397
        $cacheKey = $setWrapper->getName() . '_' . $resourceType->getFullName();
398
        if (!array_key_exists($cacheKey, $this->propertyCache)) {
399
            //Fill the cache
400
            $this->propertyCache[$cacheKey] = [];
401
            foreach ($resourceType->getAllProperties() as $resourceProperty) {
402
                //Check whether this is a visible navigation property
403
                //TODO: is this broken?? see #87
404
                if ($resourceProperty->getTypeKind() == ResourceTypeKind::ENTITY
405
                    && !is_null($this->getResourceSetWrapperForNavigationProperty(
406
                        $setWrapper,
407
                        $resourceType,
0 ignored issues
show
Compatibility introduced by
$resourceType of type object<POData\Providers\Metadata\ResourceType> is not a sub-type of object<POData\Providers\...ata\ResourceEntityType>. It seems like you assume a child class of the class POData\Providers\Metadata\ResourceType to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
408
                        $resourceProperty
409
                    ))
410
                ) {
411
                    $this->propertyCache[$cacheKey][$resourceProperty->getName()] = $resourceProperty;
412
                } else {
413
                    //primitive, bag or complex property
414
                    $this->propertyCache[$cacheKey][$resourceProperty->getName()] = $resourceProperty;
415
                }
416
            }
417
        }
418
419
        return $this->propertyCache[$cacheKey];
420
    }
421
422
    /**
423
     * Gets the target resource set wrapper for the given navigation property,
424
     * source resource set wrapper and the source resource type.
425
     *
426
     * @param ResourceSetWrapper $resourceSetWrapper Source resource set
427
     * @param ResourceEntityType $resourceType Source resource type
428
     * @param ResourceProperty   $navigationResourceProperty Navigation property
429
     *
430
     * @return ResourceSetWrapper|null Returns instance of ResourceSetWrapper
431
     *                                 (describes the entity set and associated configuration) for the
432
     *                                 given navigation property. returns NULL if resourceset for the
433
     *                                 navigation property is invisible or if metadata provider returns
434
     *                                 null resource association set
435
     */
436
    public function getResourceSetWrapperForNavigationProperty(
437
        ResourceSetWrapper $resourceSetWrapper,
438
        ResourceEntityType $resourceType,
439
        ResourceProperty $navigationResourceProperty
440
    ) {
441
        $associationSet = $this->getResourceAssociationSet(
442
            $resourceSetWrapper,
443
            $resourceType,
444
            $navigationResourceProperty
445
        );
446
447
        if (!is_null($associationSet)) {
448
            $relatedAssociationSetEnd = $associationSet->getRelatedResourceAssociationSetEnd(
449
                $resourceSetWrapper->getResourceSet(),
450
                $resourceType,
451
                $navigationResourceProperty
452
            );
453
454
            return $this->_validateResourceSetAndGetWrapper(
455
                $relatedAssociationSetEnd->getResourceSet()
456
            );
457
        }
458
        return null;
459
    }
460
461
    /**
462
     * Gets the ResourceAssociationSet instance for the given source association end,
463
     * Note: Wrapper for IMetadataProvider::getResourceAssociationSet
464
     * method implementation.
465
     *
466
     * @param ResourceSet           $set      Resource set of the source association end
467
     * @param ResourceEntityType    $type     Resource type of the source association end
468
     * @param ResourceProperty      $property Resource property of the source association end
469
     *
470
     * @return ResourceAssociationSet|null Returns ResourceAssociationSet for the source
471
     *                                     association end, NULL if no such
472
     *                                     association end or resource set in the
473
     *                                     other end of the association is invisible
474
     */
475
    public function getResourceAssociationSet(
476
        ResourceSet $set,
477
        ResourceEntityType $type,
478
        ResourceProperty $property
479
    ) {
480
        $type = $this->getResourceTypeWherePropertyIsDeclared($type, $property);
481
        // usage below requires $type to not be null - so kaboom as early as possible
482
        assert(null != $type, 'Resource type obtained from property must not be null.');
483
484
        $associationSet = $this->metaProvider->getResourceAssociationSet(
485
            $set,
486
            $type,
0 ignored issues
show
Compatibility introduced by
$type of type object<POData\Providers\Metadata\ResourceType> is not a sub-type of object<POData\Providers\...ata\ResourceEntityType>. It seems like you assume a child class of the class POData\Providers\Metadata\ResourceType to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
487
            $property
488
        );
489
        assert(
490
            null == $associationSet || $associationSet instanceof ResourceAssociationSet,
491
            "Retrieved resource assocation must be either null or an instance of ResourceAssociationSet"
492
        );
493
494
        if (!is_null($associationSet)) {
495
            $thisAssociationSetEnd = $associationSet->getResourceAssociationSetEnd(
496
                $set,
497
                $type,
0 ignored issues
show
Compatibility introduced by
$type of type object<POData\Providers\Metadata\ResourceType> is not a sub-type of object<POData\Providers\...ata\ResourceEntityType>. It seems like you assume a child class of the class POData\Providers\Metadata\ResourceType to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
498
                $property
499
            );
500
501
            $relatedAssociationSetEnd = $associationSet->getRelatedResourceAssociationSetEnd(
502
                $set,
503
                $type,
0 ignored issues
show
Compatibility introduced by
$type of type object<POData\Providers\Metadata\ResourceType> is not a sub-type of object<POData\Providers\...ata\ResourceEntityType>. It seems like you assume a child class of the class POData\Providers\Metadata\ResourceType to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
504
                $property
505
            );
506
507
            //If either $thisAssociationSetEnd and/or $relatedAssociationSetEnd
0 ignored issues
show
Unused Code Comprehensibility introduced by
46% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
508
            //is null means the associationset we got from the IDSMP::getResourceAssociationSet is invalid.
509
510
            //Return null, if either AssociationSet's End1 or End2's resourceset name
511
            //doesn't match the name of resource set wrapper (param1) and resource type is not assignable
512
            //from given resource type (param2)
513
            if (is_null($thisAssociationSetEnd) || is_null($relatedAssociationSetEnd)) {
514
                throw new ODataException(
515
                    Messages::providersWrapperIDSMPGetResourceSetReturnsInvalidResourceSet(
516
                        $set->getName(),
517
                        $type->getFullName(),
518
                        $property->getName()
519
                    ),
520
                    500
521
                );
522
            }
523
524
            $relatedResourceSetWrapper = $this->_validateResourceSetAndGetWrapper(
525
                $relatedAssociationSetEnd->getResourceSet()
526
            );
527
            if ($relatedResourceSetWrapper === null) {
528
                $associationSet = null;
529
            } else {
530
                $this->validateResourceType($thisAssociationSetEnd->getResourceType());
531
                $this->validateResourceType($relatedAssociationSetEnd->getResourceType());
532
            }
533
        }
534
        assert(
535
            null == $associationSet || $associationSet instanceof ResourceAssociationSet,
536
            "Retrieved resource assocation must be either null or an instance of ResourceAssociationSet"
537
        );
538
539
        return $associationSet;
540
    }
541
542
    /**
543
     * Gets the resource type on which the resource property is declared on,
544
     * If property is not declared in the given resource type, then this
545
     * function drill down to the inheritance hierarchy of the given resource
546
     * type to find out the base class in which the property is declared.
547
     *
548
     * @param ResourceType     $type     The resource type to start looking
549
     * @param ResourceProperty $property The resource property in question
550
     *
551
     * @return ResourceType|null Returns reference to the ResourceType on which
552
     *                           the $property is declared, NULL if
553
     *                           $property is not declared anywhere
554
     *                           in the inheritance hierarchy
555
     */
556
    private function getResourceTypeWherePropertyIsDeclared(ResourceType $type, ResourceProperty $property)
557
    {
558
        while (null !== $type) {
559
            if (null !== $type->resolvePropertyDeclaredOnThisType($property->getName())) {
560
                break;
561
            }
562
563
            $type = $type->getBaseType();
564
        }
565
566
        return $type;
567
    }
568
569
    /**
570
     * Wrapper function over _validateResourceSetAndGetWrapper function.
571
     *
572
     * @param ResourceSet $resourceSet see the comments of _validateResourceSetAndGetWrapper
573
     *
574
     * @return ResourceSetWrapper|null see the comments of _validateResourceSetAndGetWrapper
575
     */
576
    public function validateResourceSetAndGetWrapper(ResourceSet $resourceSet)
577
    {
578
        return $this->_validateResourceSetAndGetWrapper($resourceSet);
579
    }
580
581
    /**
582
     * Gets the Edm Schema version compliance to the metadata.
583
     *
584
     * @return EdmSchemaVersion
585
     */
586
    public function getEdmSchemaVersion()
587
    {
588
        //The minimal schema version for custom provider is 1.1
589
        return EdmSchemaVersion::VERSION_1_DOT_1;
590
    }
591
592
    /**
593
     * Gets the underlying custom expression provider, the end developer is
594
     * responsible for implementing IExpressionProvider if he choose for.
595
     *
596
     * @return IExpressionProvider Instance of IExpressionProvider implementation
597
     */
598
    public function getExpressionProvider()
599
    {
600
        return $this->providerWrapper->getExpressionProvider();
601
    }
602
603
    /**
604
     * Indicates if the QueryProvider can handle ordered paging, this means respecting order, skip, and top parameters
605
     * If the query provider can not handle ordered paging, it must return the entire result set and POData will
606
     * perform the ordering and paging.
607
     *
608
     * @return bool True if the query provider can handle ordered paging, false if POData should perform the paging
609
     */
610
    public function handlesOrderedPaging()
611
    {
612
        return $this->providerWrapper->handlesOrderedPaging();
613
    }
614
615
    /**
616
     * Gets collection of entities belongs to an entity set.
617
     *
618
     * @param QueryType             $queryType   Indicates if this is a query for a count, entities, or entities with a
619
     *                                           count
620
     * @param ResourceSet           $resourceSet The entity set containing the entities that need to be fetched
621
     * @param FilterInfo            $filterInfo  Represents the $filter parameter of the OData query.
622
     *                                           NULL if no $filter specified
623
     * @param InternalOrderByInfo   $orderBy     The orderBy information
624
     * @param int                   $top         The top count
625
     * @param int                   $skip        The skip count
626
     * @param InternalSkipTokenInfo $skipToken   The skip token
627
     *
628
     * @return QueryResult
629
     */
630
    public function getResourceSet(
631
        QueryType $queryType,
632
        ResourceSet $resourceSet,
633
        FilterInfo $filterInfo = null,
634
        InternalOrderByInfo $orderBy = null,
635
        $top = null,
636
        $skip = null,
637
        SkipTokenInfo $skipToken = null
638
    ) {
639
        return $this->providerWrapper->getResourceSet(
640
            $queryType,
641
            $resourceSet,
642
            $filterInfo,
643
            $orderBy,
644
            $top,
645
            $skip,
646
            $skipToken
647
        );
648
    }
649
650
    /**
651
     * Gets an entity instance from an entity set identified by a key.
652
     *
653
     * @param ResourceSet   $resourceSet   The entity set containing the entity to fetch
654
     * @param KeyDescriptor $keyDescriptor The key identifying the entity to fetch
655
     *
656
     * @return object|null Returns entity instance if found else null
657
     */
658
    public function getResourceFromResourceSet(ResourceSet $resourceSet, KeyDescriptor $keyDescriptor)
659
    {
660
        return $this->providerWrapper->getResourceFromResourceSet($resourceSet, $keyDescriptor);
661
    }
662
663
    /**
664
     * Puts an entity instance to entity set identified by a key.
665
     *
666
     * @param ResourceSet   $resourceSet   The entity set containing the entity to update
667
     * @param KeyDescriptor $keyDescriptor The key identifying the entity to update
668
     *
669
     * @return bool|null Returns result of executiong query
670
     */
671
    public function putResource(
672
        ResourceSet $resourceSet,
673
        KeyDescriptor $keyDescriptor,
674
        $data
675
    ) {
676
        return $this->providerWrapper->putResource(
677
            $resourceSet,
678
            $keyDescriptor,
679
            $data
680
        );
681
    }
682
683
    /**
684
     * Get related resource set for a resource.
685
     *
686
     * @param QueryType             $queryType         Indicates if this is a query for a count, entities, or entities
687
     *                                                 with a count
688
     * @param ResourceSet           $sourceResourceSet The entity set containing the source entity
689
     * @param object                $sourceEntity      The source entity instance
690
     * @param ResourceSet           $targetResourceSet The resource set containing the target of the navigation property
691
     * @param ResourceProperty      $targetProperty    The navigation property to retrieve
692
     * @param FilterInfo|null       $filterInfo        Represents the $filter parameter of the OData query.
693
     *                                                 NULL if no $filter specified
694
     * @param mixed                 $orderBy           sorted order if we want to get the data in some specific order
695
     * @param int                   $top                  number of records which need to be retrieved
696
     * @param int                   $skip                 number of records which need to be skipped
697
     * @param SkipTokenInfo|null    $skipToken            value indicating what records to skip
698
     *
699
     * @throws ODataException
700
     *
701
     * @return QueryResult
702
     */
703
    public function getRelatedResourceSet(
704
        QueryType $queryType,
705
        ResourceSet $sourceResourceSet,
706
        $sourceEntity,
707
        ResourceSet $targetResourceSet,
708
        ResourceProperty $targetProperty,
709
        $filterInfo,
710
        $orderBy,
711
        $top,
712
        $skip,
713
        SkipTokenInfo $skipToken = null
714
    ) {
715
        return $this->providerWrapper->getRelatedResourceSet(
716
            $queryType,
717
            $sourceResourceSet,
718
            $sourceEntity,
719
            $targetResourceSet,
720
            $targetProperty,
721
            $filterInfo,
0 ignored issues
show
Bug introduced by
It seems like $filterInfo defined by parameter $filterInfo on line 709 can be null; however, POData\Providers\Provide...getRelatedResourceSet() does not accept null, maybe add an additional type check?

It seems like you allow that null is being passed for a parameter, however the function which is called does not seem to accept null.

We recommend to add an additional type check (or disallow null for the parameter):

function notNullable(stdClass $x) { }

// Unsafe
function withoutCheck(stdClass $x = null) {
    notNullable($x);
}

// Safe - Alternative 1: Adding Additional Type-Check
function withCheck(stdClass $x = null) {
    if ($x instanceof stdClass) {
        notNullable($x);
    }
}

// Safe - Alternative 2: Changing Parameter
function withNonNullableParam(stdClass $x) {
    notNullable($x);
}
Loading history...
722
            $orderBy,
723
            $top,
724
            $skip,
725
            $skipToken
726
        );
727
    }
728
729
    /**
730
     * Gets a related entity instance from an entity set identified by a key.
731
     *
732
     * @param ResourceSet      $sourceResourceSet The entity set related to the entity to be fetched
733
     * @param object           $sourceEntity      The related entity instance
734
     * @param ResourceSet      $targetResourceSet The entity set from which entity needs to be fetched
735
     * @param ResourceProperty $targetProperty    The metadata of the target property
736
     * @param KeyDescriptor    $keyDescriptor     The key to identify the entity to be fetched
737
     *
738
     * @return object|null Returns entity instance if found else null
739
     */
740
    public function getResourceFromRelatedResourceSet(
741
        ResourceSet $sourceResourceSet,
742
        $sourceEntity,
743
        ResourceSet $targetResourceSet,
744
        ResourceProperty $targetProperty,
745
        KeyDescriptor $keyDescriptor
746
    ) {
747
        return $this->providerWrapper->getResourceFromRelatedResourceSet(
748
            $sourceResourceSet,
749
            $sourceEntity,
750
            $targetResourceSet,
751
            $targetProperty,
752
            $keyDescriptor
753
        );
754
    }
755
756
    /**
757
     * Get related resource for a resource.
758
     *
759
     * @param ResourceSet      $sourceResourceSet The source resource set
760
     * @param object           $sourceEntity      The source resource
761
     * @param ResourceSet      $targetResourceSet The resource set of the navigation
762
     *                                            property
763
     * @param ResourceProperty $targetProperty    The navigation property to be
764
     *                                            retrieved
765
     *
766
     * @return object|null The related resource if exists else null
767
     */
768
    public function getRelatedResourceReference(
769
        ResourceSet $sourceResourceSet,
770
        $sourceEntity,
771
        ResourceSet $targetResourceSet,
772
        ResourceProperty $targetProperty
773
    ) {
774
        return $this->providerWrapper->getRelatedResourceReference(
775
            $sourceResourceSet,
776
            $sourceEntity,
777
            $targetResourceSet,
778
            $targetProperty
779
        );
780
    }
781
782
    /**
783
     * Updates a resource.
784
     *
785
     * @param ResourceSet   $sourceResourceSet    The entity set containing the source entity
786
     * @param object        $sourceEntityInstance The source entity instance
787
     * @param KeyDescriptor $keyDescriptor        The key identifying the entity to fetch
788
     * @param object        $data                 The New data for the entity instance.
789
     * @param bool          $shouldUpdate         Should undefined values be updated or reset to default
790
     *
791
     * @return object|null The new resource value if it is assignable or throw exception for null.
792
     */
793
    public function updateResource(
794
        ResourceSet $sourceResourceSet,
795
        $sourceEntityInstance,
796
        KeyDescriptor $keyDescriptor,
797
        $data,
798
        $shouldUpdate = false
799
    ) {
800
        return $this->providerWrapper->updateResource(
801
            $sourceResourceSet,
802
            $sourceEntityInstance,
803
            $keyDescriptor,
804
            $data,
805
            $shouldUpdate
806
        );
807
    }
808
809
    /**
810
     * Delete resource from a resource set.
811
     *
812
     * @param ResourceSet $sourceResourceSet
813
     * @param object      $sourceEntityInstance
814
     *
815
     * return bool true if resources sucessfully deteled, otherwise false.
816
     */
817
    public function deleteResource(
818
        ResourceSet $sourceResourceSet,
819
        $sourceEntityInstance
820
    ) {
821
        return $this->providerWrapper->deleteResource(
822
            $sourceResourceSet,
823
            $sourceEntityInstance
824
        );
825
    }
826
827
    /**
828
     * @param ResourceSet $resourceSet          The entity set containing the entity to fetch
829
     * @param object      $sourceEntityInstance The source entity instance
830
     * @param object      $data                 The New data for the entity instance.
831
     *
832
     * returns object|null returns the newly created model if sucessful or null if model creation failed.
833
     */
834
    public function createResourceforResourceSet(
835
        ResourceSet $resourceSet,
836
        $sourceEntityInstance,
837
        $data
838
    ) {
839
        return $this->providerWrapper->createResourceforResourceSet(
840
            $resourceSet,
841
            $sourceEntityInstance,
842
            $data
843
        );
844
    }
845
846
    public function getMetadataXML()
847
    {
848
        return $this->metaProvider->getXML();
849
    }
850
}
851