Test Setup Failed
Push — master ( 0a3e88...820bc9 )
by Christopher
04:41
created

getResourceSetWrapperForNavigationProperty()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 24
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 24
rs 8.9713
c 1
b 0
f 0
cc 2
eloc 16
nc 2
nop 3
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\ResourcePathProcessor\SegmentParser\KeyDescriptor;
26
27
/**
28
 * Class ProvidersWrapper.
29
 *
30
 * A wrapper class over IMetadataProvider and IQueryProvider implementations, All calls to implementation of methods
31
 * of these interfaces should go through this wrapper class so that wrapper methods of this class can perform validation
32
 */
33
class ProvidersWrapper
34
{
35
    /**
36
     * Holds reference to IMetadataProvider implementation.
37
     *
38
     * @var IMetadataProvider
39
     */
40
    private $metaProvider;
41
42
    /**
43
     * Holds reference to IServiceConfiguration implementation.
44
     *
45
     * @var IServiceConfiguration
46
     */
47
    private $config;
48
49
    /*
50
     * Holds reference to ProvidersQueryWrapper implementation
51
     *
52
     * @var ProvidersQueryWrapper
53
     */
54
    private $providerWrapper;
55
56
    /**
57
     * Cache for ResourceProperties of a resource type that belongs to a
58
     * resource set. An entry (ResourceProperty collection) in this cache
59
     * contains only the visible properties of ResourceType.
60
     *
61
     * @var array(string, array(string, ResourceProperty))
62
     */
63
    private $propertyCache;
64
65
    /**
66
     * Cache for ResourceSetWrappers. If ResourceSet is invisible value will
67
     * be null.
68
     *
69
     * @var ResourceSetWrapper[] indexed by resource set name
70
     */
71
    private $setWrapperCache;
72
73
    /**
74
     * Cache for ResourceTypes.
75
     *
76
     * @var ResourceType[] indexed by resource type name
77
     */
78
    private $typeCache;
79
80
    /**
81
     * Cache for ResourceAssociationSet. If ResourceAssociationSet is invisible
82
     * value will be null.
83
     *
84
     * @var ResourceAssociationSet[] indexed by name
85
     */
86
    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...
87
88
    /**
89
     * Creates a new instance of ProvidersWrapper.
90
     *
91
     * @param IMetadataProvider     $meta   Reference to IMetadataProvider implementation
92
     * @param IQueryProvider        $query  Reference to IQueryProvider implementation
93
     * @param IServiceConfiguration $config Reference to IServiceConfiguration implementation
94
     */
95
    public function __construct(IMetadataProvider $meta, IQueryProvider $query, IServiceConfiguration $config)
96
    {
97
        $this->metaProvider = $meta;
98
        $this->config = $config;
99
        $this->providerWrapper = new ProvidersQueryWrapper($query);
100
        $this->setWrapperCache = [];
101
        $this->typeCache = [];
102
        $this->propertyCache = [];
103
    }
104
105
    //Wrappers for IMetadataProvider methods
106
107
    /**
108
     * To get the Container name for the data source,
109
     * Note: Wrapper for IMetadataProvider::getContainerName method
110
     * implementation.
111
     *
112
     * @throws ODataException Exception if implementation returns empty container name
113
     *
114
     * @return string that contains the name of the container
115
     */
116
    public function getContainerName()
117
    {
118
        $containerName = $this->metaProvider->getContainerName();
119
        if (empty($containerName)) {
120
            throw new ODataException(
121
                Messages::providersWrapperContainerNameMustNotBeNullOrEmpty(),
122
                500
123
            );
124
        }
125
126
        return $containerName;
127
    }
128
129
    /**
130
     * To get Namespace name for the data source,
131
     * Note: Wrapper for IMetadataProvider::getContainerNamespace method implementation.
132
     *
133
     * @throws ODataException Exception if implementation returns empty container namespace
134
     *
135
     * @return string that contains the namespace name
136
     */
137
    public function getContainerNamespace()
138
    {
139
        $containerNamespace = $this->metaProvider->getContainerNamespace();
140
        if (empty($containerNamespace)) {
141
            throw new ODataException(
142
                Messages::providersWrapperContainerNamespaceMustNotBeNullOrEmpty(),
143
                500
144
            );
145
        }
146
147
        return $containerNamespace;
148
    }
149
150
    /**
151
     * To get the data service configuration.
152
     *
153
     * @return IServiceConfiguration
154
     */
155
    public function getConfiguration()
156
    {
157
        return $this->config;
158
    }
159
160
    /**
161
     *  To get all entity set information,
162
     *  Note: Wrapper for IMetadataProvider::getResourceSets method implementation,
163
     *  This method returns array of ResourceSetWrapper instances but the corresponding IDSMP method
164
     *  returns array of ResourceSet instances.
165
     *
166
     *  @throws ODataException when two resource sets with the same name are encountered
167
     *
168
     *  @return ResourceSetWrapper[] The ResourceSetWrappers for the visible ResourceSets
169
     */
170
    public function getResourceSets()
171
    {
172
        $resourceSets = $this->metaProvider->getResourceSets();
173
        $resourceSetWrappers = [];
174
        $resourceSetNames = [];
175
        foreach ($resourceSets as $resourceSet) {
176
            $name = $resourceSet->getName();
177
            if (in_array($name, $resourceSetNames)) {
178
                throw new ODataException(Messages::providersWrapperEntitySetNameShouldBeUnique($name), 500);
179
            }
180
181
            $resourceSetNames[] = $name;
182
            $resourceSetWrapper = $this->_validateResourceSetAndGetWrapper($resourceSet);
183
            if (!is_null($resourceSetWrapper)) {
184
                $resourceSetWrappers[] = $resourceSetWrapper;
185
            }
186
        }
187
188
        return $resourceSetWrappers;
189
    }
190
191
    /**
192
     * This function perform the following operations
193
     *  (1) If the cache contain an entry [key, value] for the resourceset then
194
     *      return the entry-value
195
     *  (2) If the cache not contain an entry for the resourceset then validate
196
     *      the resourceset
197
     *            (a) If valid add entry as [resouceset_name, resourceSetWrapper]
198
     *            (b) if not valid add entry as [resouceset_name, null]
199
     *  Note: validating a resourceset means checking the resourceset is visible
200
     *  or not using configuration.
201
     *
202
     * @param ResourceSet $resourceSet The resourceset to validate and get the
203
     *                                 wrapper for
204
     *
205
     * @return ResourceSetWrapper|null Returns an instance if a resource set with the given name is visible
206
     */
207
    private function _validateResourceSetAndGetWrapper(ResourceSet $resourceSet)
208
    {
209
        $cacheKey = $resourceSet->getName();
210
        if (array_key_exists($cacheKey, $this->setWrapperCache)) {
211
            return $this->setWrapperCache[$cacheKey];
212
        }
213
214
        $this->validateResourceType($resourceSet->getResourceType());
215
        $wrapper = new ResourceSetWrapper($resourceSet, $this->config);
216
        $nuVal = $wrapper->isVisible() ? $wrapper : null;
217
        $this->setWrapperCache[$cacheKey] = $nuVal;
218
219
        return $this->setWrapperCache[$cacheKey];
220
    }
221
222
    /**
223
     * Validates the given instance of ResourceType.
224
     *
225
     * @param ResourceType $resourceType The ResourceType to validate
226
     *
227
     * @throws ODataException Exception if $resourceType is invalid
228
     *
229
     * @return ResourceType
230
     */
231
    private function validateResourceType(ResourceType $resourceType)
232
    {
233
        $cacheKey = $resourceType->getName();
234
        if (array_key_exists($cacheKey, $this->typeCache)) {
235
            return $this->typeCache[$cacheKey];
236
        }
237
238
        //TODO: Do validation if any for the ResourceType
239
        $this->typeCache[$cacheKey] = $resourceType;
240
241
        return $resourceType;
242
    }
243
244
    /**
245
     * To get all resource types in the data source,
246
     * Note: Wrapper for IMetadataProvider::getTypes method implementation.
247
     *
248
     * @return ResourceType[]
249
     */
250
    public function getTypes()
251
    {
252
        $resourceTypes = $this->metaProvider->getTypes();
253
        $resourceTypeNames = [];
254
        foreach ($resourceTypes as $resourceType) {
255
            if (in_array($resourceType->getName(), $resourceTypeNames)) {
256
                throw new ODataException(
257
                    Messages::providersWrapperEntityTypeNameShouldBeUnique($resourceType->getName()),
258
                    500
259
                );
260
            }
261
262
            $resourceTypeNames[] = $resourceType->getName();
263
            $this->validateResourceType($resourceType);
264
        }
265
266
        return $resourceTypes;
267
    }
268
269
    /**
270
     * To get a resource set based on the specified resource set name which is
271
     * visible,
272
     * Note: Wrapper for IMetadataProvider::resolveResourceSet method
273
     * implementation.
274
     *
275
     * @param string $name Name of the resource set
276
     *
277
     * @return ResourceSetWrapper|null Returns resource set with the given name if found,
278
     *                                 NULL if resource set is set to invisible or not found
279
     */
280
    public function resolveResourceSet($name)
281
    {
282
        if (array_key_exists($name, $this->setWrapperCache)) {
283
            return $this->setWrapperCache[$name];
284
        }
285
286
        $resourceSet = $this->metaProvider->resolveResourceSet($name);
287
        if (is_null($resourceSet)) {
288
            return;
289
        }
290
291
        return $this->_validateResourceSetAndGetWrapper($resourceSet);
292
    }
293
294
    /**
295
     * To get a resource type based on the resource set name,
296
     * Note: Wrapper for IMetadataProvider::resolveResourceType
297
     * method implementation.
298
     *
299
     * @param string $name Name of the resource set
300
     *
301
     * @throws ODataException If the ResourceType is invalid
302
     *
303
     * @return ResourceType|null resource type with the given resource set name if found else NULL
304
     */
305
    public function resolveResourceType($name)
306
    {
307
        $resourceType = $this->metaProvider->resolveResourceType($name);
308
        if (is_null($resourceType)) {
309
            return;
310
        }
311
312
        return $this->validateResourceType($resourceType);
313
    }
314
315
    /**
316
     * The method must return a collection of all the types derived from
317
     * $resourceType The collection returned should NOT include the type
318
     * passed in as a parameter
319
     * Note: Wrapper for IMetadataProvider::getDerivedTypes
320
     * method implementation.
321
     *
322
     * @param ResourceType $resourceType Resource to get derived resource types from
323
     *
324
     * @throws InvalidOperationException when the meat provider doesn't return an array
325
     *
326
     * @return ResourceType[]
327
     */
328
    public function getDerivedTypes(ResourceType $resourceType)
329
    {
330
        $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...
331
        if (!is_array($derivedTypes)) {
332
            throw new InvalidOperationException(
333
                Messages::metadataAssociationTypeSetInvalidGetDerivedTypesReturnType($resourceType->getName())
334
            );
335
        }
336
337
        foreach ($derivedTypes as $derivedType) {
338
            $this->validateResourceType($derivedType);
339
        }
340
341
        return $derivedTypes;
342
    }
343
344
    /**
345
     * Returns true if $resourceType represents an Entity Type which has derived
346
     * Entity Types, else false.
347
     * Note: Wrapper for IMetadataProvider::hasDerivedTypes method
348
     * implementation.
349
     *
350
     * @param ResourceType $resourceType Resource to check for derived resource
351
     *                                   types
352
     *
353
     * @throws ODataException If the ResourceType is invalid
354
     *
355
     * @return bool
356
     */
357
    public function hasDerivedTypes(ResourceType $resourceType)
358
    {
359
        $this->validateResourceType($resourceType);
360
361
        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...
362
    }
363
364
    /**
365
     * Gets the visible resource properties for the given resource type from the given resource set wrapper.
366
     *
367
     * @param ResourceSetWrapper $setWrapper Resource set wrapper in question
368
     * @param ResourceType $resourceType Resource type in question
369
     *
370
     * @return ResourceProperty[] Collection of visible resource properties from the given resource set wrapper
371
     *                            and resource type
372
     */
373
    public function getResourceProperties(ResourceSetWrapper $setWrapper, ResourceType $resourceType)
374
    {
375
        if ($resourceType->getResourceTypeKind() != ResourceTypeKind::ENTITY) {
376
            //Complex resource type
377
            return $resourceType->getAllProperties();
378
        }
379
        //TODO: move this to doctrine annotations
380
        $cacheKey = $setWrapper->getName() . '_' . $resourceType->getFullName();
381
        if (!array_key_exists($cacheKey, $this->propertyCache)) {
382
            //Fill the cache
383
            $this->propertyCache[$cacheKey] = [];
384
            foreach ($resourceType->getAllProperties() as $resourceProperty) {
385
                //Check whether this is a visible navigation property
386
                //TODO: is this broken?? see #87
387
                if ($resourceProperty->getTypeKind() == ResourceTypeKind::ENTITY
388
                    && !is_null($this->getResourceSetWrapperForNavigationProperty(
389
                        $setWrapper,
390
                        $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...
391
                        $resourceProperty
392
                    ))
393
                ) {
394
                    $this->propertyCache[$cacheKey][$resourceProperty->getName()] = $resourceProperty;
395
                } else {
396
                    //primitive, bag or complex property
397
                    $this->propertyCache[$cacheKey][$resourceProperty->getName()] = $resourceProperty;
398
                }
399
            }
400
        }
401
402
        return $this->propertyCache[$cacheKey];
403
    }
404
405
    /**
406
     * Gets the target resource set wrapper for the given navigation property,
407
     * source resource set wrapper and the source resource type.
408
     *
409
     * @param ResourceSetWrapper $resourceSetWrapper Source resource set
410
     * @param ResourceEntityType $resourceType Source resource type
411
     * @param ResourceProperty   $navigationResourceProperty Navigation property
412
     *
413
     * @return ResourceSetWrapper|null Returns instance of ResourceSetWrapper
414
     *                                 (describes the entity set and associated configuration) for the
415
     *                                 given navigation property. returns NULL if resourceset for the
416
     *                                 navigation property is invisible or if metadata provider returns
417
     *                                 null resource association set
418
     */
419
    public function getResourceSetWrapperForNavigationProperty(
420
        ResourceSetWrapper $resourceSetWrapper,
421
        ResourceEntityType $resourceType,
422
        ResourceProperty $navigationResourceProperty
423
    ) {
424
        $associationSet = $this->getResourceAssociationSet(
425
            $resourceSetWrapper,
426
            $resourceType,
427
            $navigationResourceProperty
428
        );
429
430
        if (!is_null($associationSet)) {
431
            $relatedAssociationSetEnd = $associationSet->getRelatedResourceAssociationSetEnd(
432
                $resourceSetWrapper->getResourceSet(),
433
                $resourceType,
434
                $navigationResourceProperty
435
            );
436
437
            return $this->_validateResourceSetAndGetWrapper(
438
                $relatedAssociationSetEnd->getResourceSet()
439
            );
440
        }
441
        return null;
442
    }
443
444
    /**
445
     * Gets the ResourceAssociationSet instance for the given source association end,
446
     * Note: Wrapper for IMetadataProvider::getResourceAssociationSet
447
     * method implementation.
448
     *
449
     * @param ResourceSet           $set      Resource set of the source association end
450
     * @param ResourceEntityType    $type     Resource type of the source association end
451
     * @param ResourceProperty      $property Resource property of the source association end
452
     *
453
     * @return ResourceAssociationSet|null Returns ResourceAssociationSet for the source
454
     *                                     association end, NULL if no such
455
     *                                     association end or resource set in the
456
     *                                     other end of the association is invisible
457
     */
458
    public function getResourceAssociationSet(
459
        ResourceSet $set,
460
        ResourceEntityType $type,
461
        ResourceProperty $property
462
    ) {
463
        $type = $this->getResourceTypeWherePropertyIsDeclared($type, $property);
464
        // usage below requires $type to not be null - so kaboom as early as possible
465
        assert(null != $type, 'Resource type obtained from property must not be null.');
466
467
        $associationSet = $this->metaProvider->getResourceAssociationSet(
468
            $set,
469
            $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...
470
            $property
471
        );
472
        assert(
473
            null == $associationSet || $associationSet instanceof ResourceAssociationSet,
474
            "Retrieved resource assocation must be either null or an instance of ResourceAssociationSet"
475
        );
476
477
        if (!is_null($associationSet)) {
478
            $thisAssociationSetEnd = $associationSet->getResourceAssociationSetEnd(
479
                $set,
480
                $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...
481
                $property
482
            );
483
484
            $relatedAssociationSetEnd = $associationSet->getRelatedResourceAssociationSetEnd(
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
490
            //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...
491
            //is null means the associationset we got from the IDSMP::getResourceAssociationSet is invalid.
492
493
            //Return null, if either AssociationSet's End1 or End2's resourceset name
494
            //doesn't match the name of resource set wrapper (param1) and resource type is not assignable
495
            //from given resource type (param2)
496
            if (is_null($thisAssociationSetEnd) || is_null($relatedAssociationSetEnd)) {
497
                throw new ODataException(
498
                    Messages::providersWrapperIDSMPGetResourceSetReturnsInvalidResourceSet(
499
                        $set->getName(),
500
                        $type->getFullName(),
501
                        $property->getName()
502
                    ),
503
                    500
504
                );
505
            }
506
507
            $relatedResourceSetWrapper = $this->_validateResourceSetAndGetWrapper(
508
                $relatedAssociationSetEnd->getResourceSet()
509
            );
510
            if ($relatedResourceSetWrapper === null) {
511
                $associationSet = null;
512
            } else {
513
                $this->validateResourceType($thisAssociationSetEnd->getResourceType());
514
                $this->validateResourceType($relatedAssociationSetEnd->getResourceType());
515
            }
516
        }
517
        assert(
518
            null == $associationSet || $associationSet instanceof ResourceAssociationSet,
519
            "Retrieved resource assocation must be either null or an instance of ResourceAssociationSet"
520
        );
521
522
        return $associationSet;
523
    }
524
525
    /**
526
     * Gets the resource type on which the resource property is declared on,
527
     * If property is not declared in the given resource type, then this
528
     * function drill down to the inheritance hierarchy of the given resource
529
     * type to find out the base class in which the property is declared.
530
     *
531
     * @param ResourceType     $type     The resource type to start looking
532
     * @param ResourceProperty $property The resource property in question
533
     *
534
     * @return ResourceType|null Returns reference to the ResourceType on which
535
     *                           the $property is declared, NULL if
536
     *                           $property is not declared anywhere
537
     *                           in the inheritance hierarchy
538
     */
539
    private function getResourceTypeWherePropertyIsDeclared(ResourceType $type, ResourceProperty $property)
540
    {
541
        while (null !== $type) {
542
            if (null !== $type->resolvePropertyDeclaredOnThisType($property->getName())) {
543
                break;
544
            }
545
546
            $type = $type->getBaseType();
547
        }
548
549
        return $type;
550
    }
551
552
    /**
553
     * Wrapper function over _validateResourceSetAndGetWrapper function.
554
     *
555
     * @param ResourceSet $resourceSet see the comments of _validateResourceSetAndGetWrapper
556
     *
557
     * @return ResourceSetWrapper|null see the comments of _validateResourceSetAndGetWrapper
558
     */
559
    public function validateResourceSetAndGetWrapper(ResourceSet $resourceSet)
560
    {
561
        return $this->_validateResourceSetAndGetWrapper($resourceSet);
562
    }
563
564
    /**
565
     * Gets the Edm Schema version compliance to the metadata.
566
     *
567
     * @return EdmSchemaVersion
568
     */
569
    public function getEdmSchemaVersion()
570
    {
571
        //The minimal schema version for custom provider is 1.1
572
        return EdmSchemaVersion::VERSION_1_DOT_1;
573
    }
574
575
    /**
576
     * Gets the underlying custom expression provider, the end developer is
577
     * responsible for implementing IExpressionProvider if he choose for.
578
     *
579
     * @return IExpressionProvider Instance of IExpressionProvider implementation
580
     */
581
    public function getExpressionProvider()
582
    {
583
        return $this->providerWrapper->getExpressionProvider();
584
    }
585
586
    /**
587
     * Indicates if the QueryProvider can handle ordered paging, this means respecting order, skip, and top parameters
588
     * If the query provider can not handle ordered paging, it must return the entire result set and POData will
589
     * perform the ordering and paging.
590
     *
591
     * @return bool True if the query provider can handle ordered paging, false if POData should perform the paging
592
     */
593
    public function handlesOrderedPaging()
594
    {
595
        return $this->providerWrapper->handlesOrderedPaging();
596
    }
597
598
    /**
599
     * Gets collection of entities belongs to an entity set.
600
     *
601
     * @param QueryType             $queryType   Indicates if this is a query for a count, entities, or entities with a
602
     *                                           count
603
     * @param ResourceSet           $resourceSet The entity set containing the entities that need to be fetched
604
     * @param FilterInfo            $filterInfo  Represents the $filter parameter of the OData query.
605
     *                                           NULL if no $filter specified
606
     * @param InternalOrderByInfo   $orderBy     The orderBy information
607
     * @param int                   $top         The top count
608
     * @param int                   $skip        The skip count
609
     * @param InternalSkipTokenInfo $skipToken   The skip token
610
     *
611
     * @return QueryResult
612
     */
613
    public function getResourceSet(
614
        QueryType $queryType,
615
        ResourceSet $resourceSet,
616
        FilterInfo $filterInfo = null,
617
        InternalOrderByInfo $orderBy = null,
618
        $top = null,
619
        $skip = null,
620
        InternalSkipTokenInfo $skipToken = null
621
    ) {
622
        return $this->providerWrapper->getResourceSet(
623
            $queryType,
624
            $resourceSet,
625
            $filterInfo,
626
            $orderBy,
627
            $top,
628
            $skip,
629
            $skipToken
630
        );
631
    }
632
633
    /**
634
     * Gets an entity instance from an entity set identified by a key.
635
     *
636
     * @param ResourceSet   $resourceSet   The entity set containing the entity to fetch
637
     * @param KeyDescriptor $keyDescriptor The key identifying the entity to fetch
638
     *
639
     * @return object|null Returns entity instance if found else null
640
     */
641
    public function getResourceFromResourceSet(ResourceSet $resourceSet, KeyDescriptor $keyDescriptor)
642
    {
643
        return $this->providerWrapper->getResourceFromResourceSet($resourceSet, $keyDescriptor);
644
    }
645
646
    /**
647
     * Puts an entity instance to entity set identified by a key.
648
     *
649
     * @param ResourceSet   $resourceSet   The entity set containing the entity to update
650
     * @param KeyDescriptor $keyDescriptor The key identifying the entity to update
651
     *
652
     * @return bool|null Returns result of executiong query
653
     */
654
    public function putResource(
655
        ResourceSet $resourceSet,
656
        KeyDescriptor $keyDescriptor,
657
        $data
658
    ) {
659
        return $this->providerWrapper->putResource(
660
            $resourceSet,
661
            $keyDescriptor,
662
            $data
663
        );
664
    }
665
666
    /**
667
     * Get related resource set for a resource.
668
     *
669
     * @param QueryType        $queryType         Indicates if this is a query for a count, entities, or entities
670
     *                                            with a count
671
     * @param ResourceSet      $sourceResourceSet The entity set containing the source entity
672
     * @param object           $sourceEntity      The source entity instance
673
     * @param ResourceSet      $targetResourceSet The resource set of containing the target of the navigation property
674
     * @param ResourceProperty $targetProperty    The navigation property to retrieve
675
     * @param FilterInfo|null  $filterInfo        Represents the $filter parameter of the OData query.
676
     *                                            NULL if no $filter specified
677
     * @param mixed            $orderBy           sorted order if we want to get the data in some specific order
678
     * @param int              $top               number of records which  need to be skip
679
     * @param string           $skip              value indicating what records to skip
680
     *
681
     * @throws ODataException
682
     *
683
     * @return QueryResult
684
     */
685
    public function getRelatedResourceSet(
686
        QueryType $queryType,
687
        ResourceSet $sourceResourceSet,
688
        $sourceEntity,
689
        ResourceSet $targetResourceSet,
690
        ResourceProperty $targetProperty,
691
        $filterInfo,
692
        $orderBy,
693
        $top,
694
        $skip
695
    ) {
696
        return $this->providerWrapper->getRelatedResourceSet(
697
            $queryType,
698
            $sourceResourceSet,
699
            $sourceEntity,
700
            $targetResourceSet,
701
            $targetProperty,
702
            $filterInfo,
0 ignored issues
show
Bug introduced by
It seems like $filterInfo defined by parameter $filterInfo on line 691 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...
703
            $orderBy,
704
            $top,
705
            $skip
706
        );
707
    }
708
709
    /**
710
     * Gets a related entity instance from an entity set identified by a key.
711
     *
712
     * @param ResourceSet      $sourceResourceSet The entity set related to the entity to be fetched
713
     * @param object           $sourceEntity      The related entity instance
714
     * @param ResourceSet      $targetResourceSet The entity set from which entity needs to be fetched
715
     * @param ResourceProperty $targetProperty    The metadata of the target property
716
     * @param KeyDescriptor    $keyDescriptor     The key to identify the entity to be fetched
717
     *
718
     * @return object|null Returns entity instance if found else null
719
     */
720
    public function getResourceFromRelatedResourceSet(
721
        ResourceSet $sourceResourceSet,
722
        $sourceEntity,
723
        ResourceSet $targetResourceSet,
724
        ResourceProperty $targetProperty,
725
        KeyDescriptor $keyDescriptor
726
    ) {
727
        return $this->providerWrapper->getResourceFromRelatedResourceSet(
728
            $sourceResourceSet,
729
            $sourceEntity,
730
            $targetResourceSet,
731
            $targetProperty,
732
            $keyDescriptor
733
        );
734
    }
735
736
    /**
737
     * Get related resource for a resource.
738
     *
739
     * @param ResourceSet      $sourceResourceSet The source resource set
740
     * @param object           $sourceEntity      The source resource
741
     * @param ResourceSet      $targetResourceSet The resource set of the navigation
742
     *                                            property
743
     * @param ResourceProperty $targetProperty    The navigation property to be
744
     *                                            retrieved
745
     *
746
     * @return object|null The related resource if exists else null
747
     */
748
    public function getRelatedResourceReference(
749
        ResourceSet $sourceResourceSet,
750
        $sourceEntity,
751
        ResourceSet $targetResourceSet,
752
        ResourceProperty $targetProperty
753
    ) {
754
        return $this->providerWrapper->getRelatedResourceReference(
755
            $sourceResourceSet,
756
            $sourceEntity,
757
            $targetResourceSet,
758
            $targetProperty
759
        );
760
    }
761
762
    /**
763
     * Updates a resource.
764
     *
765
     * @param ResourceSet   $sourceResourceSet    The entity set containing the source entity
766
     * @param object        $sourceEntityInstance The source entity instance
767
     * @param KeyDescriptor $keyDescriptor        The key identifying the entity to fetch
768
     * @param object        $data                 The New data for the entity instance.
769
     * @param bool          $shouldUpdate         Should undefined values be updated or reset to default
770
     *
771
     * @return object|null The new resource value if it is assignable or throw exception for null.
772
     */
773
    public function updateResource(
774
        ResourceSet $sourceResourceSet,
775
        $sourceEntityInstance,
776
        KeyDescriptor $keyDescriptor,
777
        $data,
778
        $shouldUpdate = false
779
    ) {
780
        return $this->providerWrapper->updateResource(
781
            $sourceResourceSet,
782
            $sourceEntityInstance,
783
            $keyDescriptor,
784
            $data,
785
            $shouldUpdate
786
        );
787
    }
788
789
    /**
790
     * Delete resource from a resource set.
791
     *
792
     * @param ResourceSet $sourceResourceSet
793
     * @param object      $sourceEntityInstance
794
     *
795
     * return bool true if resources sucessfully deteled, otherwise false.
796
     */
797
    public function deleteResource(
798
        ResourceSet $sourceResourceSet,
799
        $sourceEntityInstance
800
    ) {
801
        return $this->providerWrapper->deleteResource(
802
            $sourceResourceSet,
803
            $sourceEntityInstance
804
        );
805
    }
806
807
    /**
808
     * @param ResourceSet $resourceSet          The entity set containing the entity to fetch
809
     * @param object      $sourceEntityInstance The source entity instance
810
     * @param object      $data                 The New data for the entity instance.
811
     *
812
     * returns object|null returns the newly created model if sucessful or null if model creation failed.
813
     */
814
    public function createResourceforResourceSet(
815
        ResourceSet $resourceSet,
816
        $sourceEntityInstance,
817
        $data
818
    ) {
819
        return $this->providerWrapper->createResourceforResourceSet(
820
            $resourceSet,
821
            $sourceEntityInstance,
822
            $data
823
        );
824
    }
825
826
    public function getMetadataXML()
827
    {
828
        return $this->metaProvider->getXML();
829
    }
830
}
831