Passed
Push — master ( 057e05...52b23b )
by Christopher
02:53
created

ProvidersWrapper::GetMetadataXML()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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