Completed
Push — master ( bffd1d...b8dc97 )
by Bálint
11:00
created
src/POData/Providers/ProvidersWrapper.php 1 patch
Indentation   +951 added lines, -951 removed lines patch added patch discarded remove patch
@@ -32,955 +32,955 @@
 block discarded – undo
32 32
  */
33 33
 class ProvidersWrapper
34 34
 {
35
-	/**
36
-	 * Holds reference to IMetadataProvider implementation
37
-	 *
38
-	 * @var IMetadataProvider
39
-	 */
40
-	private $metaProvider;
41
-
42
-	/**
43
-	 * Holds reference to IQueryProvider implementation
44
-	 *
45
-	 * @var IQueryProvider
46
-	 *
47
-	 */
48
-	private $queryProvider;
49
-
50
-	/**
51
-	 * Holds reference to IServiceConfiguration implementation
52
-	 *
53
-	 * @var ServiceConfiguration
54
-	 */
55
-	private $config;
56
-
57
-
58
-	/**
59
-	 * Cache for ResourceProperties of a resource type that belongs to a
60
-	 * resource set. An entry (ResourceProperty collection) in this cache
61
-	 * contains only the visible properties of ResourceType.
62
-	 *
63
-	 * @var array(string, array(string, ResourceProperty))
64
-	 */
65
-	private $propertyCache;
66
-
67
-	/**
68
-	 * Cache for ResourceSetWrappers. If ResourceSet is invisible value will
69
-	 * be null.
70
-	 *
71
-	 * @var ResourceSetWrapper[] indexed by resource set name
72
-	 */
73
-	private $setWrapperCache;
74
-
75
-	/**
76
-	 * Cache for ResourceTypes
77
-	 *
78
-	 * @var ResourceType[] indexed by resource type name
79
-	 */
80
-	private $typeCache;
81
-
82
-	/**
83
-	 * Cache for ResourceAssociationSet. If ResourceAssociationSet is invisible
84
-	 * value will be null.
85
-	 *
86
-	 * @var ResourceAssociationSet[] indexed by name
87
-	 */
88
-	private $associationSetCache;
89
-
90
-	/**
91
-	 * Creates a new instance of ProvidersWrapper
92
-	 *
93
-	 * @param IMetadataProvider $metadataProvider Reference to IMetadataProvider implementation
94
-	 * @param IQueryProvider    $queryProvider    Reference to IQueryProvider implementation
95
-	 * @param ServiceConfiguration    $configuration    Reference to IServiceConfiguration implementation
96
-	 */
97
-	public function __construct(IMetadataProvider $metadataProvider, IQueryProvider $queryProvider, ServiceConfiguration $configuration)
98
-	{
99
-		$this->metaProvider = $metadataProvider;
100
-		$this->queryProvider = $queryProvider;
101
-		$this->config = $configuration;
102
-		$this->setWrapperCache = array();
103
-		$this->typeCache = array();
104
-		$this->associationSetCache = array();
105
-		$this->propertyCache = array();
106
-	}
107
-
108
-	//Wrappers for IMetadataProvider methods
109
-
110
-	/**
111
-	 * To get the Container name for the data source,
112
-	 * Note: Wrapper for IMetadataProvider::getContainerName method
113
-	 * implementation
114
-	 *
115
-	 * @return string that contains the name of the container
116
-	 *
117
-	 * @throws ODataException Exception if implementation returns empty container name
118
-	 *
119
-	 */
120
-	public function getContainerName()
121
-	{
122
-		$containerName = $this->metaProvider->getContainerName();
123
-		if (empty($containerName)) {
124
-			throw new ODataException(
125
-				Messages::providersWrapperContainerNameMustNotBeNullOrEmpty(),
126
-				500
127
-			);
128
-		}
129
-
130
-		return $containerName;
131
-	}
132
-
133
-	/**
134
-	 * To get Namespace name for the data source,
135
-	 * Note: Wrapper for IMetadataProvider::getContainerNamespace method implementation
136
-	 *
137
-	 * @return string that contains the namespace name.
138
-	 *
139
-	 * @throws ODataException Exception if implementation returns empty container namespace
140
-	 *
141
-	 */
142
-	public function getContainerNamespace()
143
-	{
144
-		$containerNamespace = $this->metaProvider->getContainerNamespace();
145
-		if (empty($containerNamespace)) {
146
-			throw new ODataException(
147
-				Messages::providersWrapperContainerNamespaceMustNotBeNullOrEmpty(),
148
-				500
149
-			);
150
-		}
151
-
152
-		return $containerNamespace;
153
-	}
154
-
155
-	/**
156
-	 * To get the data service configuration
157
-	 *
158
-	 * @return ServiceConfiguration
159
-	 */
160
-	public function getConfiguration()
161
-	{
162
-		return $this->config;
163
-	}
164
-
165
-	/**
166
-	 *  To get all entity set information,
167
-	 *  Note: Wrapper for IMetadataProvider::getResourceSets method implementation,
168
-	 *  This method returns array of ResourceSetWrapper instances but the corresponding IDSMP method returns array of ResourceSet instances
169
-	 *
170
-	 *  @return ResourceSetWrapper[] The ResourceSetWrappers for the visible ResourceSets
171
-	 *  @throws ODataException when two resource sets with the same name are encountered
172
-	 *
173
-	 */
174
-	public function getResourceSets()
175
-	{
176
-		$resourceSets = $this->metaProvider->getResourceSets();
177
-		$resourceSetWrappers = array();
178
-		$resourceSetNames = array();
179
-		foreach ($resourceSets as $resourceSet) {
180
-			$name = $resourceSet->getName();
181
-			if (in_array($name, $resourceSetNames)) {
182
-				throw new ODataException(Messages::providersWrapperEntitySetNameShouldBeUnique($name), 500 );
183
-			}
184
-
185
-			$resourceSetNames[] = $name;
186
-			$resourceSetWrapper = $this->_validateResourceSetAndGetWrapper($resourceSet);
187
-			if (!is_null($resourceSetWrapper)) {
188
-				$resourceSetWrappers[] = $resourceSetWrapper;
189
-			}
190
-		}
191
-
192
-		return $resourceSetWrappers;
193
-	}
194
-
195
-	/**
196
-	 * To get all resource types in the data source,
197
-	 * Note: Wrapper for IMetadataProvider::getTypes method implementation
198
-	 *
199
-	 * @return ResourceType[]
200
-	 */
201
-	public function getTypes()
202
-	{
203
-		$resourceTypes = $this->metaProvider->getTypes();
204
-		$resourceTypeNames = array();
205
-		foreach ($resourceTypes as $resourceType) {
206
-			if (in_array($resourceType->getName(), $resourceTypeNames)) {
207
-				throw new ODataException(
208
-					Messages::providersWrapperEntityTypeNameShouldBeUnique($resourceType->getName()),
209
-					500
210
-				);
211
-			}
212
-
213
-			$resourceTypeNames[] = $resourceType->getName();
214
-			$this->_validateResourceType($resourceType);
215
-		}
216
-
217
-		return $resourceTypes;
218
-	}
219
-
220
-	/**
221
-	 * To get a resource set based on the specified resource set name which is
222
-	 * visible,
223
-	 * Note: Wrapper for IMetadataProvider::resolveResourceSet method
224
-	 * implementation
225
-	 *
226
-	 * @param string $name Name of the resource set
227
-	 *
228
-	 * @return ResourceSetWrapper|null Returns resource set with the given name if found, NULL if resource set is set to invisible or not found
229
-	 *
230
-	 */
231
-	public function resolveResourceSet($name)
232
-	{
233
-		if (array_key_exists($name, $this->setWrapperCache)) {
234
-			return $this->setWrapperCache[$name];
235
-		}
236
-
237
-		$resourceSet = $this->metaProvider->resolveResourceSet($name);
238
-		if (is_null($resourceSet)) {
239
-			return null;
240
-		}
241
-
242
-		return $this->_validateResourceSetAndGetWrapper($resourceSet);
243
-	}
244
-
245
-	/**
246
-	 * To get a resource type based on the resource set name,
247
-	 * Note: Wrapper for IMetadataProvider::resolveResourceType
248
-	 * method implementation
249
-	 *
250
-	 * @param string $name Name of the resource set
251
-	 *
252
-	 * @return ResourceType|null resource type with the given resource set name if found else NULL
253
-	 *
254
-	 *
255
-	 * @throws ODataException If the ResourceType is invalid
256
-	 */
257
-	public function resolveResourceType($name)
258
-	{
259
-		$resourceType = $this->metaProvider->resolveResourceType($name);
260
-		if (is_null($resourceType)) {
261
-			return null;
262
-		}
263
-
264
-		return $this->_validateResourceType($resourceType);
265
-	}
266
-
267
-	/**
268
-	 * The method must return a collection of all the types derived from
269
-	 * $resourceType The collection returned should NOT include the type
270
-	 * passed in as a parameter
271
-	 * Note: Wrapper for IMetadataProvider::getDerivedTypes
272
-	 * method implementation
273
-	 *
274
-	 * @param ResourceType $resourceType Resource to get derived resource types from
275
-	 *
276
-	 * @return ResourceType[]
277
-	 *
278
-	 * @throws InvalidOperationException when the meat provider doesn't return an array
279
-	 */
280
-	public function getDerivedTypes(ResourceType $resourceType)
281
-	{
282
-		$derivedTypes = $this->metaProvider->getDerivedTypes($resourceType);
283
-		if (!is_array($derivedTypes)) {
284
-			throw new InvalidOperationException(Messages::metadataAssociationTypeSetInvalidGetDerivedTypesReturnType($resourceType->getName()));
285
-		}
286
-
287
-		foreach ($derivedTypes as $derivedType) {
288
-			$this->_validateResourceType($derivedType);
289
-		}
290
-
291
-		return $derivedTypes;
292
-	}
293
-
294
-	/**
295
-	 * Returns true if $resourceType represents an Entity Type which has derived
296
-	 * Entity Types, else false.
297
-	 * Note: Wrapper for IMetadataProvider::hasDerivedTypes method
298
-	 * implementation
299
-	 *
300
-	 * @param ResourceType $resourceType Resource to check for derived resource
301
-	 *                                   types.
302
-	 *
303
-	 * @return boolean
304
-	 *
305
-	 * @throws ODataException If the ResourceType is invalid
306
-	 */
307
-	public function hasDerivedTypes(ResourceType $resourceType)
308
-	{
309
-		$this->_validateResourceType($resourceType);
310
-		return $this->metaProvider->hasDerivedTypes($resourceType);
311
-	}
312
-
313
-	/**
314
-	 * Gets the ResourceAssociationSet instance for the given source association end,
315
-	 * Note: Wrapper for IMetadataProvider::getResourceAssociationSet
316
-	 * method implementation
317
-	 *
318
-	 * @param ResourceSet $set Resource set of the source association end
319
-	 * @param ResourceType       $type       Resource type of the source association end
320
-	 * @param ResourceProperty   $property   Resource property of the source association end
321
-	 *
322
-	 *
323
-	 * @return ResourceAssociationSet|null Returns ResourceAssociationSet for the source
324
-	 *                                             association end, NULL if no such
325
-	 *                                             association end or resource set in the
326
-	 *                                             other end of the association is invisible
327
-	 */
328
-	public function getResourceAssociationSet(
329
-		ResourceSet $set,
330
-		ResourceType $type,
331
-		ResourceProperty $property
332
-	) {
333
-		$type = $this->_getResourceTypeWherePropertyIsDeclared($type, $property);
334
-		$cacheKey = $set->getName() . '_' . $type->getName() . '_' . $property->getName();
335
-
336
-		if (array_key_exists($cacheKey,  $this->associationSetCache)) {
337
-			return $this->associationSetCache[$cacheKey];
338
-		}
339
-
340
-		$associationSet = $this->metaProvider->getResourceAssociationSet(
341
-			$set,
342
-			$type,
343
-			$property
344
-		);
345
-
346
-		if (!is_null($associationSet)) {
347
-			$thisAssociationSetEnd = $associationSet->getResourceAssociationSetEnd(
348
-				$set,
349
-				$type,
350
-				$property
351
-			);
352
-
353
-			$relatedAssociationSetEnd = $associationSet->getRelatedResourceAssociationSetEnd(
354
-				$set,
355
-				$type,
356
-				$property
357
-			);
358
-
359
-			//If $thisAssociationSetEnd or $relatedAssociationSetEnd
360
-			//is null means the associationset
361
-			//we got from the IDSMP::getResourceAssociationSet is invalid.
362
-			//AssociationSet::getResourceAssociationSetEnd
363
-			//return null, if AssociationSet's End1 or End2's resourceset name
364
-			//is not matching with the name of
365
-			//resource set wrapper (param1) and resource type is not assignable
366
-			//from given resource type (param2)
367
-			if (is_null($thisAssociationSetEnd) || is_null($relatedAssociationSetEnd)) {
368
-				throw new ODataException(
369
-					Messages::providersWrapperIDSMPGetResourceSetReturnsInvalidResourceSet(
370
-						$set->getName(),
371
-						$type->getFullName(),
372
-						$property->getName()
373
-					),
374
-					500
375
-				);
376
-			}
377
-
378
-			$relatedResourceSetWrapper = $this->_validateResourceSetAndGetWrapper(
379
-				$relatedAssociationSetEnd->getResourceSet()
380
-			);
381
-			if ($relatedResourceSetWrapper === null) {
382
-				$associationSet = null;
383
-			} else {
384
-				$this->_validateResourceType($thisAssociationSetEnd->getResourceType());
385
-				$this->_validateResourceType($relatedAssociationSetEnd->getResourceType());
386
-			}
387
-		}
388
-
389
-		$this->associationSetCache[$cacheKey] = $associationSet;
390
-		return $associationSet;
391
-	}
392
-
393
-	/**
394
-	 * Gets the target resource set wrapper for the given navigation property,
395
-	 * source resource set wrapper and the source resource type
396
-	 *
397
-	 * @param ResourceSetWrapper $resourceSetWrapper         Source resource set.
398
-	 * @param ResourceType       $resourceType               Source resource type.
399
-	 * @param ResourceProperty   $navigationResourceProperty Navigation property.
400
-	 *
401
-	 * @return ResourceSetWrapper|null Returns instance of ResourceSetWrapper
402
-	 *     (describes the entity set and associated configuration) for the
403
-	 *     given navigation property. returns NULL if resourceset for the
404
-	 *     navigation property is invisible or if metadata provider returns
405
-	 *     null resource association set
406
-	 */
407
-	public function getResourceSetWrapperForNavigationProperty(
408
-		ResourceSetWrapper $resourceSetWrapper,
409
-		ResourceType $resourceType,
410
-		ResourceProperty $navigationResourceProperty
411
-	) {
412
-		$associationSet = $this->getResourceAssociationSet(
413
-			$resourceSetWrapper,
414
-			$resourceType,
415
-			$navigationResourceProperty
416
-		);
417
-
418
-		if (!is_null($associationSet)) {
419
-			$relatedAssociationSetEnd = $associationSet->getRelatedResourceAssociationSetEnd(
420
-				$resourceSetWrapper->getResourceSet(),
421
-				$resourceType,
422
-				$navigationResourceProperty
423
-			);
424
-			return $this->_validateResourceSetAndGetWrapper(
425
-				$relatedAssociationSetEnd->getResourceSet()
426
-			);
427
-		}
428
-
429
-		return null;
430
-	}
431
-
432
-	/**
433
-	 * Gets the visible resource properties for the given resource type from the given resource set wrapper.
434
-	 *
435
-	 * @param ResourceSetWrapper $setWrapper Resource set wrapper in question.
436
-	 * @param ResourceType       $resourceType       Resource type in question.
437
-	 * @return ResourceProperty[] Collection of visible resource properties from the given resource set wrapper and resource type.
438
-	 */
439
-	public function getResourceProperties(ResourceSetWrapper $setWrapper, ResourceType $resourceType) {
440
-		if ($resourceType->getResourceTypeKind() != ResourceTypeKind::ENTITY) {
441
-			//Complex resource type
442
-			return $resourceType->getAllProperties();
443
-		}
444
-		//TODO: move this to doctrine annotations
445
-		$cacheKey = $setWrapper->getName() . '_' . $resourceType->getFullName();
446
-		if (!array_key_exists($cacheKey,  $this->propertyCache)) {
447
-			//Fill the cache
448
-			$this->propertyCache[$cacheKey] = array();
449
-			foreach ($resourceType->getAllProperties() as $resourceProperty) {
450
-				//Check whether this is a visible navigation property
451
-				//TODO: is this broken?? see #87
452
-				if ($resourceProperty->getTypeKind() == ResourceTypeKind::ENTITY
453
-					&& !is_null($this->getResourceSetWrapperForNavigationProperty($setWrapper, $resourceType, $resourceProperty))
454
-				) {
455
-					$this->propertyCache[$cacheKey][$resourceProperty->getName()] = $resourceProperty;
456
-				} else {
457
-					//primitive, bag or complex property
458
-					$this->propertyCache[$cacheKey][$resourceProperty->getName()] = $resourceProperty;
459
-				}
460
-			}
461
-		}
462
-		return $this->propertyCache[$cacheKey];
463
-
464
-	}
465
-
466
-	/**
467
-	 * Wrapper function over _validateResourceSetAndGetWrapper function
468
-	 *
469
-	 * @param ResourceSet $resourceSet see the comments of _validateResourceSetAndGetWrapper
470
-	 *
471
-	 * @return ResourceSetWrapper|null see the comments of _validateResourceSetAndGetWrapper
472
-	 */
473
-	public function validateResourceSetAndGetWrapper(ResourceSet $resourceSet)
474
-	{
475
-		return $this->_validateResourceSetAndGetWrapper($resourceSet);
476
-	}
477
-
478
-	/**
479
-	 * Gets the Edm Schema version compliance to the metadata
480
-	 *
481
-	 * @return EdmSchemaVersion
482
-	 */
483
-	public function getEdmSchemaVersion()
484
-	{
485
-		//The minimal schema version for custom provider is 1.1
486
-		return EdmSchemaVersion::VERSION_1_DOT_1;
487
-	}
488
-
489
-	/**
490
-	 * This function perform the following operations
491
-	 *  (1) If the cache contain an entry [key, value] for the resourceset then
492
-	 *      return the entry-value
493
-	 *  (2) If the cache not contain an entry for the resourceset then validate
494
-	 *      the resourceset
495
-	 *            (a) If valid add entry as [resouceset_name, resourceSetWrapper]
496
-	 *            (b) if not valid add entry as [resouceset_name, null]
497
-	 *  Note: validating a resourceset means checking the resourceset is visible
498
-	 *  or not using configuration
499
-	 *
500
-	 * @param ResourceSet $resourceSet The resourceset to validate and get the
501
-	 *                                 wrapper for
502
-	 *
503
-	 * @return ResourceSetWrapper|null Returns an instance if a resource set with the given name is visible
504
-	 */
505
-	private function _validateResourceSetAndGetWrapper(ResourceSet $resourceSet)
506
-	{
507
-		$cacheKey = $resourceSet->getName();
508
-		if (array_key_exists($cacheKey, $this->setWrapperCache)) {
509
-			return $this->setWrapperCache[$cacheKey];
510
-		}
511
-
512
-		$this->_validateResourceType($resourceSet->getResourceType());
513
-		$wrapper = new ResourceSetWrapper($resourceSet, $this->config);
514
-		if ($wrapper->isVisible()) {
515
-			$this->setWrapperCache[$cacheKey] = $wrapper;
516
-		} else {
517
-			$this->setWrapperCache[$cacheKey] = null;
518
-		}
519
-
520
-		return $this->setWrapperCache[$cacheKey];
521
-	}
522
-
523
-	/**
524
-	 * Validates the given instance of ResourceType
525
-	 *
526
-	 * @param ResourceType $resourceType The ResourceType to validate
527
-	 *
528
-	 * @return ResourceType
529
-	 *
530
-	 * @throws ODataException Exception if $resourceType is invalid
531
-	 */
532
-	private function _validateResourceType(ResourceType $resourceType)
533
-	{
534
-		$cacheKey = $resourceType->getName();
535
-		if (array_key_exists($cacheKey, $this->typeCache)) {
536
-			return $this->typeCache[$cacheKey];
537
-		}
538
-
539
-		//TODO: Do validation if any for the ResourceType
540
-		$this->typeCache[$cacheKey] = $resourceType;
541
-		return $resourceType;
542
-	}
543
-
544
-	/**
545
-	 * Gets the resource type on which the resource property is declared on,
546
-	 * If property is not declared in the given resource type, then this
547
-	 * function drill down to the inheritance hierarchy of the given resource
548
-	 * type to find out the base class in which the property is declared
549
-	 *
550
-	 * @param ResourceType     $resourceType     The resource type to start looking
551
-	 * @param ResourceProperty $resourceProperty The resource property in question
552
-	 *
553
-	 * @return ResourceType|null Returns reference to the ResourceType on which
554
-	 *                                   the $resourceProperty is declared, NULL if
555
-	 *                                   $resourceProperty is not declared anywhere
556
-	 *                                   in the inheritance hierarchy
557
-	 */
558
-	private function _getResourceTypeWherePropertyIsDeclared(ResourceType $resourceType,
559
-		ResourceProperty $resourceProperty
560
-	) {
561
-		$type = $resourceType;
562
-		while ($type !== null) {
563
-			if ($type->resolvePropertyDeclaredOnThisType($resourceProperty->getName()) !== null) {
564
-				break;
565
-			}
566
-
567
-			$type = $type->getBaseType();
568
-		}
569
-
570
-		return $type;
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
-	 */
580
-	public function getExpressionProvider()
581
-	{
582
-		$expressionProvider = $this->queryProvider->getExpressionProvider();
583
-		if (is_null($expressionProvider)) {
584
-			throw ODataException::createInternalServerError(Messages::providersWrapperExpressionProviderMustNotBeNullOrEmpty());
585
-		}
586
-
587
-		if (!$expressionProvider instanceof IExpressionProvider)
588
-		{
589
-			throw ODataException::createInternalServerError( Messages::providersWrapperInvalidExpressionProviderInstance() );
590
-		}
591
-
592
-		return $expressionProvider;
593
-	}
594
-
595
-	/**
596
-	 * Indicates if the QueryProvider can handle ordered paging, this means respecting order, skip, and top parameters
597
-	 * If the query provider can not handle ordered paging, it must return the entire result set and POData will
598
-	 * perform the ordering and paging
599
-	 *
600
-	 * @return Boolean True if the query provider can handle ordered paging, false if POData should perform the paging
601
-	 */
602
-	public function handlesOrderedPaging()
603
-	{
604
-		return $this->queryProvider->handlesOrderedPaging();
605
-	}
606
-
607
-
608
-	private function ValidateQueryResult($queryResult, QueryType $queryType, $methodName){
609
-		if (!$queryResult instanceof QueryResult) {
610
-			throw ODataException::createInternalServerError(
611
-				Messages::queryProviderReturnsNonQueryResult($methodName)
612
-			);
613
-		}
614
-
615
-		if($queryType == QueryType::COUNT() || $queryType == QueryType::ENTITIES_WITH_COUNT()){
616
-			//and the provider is supposed to handle the ordered paging they must return a count!
617
-			if($this->queryProvider->handlesOrderedPaging() && !is_numeric($queryResult->count)){
618
-				throw ODataException::createInternalServerError(
619
-					Messages::queryProviderResultCountMissing($methodName, $queryType)
620
-				);
621
-			}
622
-
623
-			//If POData is supposed to handle the ordered aging they must return results! (possibly empty)
624
-			if(!$this->queryProvider->handlesOrderedPaging() && !is_array($queryResult->results)){
625
-				throw ODataException::createInternalServerError(
626
-					Messages::queryProviderResultsMissing($methodName, $queryType)
627
-				);
628
-			}
629
-		}
630
-
631
-		if(($queryType == QueryType::ENTITIES() || $queryType == QueryType::ENTITIES_WITH_COUNT()) && !is_array($queryResult->results)){
632
-			throw ODataException::createInternalServerError(
633
-				Messages::queryProviderResultsMissing($methodName, $queryType)
634
-			);
635
-		}
636
-	}
637
-
638
-	/**
639
-	 * Gets collection of entities belongs to an entity set
640
-	 *
641
-	 * @param QueryType $queryType indicates if this is a query for a count, entities, or entities with a count
642
-	 * @param ResourceSet $resourceSet The entity set containing the entities that need to be fetched
643
-	 * @param FilterInfo $filterInfo represents the $filter parameter of the OData query.  NULL if no $filter specified
644
-	 * @param InternalOrderByInfo $orderBy The orderBy information
645
-	 * @param int $top The top count
646
-	 * @param int $skip The skip count
647
-	 *
648
-	 * @return QueryResult
649
-	 */
650
-	public function getResourceSet(QueryType $queryType, ResourceSet $resourceSet, $filterInfo, $orderBy, $top, $skip, $skiptoken = null, $expansion=null)
651
-	{
652
-
653
-		$queryResult = $this->queryProvider->getResourceSet(
654
-			$queryType,
655
-			$resourceSet,
656
-			$filterInfo,
657
-			$orderBy,
658
-			$top,
659
-			$skip,
660
-			$skiptoken,
661
-			$expansion
662
-		);
663
-
664
-		$this->validateQueryResult($queryResult, $queryType, 'IQueryProvider::getResourceSet');
665
-
666
-		return $queryResult;
667
-	}
668
-
669
-
670
-
671
-	/**
672
-	 * Gets an entity instance from an entity set identified by a key
673
-	 *
674
-	 * @param ResourceSet $resourceSet The entity set containing the entity to fetch
675
-	 * @param KeyDescriptor $keyDescriptor The key identifying the entity to fetch
676
-	 *
677
-	 * @return object|null Returns entity instance if found else null
678
-	 */
679
-	public function getResourceFromResourceSet(ResourceSet $resourceSet, KeyDescriptor $keyDescriptor)
680
-	{
681
-		$entityInstance = $this->queryProvider->getResourceFromResourceSet( $resourceSet, $keyDescriptor );
682
-		$this->_validateEntityInstance(
683
-			$entityInstance,
684
-			$resourceSet,
685
-			$keyDescriptor,
686
-			'IQueryProvider::getResourceFromResourceSet'
687
-		);
688
-		return $entityInstance;
689
-	}
690
-
691
-	/**
692
-	 * Puts an entity instance to entity set identified by a key
693
-	 *
694
-	 * @param ResourceSet $resourceSet The entity set containing the entity to update
695
-	 * @param KeyDescriptor $keyDescriptor The key identifying the entity to update
696
-	 *
697
-	 * @return bool|null Returns result of executiong query
698
-	 */
699
-	public function putResource(
700
-		ResourceSet $resourceSet,
701
-		KeyDescriptor $keyDescriptor,
702
-		$data
703
-	) {
704
-		$queryResult = $this->queryProvider->putResource(
705
-			$resourceSet,
706
-			$keyDescriptor,
707
-			$data
708
-		);
709
-
710
-		return $queryResult;
711
-	}
712
-
713
-	/**
714
-	 * Posts an entity instance to entity set identified by a key
715
-	 *
716
-	 * @param ResourceSet $resourceSet The entity set containing the entity to update
717
-	 * @param KeyDescriptor $keyDescriptor The key identifying the entity to update
718
-	 *
719
-	 * @return bool|null Returns result of executiong query
720
-	 */
721
-	public function postResource(
722
-		ResourceSet $resourceSet,
723
-		$data
724
-	) {
725
-		$queryResult = $this->queryProvider->postResource(
726
-			$resourceSet,
727
-			$data
728
-		);
729
-
730
-		return $queryResult;
731
-	}
732
-
733
-	/**
734
-	 * Posts an entity instance to entity set identified by a key
735
-	 *
736
-	 * @param ResourceSet $resourceSet The entity set containing the entity to update
737
-	 * @param KeyDescriptor $keyDescriptor The key identifying the entity to update
738
-	 *
739
-	 * @return bool|null Returns result of executiong query
740
-	 */
741
-	public function deleteResource(
742
-		ResourceSet $resourceSet,
743
-		$keyDescriptor
744
-	) {
745
-		$queryResult = $this->queryProvider->deleteResource(
746
-			$resourceSet,
747
-			$keyDescriptor
748
-		);
749
-
750
-		return $queryResult;
751
-	}
752
-
753
-	/**
754
-	 * Get related resource set for a resource
755
-	 *
756
-	 * @param QueryType $queryType indicates if this is a query for a count, entities, or entities with a count
757
-	 * @param ResourceSet $sourceResourceSet The entity set containing the source entity
758
-	 * @param object $sourceEntity The source entity instance.
759
-	 * @param ResourceSet      $targetResourceSet    The resource set of containing the target of the navigation property
760
-	 * @param ResourceProperty $targetProperty       The navigation property to retrieve
761
-	 * @param FilterInfo  $filterInfo represents the $filter parameter of the OData query.  NULL if no $filter specified
762
-	 * @param mixed $orderBy sorted order if we want to get the data in some specific order
763
-	 * @param int $top number of records which  need to be skip
764
-	 * @param String $skip value indicating what records to skip
765
-	 *
766
-	 * @return QueryResult
767
-	 *
768
-	 * @throws ODataException
769
-	 */
770
-	public function getRelatedResourceSet(
771
-		QueryType $queryType,
772
-		ResourceSet $sourceResourceSet,
773
-		$sourceEntity,
774
-		ResourceSet $targetResourceSet,
775
-		ResourceProperty $targetProperty,
776
-		$filterInfo,
777
-		$orderBy,
778
-		$top,
779
-		$skip
780
-	) {
781
-
782
-		$queryResult = $this->queryProvider->getRelatedResourceSet(
783
-			$queryType,
784
-			$sourceResourceSet,
785
-			$sourceEntity,
786
-			$targetResourceSet,
787
-			$targetProperty,
788
-			$filterInfo,
789
-			$orderBy,
790
-			$top,
791
-			$skip
792
-		);
793
-
794
-
795
-		$this->validateQueryResult($queryResult, $queryType, 'IQueryProvider::getRelatedResourceSet');
796
-
797
-
798
-		return $queryResult;
799
-	}
800
-
801
-	/**
802
-	 * Gets a related entity instance from an entity set identified by a key
803
-	 *
804
-	 * @param ResourceSet      $sourceResourceSet The entity set related to the entity to be fetched.
805
-	 * @param object           $sourceEntity      The related entity instance.
806
-	 * @param ResourceSet      $targetResourceSet The entity set from which entity needs to be fetched.
807
-	 * @param ResourceProperty $targetProperty    The metadata of the target property.
808
-	 * @param KeyDescriptor    $keyDescriptor     The key to identify the entity to be fetched.
809
-	 *
810
-	 *
811
-	 * @return object|null Returns entity instance if found else null
812
-	 */
813
-	public function getResourceFromRelatedResourceSet(ResourceSet $sourceResourceSet,
814
-		$sourceEntity, ResourceSet $targetResourceSet, ResourceProperty $targetProperty,
815
-		KeyDescriptor $keyDescriptor
816
-	) {
817
-		$entityInstance = $this->queryProvider->getResourceFromRelatedResourceSet(
818
-			$sourceResourceSet,
819
-			$sourceEntity,
820
-			$targetResourceSet,
821
-			$targetProperty,
822
-			$keyDescriptor
823
-		);
824
-
825
-		$this->_validateEntityInstance(
826
-			$entityInstance, $targetResourceSet,
827
-			$keyDescriptor,
828
-			'IQueryProvider::getResourceFromRelatedResourceSet'
829
-		);
830
-		return $entityInstance;
831
-	}
832
-
833
-	/**
834
-	 * Get related resource for a resource
835
-	 *
836
-	 * @param ResourceSet      $sourceResourceSet The source resource set
837
-	 * @param object           $sourceEntity      The source resource
838
-	 * @param ResourceSet      $targetResourceSet The resource set of the navigation
839
-	 *                                            property
840
-	 * @param ResourceProperty $targetProperty    The navigation property to be
841
-	 *                                            retrieved
842
-	 *
843
-	 * @return object|null The related resource if exists else null
844
-	 */
845
-	public function getRelatedResourceReference(ResourceSet $sourceResourceSet,
846
-		$sourceEntity, ResourceSet $targetResourceSet,
847
-		ResourceProperty $targetProperty
848
-	) {
849
-		$entityInstance = $this->queryProvider->getRelatedResourceReference(
850
-			$sourceResourceSet,
851
-			$sourceEntity,
852
-			$targetResourceSet,
853
-			$targetProperty
854
-		);
855
-
856
-		// we will not throw error if the resource reference is null
857
-		// e.g. Orders(1234)/Customer => Customer can be null, this is
858
-		// allowed if Customer is last segment. consider the following:
859
-		// Orders(1234)/Customer/Orders => here if Customer is null then
860
-		// the UriProcessor will throw error.
861
-		if (!is_null($entityInstance)) {
862
-			$entityName
863
-				= $targetResourceSet
864
-					->getResourceType()
865
-					->getInstanceType()
866
-					->getName();
867
-			if (!is_object($entityInstance)
868
-				|| !($entityInstance instanceof $entityName)
869
-			) {
870
-				throw ODataException::createInternalServerError(
871
-					Messages::providersWrapperIDSQPMethodReturnsUnExpectedType(
872
-						$entityName,
873
-						'IQueryProvider::getRelatedResourceReference'
874
-					)
875
-				);
876
-			}
877
-
878
-			foreach ($targetProperty->getResourceType()->getKeyProperties()
879
-			as $keyName => $resourceProperty) {
880
-				try {
881
-					$keyProperty = new \ReflectionProperty(
882
-						$entityInstance,
883
-						$keyName
884
-					);
885
-					$keyProperty->setAccessible(true);
886
-					$keyValue = $keyProperty->getValue($entityInstance);
887
-					if (is_null($keyValue)) {
888
-						throw ODataException::createInternalServerError(
889
-							Messages::providersWrapperIDSQPMethodReturnsInstanceWithNullKeyProperties('IDSQP::getRelatedResourceReference')
890
-						);
891
-					}
892
-				} catch (\ReflectionException $reflectionException) {
893
-					//throw ODataException::createInternalServerError(
894
-					//    Messages::orderByParserFailedToAccessOrInitializeProperty(
895
-					//        $resourceProperty->getName(), $resourceType->getName()
896
-					//    )
897
-					//);
898
-				}
899
-			}
900
-		}
901
-
902
-		return $entityInstance;
903
-	}
904
-
905
-	/**
906
-	 * Validate the given entity instance.
907
-	 *
908
-	 * @param object        $entityInstance Entity instance to validate
909
-	 * @param ResourceSet   &$resourceSet   Resource set to which the entity
910
-	 *                                      instance belongs to.
911
-	 * @param KeyDescriptor &$keyDescriptor The key descriptor.
912
-	 * @param string        $methodName     Method from which this function
913
-	 *                                      invoked.
914
-	 *
915
-	 * @return void
916
-	 *
917
-	 * @throws ODataException
918
-	 */
919
-	private function _validateEntityInstance($entityInstance,
920
-		ResourceSet &$resourceSet,
921
-		KeyDescriptor &$keyDescriptor,
922
-		$methodName
923
-	) {
924
-		if (is_null($entityInstance)) {
925
-			throw ODataException::createResourceNotFoundError($resourceSet->getName());
926
-		}
927
-
928
-		$entityName = $resourceSet->getResourceType()->getInstanceType()->getName();
929
-		if (!is_object($entityInstance)
930
-			|| !($entityInstance instanceof $entityName)
931
-		) {
932
-			throw ODataException::createInternalServerError(
933
-				Messages::providersWrapperIDSQPMethodReturnsUnExpectedType(
934
-					$entityName,
935
-					$methodName
936
-				)
937
-			);
938
-		}
939
-
940
-		foreach ($keyDescriptor->getValidatedNamedValues()
941
-			as $keyName => $valueDescription) {
942
-			try {
943
-				$keyProperty = new \ReflectionProperty($entityInstance, $keyName);
944
-				$keyProperty->setAccessible(true);
945
-				$keyValue = $keyProperty->getValue($entityInstance);
946
-				if (is_null($keyValue)) {
947
-					throw ODataException::createInternalServerError(
948
-						Messages::providersWrapperIDSQPMethodReturnsInstanceWithNullKeyProperties($methodName)
949
-					);
950
-				}
951
-
952
-				$convertedValue
953
-					= $valueDescription[1]->convert($valueDescription[0]);
954
-				if ($keyValue != $convertedValue) {
955
-					throw ODataException::createInternalServerError(
956
-						Messages::providersWrapperIDSQPMethodReturnsInstanceWithNonMatchingKeys($methodName)
957
-					);
958
-				}
959
-			} catch (\ReflectionException $reflectionException) {
960
-				//throw ODataException::createInternalServerError(
961
-				//  Messages::orderByParserFailedToAccessOrInitializeProperty(
962
-				//      $resourceProperty->getName(), $resourceType->getName()
963
-				//  )
964
-				//);
965
-			}
966
-		}
967
-	}
968
-
969
-	/**
970
-	 * Assert that the given condition is true.
971
-	 *
972
-	 * @param boolean $condition         Condition to be asserted.
973
-	 * @param string  $conditionAsString String containing message incase
974
-	 *                                   if assertion fails.
975
-	 *
976
-	 * @throws InvalidOperationException Incase if assertion fails.
977
-	 *
978
-	 * @return void
979
-	 */
980
-	protected function assert($condition, $conditionAsString)
981
-	{
982
-		if (!$condition) {
983
-			throw new InvalidOperationException("Unexpected state, expecting $conditionAsString");
984
-		}
985
-	}
35
+    /**
36
+     * Holds reference to IMetadataProvider implementation
37
+     *
38
+     * @var IMetadataProvider
39
+     */
40
+    private $metaProvider;
41
+
42
+    /**
43
+     * Holds reference to IQueryProvider implementation
44
+     *
45
+     * @var IQueryProvider
46
+     *
47
+     */
48
+    private $queryProvider;
49
+
50
+    /**
51
+     * Holds reference to IServiceConfiguration implementation
52
+     *
53
+     * @var ServiceConfiguration
54
+     */
55
+    private $config;
56
+
57
+
58
+    /**
59
+     * Cache for ResourceProperties of a resource type that belongs to a
60
+     * resource set. An entry (ResourceProperty collection) in this cache
61
+     * contains only the visible properties of ResourceType.
62
+     *
63
+     * @var array(string, array(string, ResourceProperty))
64
+     */
65
+    private $propertyCache;
66
+
67
+    /**
68
+     * Cache for ResourceSetWrappers. If ResourceSet is invisible value will
69
+     * be null.
70
+     *
71
+     * @var ResourceSetWrapper[] indexed by resource set name
72
+     */
73
+    private $setWrapperCache;
74
+
75
+    /**
76
+     * Cache for ResourceTypes
77
+     *
78
+     * @var ResourceType[] indexed by resource type name
79
+     */
80
+    private $typeCache;
81
+
82
+    /**
83
+     * Cache for ResourceAssociationSet. If ResourceAssociationSet is invisible
84
+     * value will be null.
85
+     *
86
+     * @var ResourceAssociationSet[] indexed by name
87
+     */
88
+    private $associationSetCache;
89
+
90
+    /**
91
+     * Creates a new instance of ProvidersWrapper
92
+     *
93
+     * @param IMetadataProvider $metadataProvider Reference to IMetadataProvider implementation
94
+     * @param IQueryProvider    $queryProvider    Reference to IQueryProvider implementation
95
+     * @param ServiceConfiguration    $configuration    Reference to IServiceConfiguration implementation
96
+     */
97
+    public function __construct(IMetadataProvider $metadataProvider, IQueryProvider $queryProvider, ServiceConfiguration $configuration)
98
+    {
99
+        $this->metaProvider = $metadataProvider;
100
+        $this->queryProvider = $queryProvider;
101
+        $this->config = $configuration;
102
+        $this->setWrapperCache = array();
103
+        $this->typeCache = array();
104
+        $this->associationSetCache = array();
105
+        $this->propertyCache = array();
106
+    }
107
+
108
+    //Wrappers for IMetadataProvider methods
109
+
110
+    /**
111
+     * To get the Container name for the data source,
112
+     * Note: Wrapper for IMetadataProvider::getContainerName method
113
+     * implementation
114
+     *
115
+     * @return string that contains the name of the container
116
+     *
117
+     * @throws ODataException Exception if implementation returns empty container name
118
+     *
119
+     */
120
+    public function getContainerName()
121
+    {
122
+        $containerName = $this->metaProvider->getContainerName();
123
+        if (empty($containerName)) {
124
+            throw new ODataException(
125
+                Messages::providersWrapperContainerNameMustNotBeNullOrEmpty(),
126
+                500
127
+            );
128
+        }
129
+
130
+        return $containerName;
131
+    }
132
+
133
+    /**
134
+     * To get Namespace name for the data source,
135
+     * Note: Wrapper for IMetadataProvider::getContainerNamespace method implementation
136
+     *
137
+     * @return string that contains the namespace name.
138
+     *
139
+     * @throws ODataException Exception if implementation returns empty container namespace
140
+     *
141
+     */
142
+    public function getContainerNamespace()
143
+    {
144
+        $containerNamespace = $this->metaProvider->getContainerNamespace();
145
+        if (empty($containerNamespace)) {
146
+            throw new ODataException(
147
+                Messages::providersWrapperContainerNamespaceMustNotBeNullOrEmpty(),
148
+                500
149
+            );
150
+        }
151
+
152
+        return $containerNamespace;
153
+    }
154
+
155
+    /**
156
+     * To get the data service configuration
157
+     *
158
+     * @return ServiceConfiguration
159
+     */
160
+    public function getConfiguration()
161
+    {
162
+        return $this->config;
163
+    }
164
+
165
+    /**
166
+     *  To get all entity set information,
167
+     *  Note: Wrapper for IMetadataProvider::getResourceSets method implementation,
168
+     *  This method returns array of ResourceSetWrapper instances but the corresponding IDSMP method returns array of ResourceSet instances
169
+     *
170
+     *  @return ResourceSetWrapper[] The ResourceSetWrappers for the visible ResourceSets
171
+     *  @throws ODataException when two resource sets with the same name are encountered
172
+     *
173
+     */
174
+    public function getResourceSets()
175
+    {
176
+        $resourceSets = $this->metaProvider->getResourceSets();
177
+        $resourceSetWrappers = array();
178
+        $resourceSetNames = array();
179
+        foreach ($resourceSets as $resourceSet) {
180
+            $name = $resourceSet->getName();
181
+            if (in_array($name, $resourceSetNames)) {
182
+                throw new ODataException(Messages::providersWrapperEntitySetNameShouldBeUnique($name), 500 );
183
+            }
184
+
185
+            $resourceSetNames[] = $name;
186
+            $resourceSetWrapper = $this->_validateResourceSetAndGetWrapper($resourceSet);
187
+            if (!is_null($resourceSetWrapper)) {
188
+                $resourceSetWrappers[] = $resourceSetWrapper;
189
+            }
190
+        }
191
+
192
+        return $resourceSetWrappers;
193
+    }
194
+
195
+    /**
196
+     * To get all resource types in the data source,
197
+     * Note: Wrapper for IMetadataProvider::getTypes method implementation
198
+     *
199
+     * @return ResourceType[]
200
+     */
201
+    public function getTypes()
202
+    {
203
+        $resourceTypes = $this->metaProvider->getTypes();
204
+        $resourceTypeNames = array();
205
+        foreach ($resourceTypes as $resourceType) {
206
+            if (in_array($resourceType->getName(), $resourceTypeNames)) {
207
+                throw new ODataException(
208
+                    Messages::providersWrapperEntityTypeNameShouldBeUnique($resourceType->getName()),
209
+                    500
210
+                );
211
+            }
212
+
213
+            $resourceTypeNames[] = $resourceType->getName();
214
+            $this->_validateResourceType($resourceType);
215
+        }
216
+
217
+        return $resourceTypes;
218
+    }
219
+
220
+    /**
221
+     * To get a resource set based on the specified resource set name which is
222
+     * visible,
223
+     * Note: Wrapper for IMetadataProvider::resolveResourceSet method
224
+     * implementation
225
+     *
226
+     * @param string $name Name of the resource set
227
+     *
228
+     * @return ResourceSetWrapper|null Returns resource set with the given name if found, NULL if resource set is set to invisible or not found
229
+     *
230
+     */
231
+    public function resolveResourceSet($name)
232
+    {
233
+        if (array_key_exists($name, $this->setWrapperCache)) {
234
+            return $this->setWrapperCache[$name];
235
+        }
236
+
237
+        $resourceSet = $this->metaProvider->resolveResourceSet($name);
238
+        if (is_null($resourceSet)) {
239
+            return null;
240
+        }
241
+
242
+        return $this->_validateResourceSetAndGetWrapper($resourceSet);
243
+    }
244
+
245
+    /**
246
+     * To get a resource type based on the resource set name,
247
+     * Note: Wrapper for IMetadataProvider::resolveResourceType
248
+     * method implementation
249
+     *
250
+     * @param string $name Name of the resource set
251
+     *
252
+     * @return ResourceType|null resource type with the given resource set name if found else NULL
253
+     *
254
+     *
255
+     * @throws ODataException If the ResourceType is invalid
256
+     */
257
+    public function resolveResourceType($name)
258
+    {
259
+        $resourceType = $this->metaProvider->resolveResourceType($name);
260
+        if (is_null($resourceType)) {
261
+            return null;
262
+        }
263
+
264
+        return $this->_validateResourceType($resourceType);
265
+    }
266
+
267
+    /**
268
+     * The method must return a collection of all the types derived from
269
+     * $resourceType The collection returned should NOT include the type
270
+     * passed in as a parameter
271
+     * Note: Wrapper for IMetadataProvider::getDerivedTypes
272
+     * method implementation
273
+     *
274
+     * @param ResourceType $resourceType Resource to get derived resource types from
275
+     *
276
+     * @return ResourceType[]
277
+     *
278
+     * @throws InvalidOperationException when the meat provider doesn't return an array
279
+     */
280
+    public function getDerivedTypes(ResourceType $resourceType)
281
+    {
282
+        $derivedTypes = $this->metaProvider->getDerivedTypes($resourceType);
283
+        if (!is_array($derivedTypes)) {
284
+            throw new InvalidOperationException(Messages::metadataAssociationTypeSetInvalidGetDerivedTypesReturnType($resourceType->getName()));
285
+        }
286
+
287
+        foreach ($derivedTypes as $derivedType) {
288
+            $this->_validateResourceType($derivedType);
289
+        }
290
+
291
+        return $derivedTypes;
292
+    }
293
+
294
+    /**
295
+     * Returns true if $resourceType represents an Entity Type which has derived
296
+     * Entity Types, else false.
297
+     * Note: Wrapper for IMetadataProvider::hasDerivedTypes method
298
+     * implementation
299
+     *
300
+     * @param ResourceType $resourceType Resource to check for derived resource
301
+     *                                   types.
302
+     *
303
+     * @return boolean
304
+     *
305
+     * @throws ODataException If the ResourceType is invalid
306
+     */
307
+    public function hasDerivedTypes(ResourceType $resourceType)
308
+    {
309
+        $this->_validateResourceType($resourceType);
310
+        return $this->metaProvider->hasDerivedTypes($resourceType);
311
+    }
312
+
313
+    /**
314
+     * Gets the ResourceAssociationSet instance for the given source association end,
315
+     * Note: Wrapper for IMetadataProvider::getResourceAssociationSet
316
+     * method implementation
317
+     *
318
+     * @param ResourceSet $set Resource set of the source association end
319
+     * @param ResourceType       $type       Resource type of the source association end
320
+     * @param ResourceProperty   $property   Resource property of the source association end
321
+     *
322
+     *
323
+     * @return ResourceAssociationSet|null Returns ResourceAssociationSet for the source
324
+     *                                             association end, NULL if no such
325
+     *                                             association end or resource set in the
326
+     *                                             other end of the association is invisible
327
+     */
328
+    public function getResourceAssociationSet(
329
+        ResourceSet $set,
330
+        ResourceType $type,
331
+        ResourceProperty $property
332
+    ) {
333
+        $type = $this->_getResourceTypeWherePropertyIsDeclared($type, $property);
334
+        $cacheKey = $set->getName() . '_' . $type->getName() . '_' . $property->getName();
335
+
336
+        if (array_key_exists($cacheKey,  $this->associationSetCache)) {
337
+            return $this->associationSetCache[$cacheKey];
338
+        }
339
+
340
+        $associationSet = $this->metaProvider->getResourceAssociationSet(
341
+            $set,
342
+            $type,
343
+            $property
344
+        );
345
+
346
+        if (!is_null($associationSet)) {
347
+            $thisAssociationSetEnd = $associationSet->getResourceAssociationSetEnd(
348
+                $set,
349
+                $type,
350
+                $property
351
+            );
352
+
353
+            $relatedAssociationSetEnd = $associationSet->getRelatedResourceAssociationSetEnd(
354
+                $set,
355
+                $type,
356
+                $property
357
+            );
358
+
359
+            //If $thisAssociationSetEnd or $relatedAssociationSetEnd
360
+            //is null means the associationset
361
+            //we got from the IDSMP::getResourceAssociationSet is invalid.
362
+            //AssociationSet::getResourceAssociationSetEnd
363
+            //return null, if AssociationSet's End1 or End2's resourceset name
364
+            //is not matching with the name of
365
+            //resource set wrapper (param1) and resource type is not assignable
366
+            //from given resource type (param2)
367
+            if (is_null($thisAssociationSetEnd) || is_null($relatedAssociationSetEnd)) {
368
+                throw new ODataException(
369
+                    Messages::providersWrapperIDSMPGetResourceSetReturnsInvalidResourceSet(
370
+                        $set->getName(),
371
+                        $type->getFullName(),
372
+                        $property->getName()
373
+                    ),
374
+                    500
375
+                );
376
+            }
377
+
378
+            $relatedResourceSetWrapper = $this->_validateResourceSetAndGetWrapper(
379
+                $relatedAssociationSetEnd->getResourceSet()
380
+            );
381
+            if ($relatedResourceSetWrapper === null) {
382
+                $associationSet = null;
383
+            } else {
384
+                $this->_validateResourceType($thisAssociationSetEnd->getResourceType());
385
+                $this->_validateResourceType($relatedAssociationSetEnd->getResourceType());
386
+            }
387
+        }
388
+
389
+        $this->associationSetCache[$cacheKey] = $associationSet;
390
+        return $associationSet;
391
+    }
392
+
393
+    /**
394
+     * Gets the target resource set wrapper for the given navigation property,
395
+     * source resource set wrapper and the source resource type
396
+     *
397
+     * @param ResourceSetWrapper $resourceSetWrapper         Source resource set.
398
+     * @param ResourceType       $resourceType               Source resource type.
399
+     * @param ResourceProperty   $navigationResourceProperty Navigation property.
400
+     *
401
+     * @return ResourceSetWrapper|null Returns instance of ResourceSetWrapper
402
+     *     (describes the entity set and associated configuration) for the
403
+     *     given navigation property. returns NULL if resourceset for the
404
+     *     navigation property is invisible or if metadata provider returns
405
+     *     null resource association set
406
+     */
407
+    public function getResourceSetWrapperForNavigationProperty(
408
+        ResourceSetWrapper $resourceSetWrapper,
409
+        ResourceType $resourceType,
410
+        ResourceProperty $navigationResourceProperty
411
+    ) {
412
+        $associationSet = $this->getResourceAssociationSet(
413
+            $resourceSetWrapper,
414
+            $resourceType,
415
+            $navigationResourceProperty
416
+        );
417
+
418
+        if (!is_null($associationSet)) {
419
+            $relatedAssociationSetEnd = $associationSet->getRelatedResourceAssociationSetEnd(
420
+                $resourceSetWrapper->getResourceSet(),
421
+                $resourceType,
422
+                $navigationResourceProperty
423
+            );
424
+            return $this->_validateResourceSetAndGetWrapper(
425
+                $relatedAssociationSetEnd->getResourceSet()
426
+            );
427
+        }
428
+
429
+        return null;
430
+    }
431
+
432
+    /**
433
+     * Gets the visible resource properties for the given resource type from the given resource set wrapper.
434
+     *
435
+     * @param ResourceSetWrapper $setWrapper Resource set wrapper in question.
436
+     * @param ResourceType       $resourceType       Resource type in question.
437
+     * @return ResourceProperty[] Collection of visible resource properties from the given resource set wrapper and resource type.
438
+     */
439
+    public function getResourceProperties(ResourceSetWrapper $setWrapper, ResourceType $resourceType) {
440
+        if ($resourceType->getResourceTypeKind() != ResourceTypeKind::ENTITY) {
441
+            //Complex resource type
442
+            return $resourceType->getAllProperties();
443
+        }
444
+        //TODO: move this to doctrine annotations
445
+        $cacheKey = $setWrapper->getName() . '_' . $resourceType->getFullName();
446
+        if (!array_key_exists($cacheKey,  $this->propertyCache)) {
447
+            //Fill the cache
448
+            $this->propertyCache[$cacheKey] = array();
449
+            foreach ($resourceType->getAllProperties() as $resourceProperty) {
450
+                //Check whether this is a visible navigation property
451
+                //TODO: is this broken?? see #87
452
+                if ($resourceProperty->getTypeKind() == ResourceTypeKind::ENTITY
453
+                    && !is_null($this->getResourceSetWrapperForNavigationProperty($setWrapper, $resourceType, $resourceProperty))
454
+                ) {
455
+                    $this->propertyCache[$cacheKey][$resourceProperty->getName()] = $resourceProperty;
456
+                } else {
457
+                    //primitive, bag or complex property
458
+                    $this->propertyCache[$cacheKey][$resourceProperty->getName()] = $resourceProperty;
459
+                }
460
+            }
461
+        }
462
+        return $this->propertyCache[$cacheKey];
463
+
464
+    }
465
+
466
+    /**
467
+     * Wrapper function over _validateResourceSetAndGetWrapper function
468
+     *
469
+     * @param ResourceSet $resourceSet see the comments of _validateResourceSetAndGetWrapper
470
+     *
471
+     * @return ResourceSetWrapper|null see the comments of _validateResourceSetAndGetWrapper
472
+     */
473
+    public function validateResourceSetAndGetWrapper(ResourceSet $resourceSet)
474
+    {
475
+        return $this->_validateResourceSetAndGetWrapper($resourceSet);
476
+    }
477
+
478
+    /**
479
+     * Gets the Edm Schema version compliance to the metadata
480
+     *
481
+     * @return EdmSchemaVersion
482
+     */
483
+    public function getEdmSchemaVersion()
484
+    {
485
+        //The minimal schema version for custom provider is 1.1
486
+        return EdmSchemaVersion::VERSION_1_DOT_1;
487
+    }
488
+
489
+    /**
490
+     * This function perform the following operations
491
+     *  (1) If the cache contain an entry [key, value] for the resourceset then
492
+     *      return the entry-value
493
+     *  (2) If the cache not contain an entry for the resourceset then validate
494
+     *      the resourceset
495
+     *            (a) If valid add entry as [resouceset_name, resourceSetWrapper]
496
+     *            (b) if not valid add entry as [resouceset_name, null]
497
+     *  Note: validating a resourceset means checking the resourceset is visible
498
+     *  or not using configuration
499
+     *
500
+     * @param ResourceSet $resourceSet The resourceset to validate and get the
501
+     *                                 wrapper for
502
+     *
503
+     * @return ResourceSetWrapper|null Returns an instance if a resource set with the given name is visible
504
+     */
505
+    private function _validateResourceSetAndGetWrapper(ResourceSet $resourceSet)
506
+    {
507
+        $cacheKey = $resourceSet->getName();
508
+        if (array_key_exists($cacheKey, $this->setWrapperCache)) {
509
+            return $this->setWrapperCache[$cacheKey];
510
+        }
511
+
512
+        $this->_validateResourceType($resourceSet->getResourceType());
513
+        $wrapper = new ResourceSetWrapper($resourceSet, $this->config);
514
+        if ($wrapper->isVisible()) {
515
+            $this->setWrapperCache[$cacheKey] = $wrapper;
516
+        } else {
517
+            $this->setWrapperCache[$cacheKey] = null;
518
+        }
519
+
520
+        return $this->setWrapperCache[$cacheKey];
521
+    }
522
+
523
+    /**
524
+     * Validates the given instance of ResourceType
525
+     *
526
+     * @param ResourceType $resourceType The ResourceType to validate
527
+     *
528
+     * @return ResourceType
529
+     *
530
+     * @throws ODataException Exception if $resourceType is invalid
531
+     */
532
+    private function _validateResourceType(ResourceType $resourceType)
533
+    {
534
+        $cacheKey = $resourceType->getName();
535
+        if (array_key_exists($cacheKey, $this->typeCache)) {
536
+            return $this->typeCache[$cacheKey];
537
+        }
538
+
539
+        //TODO: Do validation if any for the ResourceType
540
+        $this->typeCache[$cacheKey] = $resourceType;
541
+        return $resourceType;
542
+    }
543
+
544
+    /**
545
+     * Gets the resource type on which the resource property is declared on,
546
+     * If property is not declared in the given resource type, then this
547
+     * function drill down to the inheritance hierarchy of the given resource
548
+     * type to find out the base class in which the property is declared
549
+     *
550
+     * @param ResourceType     $resourceType     The resource type to start looking
551
+     * @param ResourceProperty $resourceProperty The resource property in question
552
+     *
553
+     * @return ResourceType|null Returns reference to the ResourceType on which
554
+     *                                   the $resourceProperty is declared, NULL if
555
+     *                                   $resourceProperty is not declared anywhere
556
+     *                                   in the inheritance hierarchy
557
+     */
558
+    private function _getResourceTypeWherePropertyIsDeclared(ResourceType $resourceType,
559
+        ResourceProperty $resourceProperty
560
+    ) {
561
+        $type = $resourceType;
562
+        while ($type !== null) {
563
+            if ($type->resolvePropertyDeclaredOnThisType($resourceProperty->getName()) !== null) {
564
+                break;
565
+            }
566
+
567
+            $type = $type->getBaseType();
568
+        }
569
+
570
+        return $type;
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
+     */
580
+    public function getExpressionProvider()
581
+    {
582
+        $expressionProvider = $this->queryProvider->getExpressionProvider();
583
+        if (is_null($expressionProvider)) {
584
+            throw ODataException::createInternalServerError(Messages::providersWrapperExpressionProviderMustNotBeNullOrEmpty());
585
+        }
586
+
587
+        if (!$expressionProvider instanceof IExpressionProvider)
588
+        {
589
+            throw ODataException::createInternalServerError( Messages::providersWrapperInvalidExpressionProviderInstance() );
590
+        }
591
+
592
+        return $expressionProvider;
593
+    }
594
+
595
+    /**
596
+     * Indicates if the QueryProvider can handle ordered paging, this means respecting order, skip, and top parameters
597
+     * If the query provider can not handle ordered paging, it must return the entire result set and POData will
598
+     * perform the ordering and paging
599
+     *
600
+     * @return Boolean True if the query provider can handle ordered paging, false if POData should perform the paging
601
+     */
602
+    public function handlesOrderedPaging()
603
+    {
604
+        return $this->queryProvider->handlesOrderedPaging();
605
+    }
606
+
607
+
608
+    private function ValidateQueryResult($queryResult, QueryType $queryType, $methodName){
609
+        if (!$queryResult instanceof QueryResult) {
610
+            throw ODataException::createInternalServerError(
611
+                Messages::queryProviderReturnsNonQueryResult($methodName)
612
+            );
613
+        }
614
+
615
+        if($queryType == QueryType::COUNT() || $queryType == QueryType::ENTITIES_WITH_COUNT()){
616
+            //and the provider is supposed to handle the ordered paging they must return a count!
617
+            if($this->queryProvider->handlesOrderedPaging() && !is_numeric($queryResult->count)){
618
+                throw ODataException::createInternalServerError(
619
+                    Messages::queryProviderResultCountMissing($methodName, $queryType)
620
+                );
621
+            }
622
+
623
+            //If POData is supposed to handle the ordered aging they must return results! (possibly empty)
624
+            if(!$this->queryProvider->handlesOrderedPaging() && !is_array($queryResult->results)){
625
+                throw ODataException::createInternalServerError(
626
+                    Messages::queryProviderResultsMissing($methodName, $queryType)
627
+                );
628
+            }
629
+        }
630
+
631
+        if(($queryType == QueryType::ENTITIES() || $queryType == QueryType::ENTITIES_WITH_COUNT()) && !is_array($queryResult->results)){
632
+            throw ODataException::createInternalServerError(
633
+                Messages::queryProviderResultsMissing($methodName, $queryType)
634
+            );
635
+        }
636
+    }
637
+
638
+    /**
639
+     * Gets collection of entities belongs to an entity set
640
+     *
641
+     * @param QueryType $queryType indicates if this is a query for a count, entities, or entities with a count
642
+     * @param ResourceSet $resourceSet The entity set containing the entities that need to be fetched
643
+     * @param FilterInfo $filterInfo represents the $filter parameter of the OData query.  NULL if no $filter specified
644
+     * @param InternalOrderByInfo $orderBy The orderBy information
645
+     * @param int $top The top count
646
+     * @param int $skip The skip count
647
+     *
648
+     * @return QueryResult
649
+     */
650
+    public function getResourceSet(QueryType $queryType, ResourceSet $resourceSet, $filterInfo, $orderBy, $top, $skip, $skiptoken = null, $expansion=null)
651
+    {
652
+
653
+        $queryResult = $this->queryProvider->getResourceSet(
654
+            $queryType,
655
+            $resourceSet,
656
+            $filterInfo,
657
+            $orderBy,
658
+            $top,
659
+            $skip,
660
+            $skiptoken,
661
+            $expansion
662
+        );
663
+
664
+        $this->validateQueryResult($queryResult, $queryType, 'IQueryProvider::getResourceSet');
665
+
666
+        return $queryResult;
667
+    }
668
+
669
+
670
+
671
+    /**
672
+     * Gets an entity instance from an entity set identified by a key
673
+     *
674
+     * @param ResourceSet $resourceSet The entity set containing the entity to fetch
675
+     * @param KeyDescriptor $keyDescriptor The key identifying the entity to fetch
676
+     *
677
+     * @return object|null Returns entity instance if found else null
678
+     */
679
+    public function getResourceFromResourceSet(ResourceSet $resourceSet, KeyDescriptor $keyDescriptor)
680
+    {
681
+        $entityInstance = $this->queryProvider->getResourceFromResourceSet( $resourceSet, $keyDescriptor );
682
+        $this->_validateEntityInstance(
683
+            $entityInstance,
684
+            $resourceSet,
685
+            $keyDescriptor,
686
+            'IQueryProvider::getResourceFromResourceSet'
687
+        );
688
+        return $entityInstance;
689
+    }
690
+
691
+    /**
692
+     * Puts an entity instance to entity set identified by a key
693
+     *
694
+     * @param ResourceSet $resourceSet The entity set containing the entity to update
695
+     * @param KeyDescriptor $keyDescriptor The key identifying the entity to update
696
+     *
697
+     * @return bool|null Returns result of executiong query
698
+     */
699
+    public function putResource(
700
+        ResourceSet $resourceSet,
701
+        KeyDescriptor $keyDescriptor,
702
+        $data
703
+    ) {
704
+        $queryResult = $this->queryProvider->putResource(
705
+            $resourceSet,
706
+            $keyDescriptor,
707
+            $data
708
+        );
709
+
710
+        return $queryResult;
711
+    }
712
+
713
+    /**
714
+     * Posts an entity instance to entity set identified by a key
715
+     *
716
+     * @param ResourceSet $resourceSet The entity set containing the entity to update
717
+     * @param KeyDescriptor $keyDescriptor The key identifying the entity to update
718
+     *
719
+     * @return bool|null Returns result of executiong query
720
+     */
721
+    public function postResource(
722
+        ResourceSet $resourceSet,
723
+        $data
724
+    ) {
725
+        $queryResult = $this->queryProvider->postResource(
726
+            $resourceSet,
727
+            $data
728
+        );
729
+
730
+        return $queryResult;
731
+    }
732
+
733
+    /**
734
+     * Posts an entity instance to entity set identified by a key
735
+     *
736
+     * @param ResourceSet $resourceSet The entity set containing the entity to update
737
+     * @param KeyDescriptor $keyDescriptor The key identifying the entity to update
738
+     *
739
+     * @return bool|null Returns result of executiong query
740
+     */
741
+    public function deleteResource(
742
+        ResourceSet $resourceSet,
743
+        $keyDescriptor
744
+    ) {
745
+        $queryResult = $this->queryProvider->deleteResource(
746
+            $resourceSet,
747
+            $keyDescriptor
748
+        );
749
+
750
+        return $queryResult;
751
+    }
752
+
753
+    /**
754
+     * Get related resource set for a resource
755
+     *
756
+     * @param QueryType $queryType indicates if this is a query for a count, entities, or entities with a count
757
+     * @param ResourceSet $sourceResourceSet The entity set containing the source entity
758
+     * @param object $sourceEntity The source entity instance.
759
+     * @param ResourceSet      $targetResourceSet    The resource set of containing the target of the navigation property
760
+     * @param ResourceProperty $targetProperty       The navigation property to retrieve
761
+     * @param FilterInfo  $filterInfo represents the $filter parameter of the OData query.  NULL if no $filter specified
762
+     * @param mixed $orderBy sorted order if we want to get the data in some specific order
763
+     * @param int $top number of records which  need to be skip
764
+     * @param String $skip value indicating what records to skip
765
+     *
766
+     * @return QueryResult
767
+     *
768
+     * @throws ODataException
769
+     */
770
+    public function getRelatedResourceSet(
771
+        QueryType $queryType,
772
+        ResourceSet $sourceResourceSet,
773
+        $sourceEntity,
774
+        ResourceSet $targetResourceSet,
775
+        ResourceProperty $targetProperty,
776
+        $filterInfo,
777
+        $orderBy,
778
+        $top,
779
+        $skip
780
+    ) {
781
+
782
+        $queryResult = $this->queryProvider->getRelatedResourceSet(
783
+            $queryType,
784
+            $sourceResourceSet,
785
+            $sourceEntity,
786
+            $targetResourceSet,
787
+            $targetProperty,
788
+            $filterInfo,
789
+            $orderBy,
790
+            $top,
791
+            $skip
792
+        );
793
+
794
+
795
+        $this->validateQueryResult($queryResult, $queryType, 'IQueryProvider::getRelatedResourceSet');
796
+
797
+
798
+        return $queryResult;
799
+    }
800
+
801
+    /**
802
+     * Gets a related entity instance from an entity set identified by a key
803
+     *
804
+     * @param ResourceSet      $sourceResourceSet The entity set related to the entity to be fetched.
805
+     * @param object           $sourceEntity      The related entity instance.
806
+     * @param ResourceSet      $targetResourceSet The entity set from which entity needs to be fetched.
807
+     * @param ResourceProperty $targetProperty    The metadata of the target property.
808
+     * @param KeyDescriptor    $keyDescriptor     The key to identify the entity to be fetched.
809
+     *
810
+     *
811
+     * @return object|null Returns entity instance if found else null
812
+     */
813
+    public function getResourceFromRelatedResourceSet(ResourceSet $sourceResourceSet,
814
+        $sourceEntity, ResourceSet $targetResourceSet, ResourceProperty $targetProperty,
815
+        KeyDescriptor $keyDescriptor
816
+    ) {
817
+        $entityInstance = $this->queryProvider->getResourceFromRelatedResourceSet(
818
+            $sourceResourceSet,
819
+            $sourceEntity,
820
+            $targetResourceSet,
821
+            $targetProperty,
822
+            $keyDescriptor
823
+        );
824
+
825
+        $this->_validateEntityInstance(
826
+            $entityInstance, $targetResourceSet,
827
+            $keyDescriptor,
828
+            'IQueryProvider::getResourceFromRelatedResourceSet'
829
+        );
830
+        return $entityInstance;
831
+    }
832
+
833
+    /**
834
+     * Get related resource for a resource
835
+     *
836
+     * @param ResourceSet      $sourceResourceSet The source resource set
837
+     * @param object           $sourceEntity      The source resource
838
+     * @param ResourceSet      $targetResourceSet The resource set of the navigation
839
+     *                                            property
840
+     * @param ResourceProperty $targetProperty    The navigation property to be
841
+     *                                            retrieved
842
+     *
843
+     * @return object|null The related resource if exists else null
844
+     */
845
+    public function getRelatedResourceReference(ResourceSet $sourceResourceSet,
846
+        $sourceEntity, ResourceSet $targetResourceSet,
847
+        ResourceProperty $targetProperty
848
+    ) {
849
+        $entityInstance = $this->queryProvider->getRelatedResourceReference(
850
+            $sourceResourceSet,
851
+            $sourceEntity,
852
+            $targetResourceSet,
853
+            $targetProperty
854
+        );
855
+
856
+        // we will not throw error if the resource reference is null
857
+        // e.g. Orders(1234)/Customer => Customer can be null, this is
858
+        // allowed if Customer is last segment. consider the following:
859
+        // Orders(1234)/Customer/Orders => here if Customer is null then
860
+        // the UriProcessor will throw error.
861
+        if (!is_null($entityInstance)) {
862
+            $entityName
863
+                = $targetResourceSet
864
+                    ->getResourceType()
865
+                    ->getInstanceType()
866
+                    ->getName();
867
+            if (!is_object($entityInstance)
868
+                || !($entityInstance instanceof $entityName)
869
+            ) {
870
+                throw ODataException::createInternalServerError(
871
+                    Messages::providersWrapperIDSQPMethodReturnsUnExpectedType(
872
+                        $entityName,
873
+                        'IQueryProvider::getRelatedResourceReference'
874
+                    )
875
+                );
876
+            }
877
+
878
+            foreach ($targetProperty->getResourceType()->getKeyProperties()
879
+            as $keyName => $resourceProperty) {
880
+                try {
881
+                    $keyProperty = new \ReflectionProperty(
882
+                        $entityInstance,
883
+                        $keyName
884
+                    );
885
+                    $keyProperty->setAccessible(true);
886
+                    $keyValue = $keyProperty->getValue($entityInstance);
887
+                    if (is_null($keyValue)) {
888
+                        throw ODataException::createInternalServerError(
889
+                            Messages::providersWrapperIDSQPMethodReturnsInstanceWithNullKeyProperties('IDSQP::getRelatedResourceReference')
890
+                        );
891
+                    }
892
+                } catch (\ReflectionException $reflectionException) {
893
+                    //throw ODataException::createInternalServerError(
894
+                    //    Messages::orderByParserFailedToAccessOrInitializeProperty(
895
+                    //        $resourceProperty->getName(), $resourceType->getName()
896
+                    //    )
897
+                    //);
898
+                }
899
+            }
900
+        }
901
+
902
+        return $entityInstance;
903
+    }
904
+
905
+    /**
906
+     * Validate the given entity instance.
907
+     *
908
+     * @param object        $entityInstance Entity instance to validate
909
+     * @param ResourceSet   &$resourceSet   Resource set to which the entity
910
+     *                                      instance belongs to.
911
+     * @param KeyDescriptor &$keyDescriptor The key descriptor.
912
+     * @param string        $methodName     Method from which this function
913
+     *                                      invoked.
914
+     *
915
+     * @return void
916
+     *
917
+     * @throws ODataException
918
+     */
919
+    private function _validateEntityInstance($entityInstance,
920
+        ResourceSet &$resourceSet,
921
+        KeyDescriptor &$keyDescriptor,
922
+        $methodName
923
+    ) {
924
+        if (is_null($entityInstance)) {
925
+            throw ODataException::createResourceNotFoundError($resourceSet->getName());
926
+        }
927
+
928
+        $entityName = $resourceSet->getResourceType()->getInstanceType()->getName();
929
+        if (!is_object($entityInstance)
930
+            || !($entityInstance instanceof $entityName)
931
+        ) {
932
+            throw ODataException::createInternalServerError(
933
+                Messages::providersWrapperIDSQPMethodReturnsUnExpectedType(
934
+                    $entityName,
935
+                    $methodName
936
+                )
937
+            );
938
+        }
939
+
940
+        foreach ($keyDescriptor->getValidatedNamedValues()
941
+            as $keyName => $valueDescription) {
942
+            try {
943
+                $keyProperty = new \ReflectionProperty($entityInstance, $keyName);
944
+                $keyProperty->setAccessible(true);
945
+                $keyValue = $keyProperty->getValue($entityInstance);
946
+                if (is_null($keyValue)) {
947
+                    throw ODataException::createInternalServerError(
948
+                        Messages::providersWrapperIDSQPMethodReturnsInstanceWithNullKeyProperties($methodName)
949
+                    );
950
+                }
951
+
952
+                $convertedValue
953
+                    = $valueDescription[1]->convert($valueDescription[0]);
954
+                if ($keyValue != $convertedValue) {
955
+                    throw ODataException::createInternalServerError(
956
+                        Messages::providersWrapperIDSQPMethodReturnsInstanceWithNonMatchingKeys($methodName)
957
+                    );
958
+                }
959
+            } catch (\ReflectionException $reflectionException) {
960
+                //throw ODataException::createInternalServerError(
961
+                //  Messages::orderByParserFailedToAccessOrInitializeProperty(
962
+                //      $resourceProperty->getName(), $resourceType->getName()
963
+                //  )
964
+                //);
965
+            }
966
+        }
967
+    }
968
+
969
+    /**
970
+     * Assert that the given condition is true.
971
+     *
972
+     * @param boolean $condition         Condition to be asserted.
973
+     * @param string  $conditionAsString String containing message incase
974
+     *                                   if assertion fails.
975
+     *
976
+     * @throws InvalidOperationException Incase if assertion fails.
977
+     *
978
+     * @return void
979
+     */
980
+    protected function assert($condition, $conditionAsString)
981
+    {
982
+        if (!$condition) {
983
+            throw new InvalidOperationException("Unexpected state, expecting $conditionAsString");
984
+        }
985
+    }
986 986
 }
987 987
\ No newline at end of file
Please login to merge, or discard this patch.
src/POData/UriProcessor/UriProcessor.php 2 patches
Spacing   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -114,7 +114,7 @@  discard block
 block discarded – undo
114 114
 	    $uriProcessor->request->setUriProcessor($uriProcessor);
115 115
 
116 116
         //Parse the query string options of the request Uri.
117
-        QueryProcessor::process( $uriProcessor->request, $service );
117
+        QueryProcessor::process($uriProcessor->request, $service);
118 118
 
119 119
         return $uriProcessor;
120 120
     }
@@ -171,7 +171,7 @@  discard block
 block discarded – undo
171 171
      */
172 172
     protected function executePut()
173 173
     {
174
-        return $this->executeBase(function ($uriProcessor, $segment) {
174
+        return $this->executeBase(function($uriProcessor, $segment) {
175 175
             $requestMethod = $uriProcessor->service->getOperationContext()->incomingRequest()->getMethod();
176 176
             $resourceSet = $segment->getTargetResourceSetWrapper();
177 177
             $keyDescriptor = $segment->getKeyDescriptor();
@@ -195,7 +195,7 @@  discard block
 block discarded – undo
195 195
      */
196 196
     protected function executePost()
197 197
     {
198
-        return $this->executeBase(function ($uriProcessor, $segment) {
198
+        return $this->executeBase(function($uriProcessor, $segment) {
199 199
             $requestMethod = $uriProcessor->service->getOperationContext()->incomingRequest()->getMethod();
200 200
             $resourceSet = $segment->getTargetResourceSetWrapper();
201 201
             $data = $uriProcessor->request->getData();
@@ -223,7 +223,7 @@  discard block
 block discarded – undo
223 223
      */
224 224
     protected function executeDelete()
225 225
     {
226
-        return $this->executeBase(function ($uriProcessor, $segment) {
226
+        return $this->executeBase(function($uriProcessor, $segment) {
227 227
             $requestMethod = $uriProcessor->service->getOperationContext()->incomingRequest()->getMethod();
228 228
             $resourceSet = $segment->getTargetResourceSetWrapper();
229 229
             $keyDescriptor = $segment->getKeyDescriptor();
@@ -331,7 +331,7 @@  discard block
 block discarded – undo
331 331
      * @return void
332 332
      *
333 333
      */
334
-    private function handleSegmentTargetsToResourceSet( SegmentDescriptor $segment ) {
334
+    private function handleSegmentTargetsToResourceSet(SegmentDescriptor $segment) {
335 335
         if ($segment->isSingleResult()) {
336 336
             $entityInstance = $this->providers->getResourceFromResourceSet(
337 337
                 $segment->getTargetResourceSetWrapper(),
@@ -432,7 +432,7 @@  discard block
 block discarded – undo
432 432
 	    //and just work with the QueryResult in the object model serializer
433 433
 	    $result = $segment->getResult();
434 434
 
435
-	    if(!$result instanceof QueryResult){
435
+	    if (!$result instanceof QueryResult) {
436 436
 		    //If the segment isn't a query result, then there's no paging or counting to be done
437 437
 		    return;
438 438
         }
@@ -449,7 +449,7 @@  discard block
 block discarded – undo
449 449
         }
450 450
 
451 451
 	    //Have POData perform paging if necessary
452
-	    if(!$this->providers->handlesOrderedPaging() && !empty($result->results)){
452
+	    if (!$this->providers->handlesOrderedPaging() && !empty($result->results)) {
453 453
 			$result->results = $this->performPaging($result->results);
454 454
 	    }
455 455
 
@@ -492,7 +492,7 @@  discard block
 block discarded – undo
492 492
 		if (!empty($result)) {
493 493
 			$top  = $this->request->getTopCount();
494 494
 			$skip = $this->request->getSkipCount();
495
-			if(is_null($skip)) $skip = 0;
495
+			if (is_null($skip)) $skip = 0;
496 496
 
497 497
 			$result = array_slice($result, $skip, $top);
498 498
 		}
@@ -699,7 +699,7 @@  discard block
 block discarded – undo
699 699
      * @throws InvalidOperationException If this function invoked with non-navigation
700 700
      *                                   property instance.
701 701
      */
702
-    private function _pushSegmentForNavigationProperty(ResourceProperty &$resourceProperty)
702
+    private function _pushSegmentForNavigationProperty(ResourceProperty & $resourceProperty)
703 703
     {
704 704
         if ($resourceProperty->getTypeKind() == ResourceTypeKind::ENTITY) {
705 705
             $this->assert(
@@ -794,7 +794,7 @@  discard block
 block discarded – undo
794 794
      *
795 795
      * @return bool true if the segment was push, false otherwise
796 796
      */
797
-    private function _pushSegment($segmentName, ResourceSetWrapper &$resourceSetWrapper)
797
+    private function _pushSegment($segmentName, ResourceSetWrapper & $resourceSetWrapper)
798 798
     {
799 799
         $rootProjectionNode = $this->request->getRootProjectionNode();
800 800
         if (!is_null($rootProjectionNode)
Please login to merge, or discard this patch.
Braces   +7 added lines, -9 removed lines patch added patch discarded remove patch
@@ -143,17 +143,13 @@  discard block
 block discarded – undo
143 143
         $requestMethod = $operationContext->incomingRequest()->getMethod();
144 144
         if ($requestMethod == HTTPRequestMethod::GET) {
145 145
             $this->executeGet();
146
-        }
147
-        elseif ($requestMethod == HTTPRequestMethod::PUT) {
146
+        } elseif ($requestMethod == HTTPRequestMethod::PUT) {
148 147
             $this->executePut();
149
-        }
150
-        elseif ($requestMethod == HTTPRequestMethod::POST) {
148
+        } elseif ($requestMethod == HTTPRequestMethod::POST) {
151 149
             $this->executePost();
152
-        }
153
-        elseif ($requestMethod == HTTPRequestMethod::DELETE) {
150
+        } elseif ($requestMethod == HTTPRequestMethod::DELETE) {
154 151
             $this->executeDelete();
155
-        }
156
-        else {
152
+        } else {
157 153
             throw ODataException::createNotImplementedError(Messages::unsupportedMethod($requestMethod));
158 154
         }
159 155
     }
@@ -492,7 +488,9 @@  discard block
 block discarded – undo
492 488
 		if (!empty($result)) {
493 489
 			$top  = $this->request->getTopCount();
494 490
 			$skip = $this->request->getSkipCount();
495
-			if(is_null($skip)) $skip = 0;
491
+			if(is_null($skip)) {
492
+			    $skip = 0;
493
+			}
496 494
 
497 495
 			$result = array_slice($result, $skip, $top);
498 496
 		}
Please login to merge, or discard this patch.
src/POData/Writers/Json/JsonLightODataWriter.php 2 patches
Indentation   +296 added lines, -296 removed lines patch added patch discarded remove patch
@@ -29,256 +29,256 @@  discard block
 block discarded – undo
29 29
 class JsonLightODataWriter extends JsonODataV2Writer
30 30
 {
31 31
 
32
-	/**
33
-	 * @var JsonLightMetadataLevel
34
-	 */
35
-	protected $metadataLevel;
36
-
37
-
38
-	/**
39
-	 *
40
-	 * The service base uri
41
-	 * @var string
42
-	 */
43
-	protected $baseUri;
44
-
45
-
46
-	public function __construct(JsonLightMetadataLevel $metadataLevel, $absoluteServiceUri)
47
-	{
48
-		if(strlen($absoluteServiceUri) == 0)
49
-		{
50
-			throw new \Exception("absoluteServiceUri must not be empty or null");
51
-		}
52
-		$this->baseUri = $absoluteServiceUri;
53
-
54
-		$this->_writer = new JsonWriter('');
55
-		$this->urlKey = ODataConstants::JSON_URL_STRING;
56
-		$this->dataArrayName = ODataConstants::JSON_LIGHT_VALUE_NAME;
57
-		$this->rowCountName = ODataConstants::JSON_LIGHT_ROWCOUNT_STRING;
58
-		$this->metadataLevel = $metadataLevel;
59
-	}
60
-
61
-
62
-	/**
63
-	 * Determines if the given writer is capable of writing the response or not
64
-	 * @param Version $responseVersion the OData version of the response
65
-	 * @param string $contentType the Content Type of the response
66
-	 * @return boolean true if the writer can handle the response, false otherwise
67
-	 */
68
-	public function canHandle(Version $responseVersion, $contentType)
69
-	{
70
-		if($responseVersion != Version::v3()){
71
-			return false;
72
-		}
73
-
74
-		$parts = explode(";", $contentType);
75
-
76
-		//It must be app/json and have the right odata= piece
77
-		$metadata = array_filter($parts, function ($item) { strpos($item, 'odata') !== false; });
78
-		return in_array(MimeTypes::MIME_APPLICATION_JSON, $parts) && (empty($metadata) || in_array($this->metadataLevel->getValue(), $metadata));
79
-	}
80
-
81
-
82
-
83
-	/**
84
-	 * Write the given OData model in a specific response format
85
-	 *
86
-	 * @param  ODataURL|ODataURLCollection|ODataPropertyContent|ODataFeed|ODataEntry $model Object of requested content.
87
-	 *
88
-	 * @return JsonLightODataWriter
89
-	 */
90
-	public function write($model){
91
-		$this->_writer->startObjectScope();
92
-
93
-		if ($model instanceof ODataURL) {
94
-			$this->writeTopLevelMeta("url");
95
-			$this->writeURL($model);
96
-		} elseif ($model instanceof ODataURLCollection) {
97
-			$this->writeTopLevelMeta("urlCollection");
98
-			$this->writeURLCollection($model);
99
-		} elseif ($model instanceof ODataPropertyContent) {
100
-			$this->writeTopLevelMeta( $model->properties[0]->typeName );
101
-			$this->writeTopLevelProperty($model->properties[0]);
102
-		} elseif ($model instanceof ODataFeed) {
103
-			$this->writeTopLevelMeta($model->title);
104
-			$this->writeRowCount($model->rowCount);
105
-			$this->writeNextPageLink($model->nextPageLink);
106
-			$this->_writer
107
-				->writeName($this->dataArrayName)
108
-				->startArrayScope();
109
-			$this->writeFeed($model);
110
-			$this->_writer->endScope();
111
-		}elseif ($model instanceof ODataEntry) {
112
-			$this->writeTopLevelMeta($model->resourceSetName . "/@Element");
113
-			$this->writeEntry($model);
114
-		}
115
-
116
-		$this->_writer->endScope();
117
-
118
-		return $this;
119
-	}
120
-
121
-
122
-	/**
123
-	 *
124
-	 * @param ODataProperty $property
125
-	 *
126
-	 * @return JsonLightODataWriter
127
-	 */
128
-	protected function writeTopLevelProperty(ODataProperty $property)
129
-	{
130
-		$this->writePropertyMeta($property);
131
-		if ($property->value == null) {
132
-			$this->_writer->writeName(ODataConstants::JSON_LIGHT_VALUE_NAME);
133
-			$this->_writer->writeValue("null");
134
-		} elseif ($property->value instanceof ODataPropertyContent) {
135
-			//In the case of complex properties at the top level we don't write the name of the property,
136
-			//just the sub properties.
137
-			$this->writeComplexPropertyMeta($property)
138
-				->writeProperties($property->value);
139
-		} elseif ($property->value instanceof ODataBagContent) {
140
-			$this->_writer->writeName(ODataConstants::JSON_LIGHT_VALUE_NAME);
141
-			$this->writeBagContent($property->value);
142
-		} else {
143
-			$this->_writer->writeName(ODataConstants::JSON_LIGHT_VALUE_NAME);
144
-			$this->_writer->writeValue($property->value, $property->typeName);
145
-		}
146
-
147
-		return $this;
148
-	}
149
-
150
-
151
-
152
-	protected function writeTopLevelMeta($fragment)
153
-	{
154
-		if($this->metadataLevel == JsonLightMetadataLevel::NONE())
155
-		{
156
-			return;
157
-		}
158
-
159
-		$this->_writer
160
-			->writeName(ODataConstants::JSON_LIGHT_METADATA_STRING)
161
-			->writeValue($this->baseUri . '/' . ODataConstants::URI_METADATA_SEGMENT . '#' . $fragment);
162
-
163
-	}
164
-
165
-
166
-	protected function writePropertyMeta(ODataProperty $property)
167
-	{
168
-		if($this->metadataLevel != JsonLightMetadataLevel::FULL())
169
-		{
170
-			//Only full meta level outputs this info
171
-			return $this;
172
-		}
173
-
174
-		if(is_null($property->value))
175
-		{
176
-			//it appears full metadata doesn't output types for nulls...
177
-			return $this;
178
-		}
179
-
180
-
181
-		switch($property->typeName)
182
-		{
183
-			//The type metadata is only included on certain types of properties
184
-			//Note this also excludes Complex types
185
-
186
-			case "Edm.Decimal":
187
-			case "Edm.DateTime":
188
-				$this->_writer
189
-					->writeName($property->name . ODataConstants::JSON_LIGHT_METADATA_PROPERTY_TYPE_SUFFIX_STRING)
190
-					->writeValue($property->typeName);
191
-		}
192
-
193
-
194
-		return $this;
195
-	}
196
-
197
-	/**
198
-	 *
199
-	 * @param ODataEntry $entry Entry to write metadata for.
200
-	 *
201
-	 * @return JsonLightODataWriter
202
-	 */
203
-	protected function writeEntryMetadata(ODataEntry $entry){
204
-
205
-		if($this->metadataLevel != JsonLightMetadataLevel::FULL())
206
-		{
207
-			//Only full meta level outputs this info
208
-			return $this;
209
-		}
210
-
211
-		$this->_writer
212
-			->writeName(ODataConstants::JSON_LIGHT_METADATA_TYPE_STRING)
213
-			->writeValue($entry->type)
214
-			->writeName(ODataConstants::JSON_LIGHT_METADATA_ID_STRING)
215
-			->writeValue($entry->id)
216
-			->writeName(ODataConstants::JSON_LIGHT_METADATA_ETAG_STRING)
217
-			->writeValue($entry->eTag)
218
-			->writeName(ODataConstants::JSON_LIGHT_METADATA_EDIT_LINK_STRING)
219
-			->writeValue($entry->editLink)
220
-		;
221
-
222
-		return $this;
223
-	}
224
-
225
-
226
-	/**
227
-	 * @param ODataLink $link Link to write.
228
-	 *
229
-	 * @return JsonLightODataWriter
230
-	 */
231
-	protected function writeLink(ODataLink $link){
232
-
233
-		if($this->metadataLevel == JsonLightMetadataLevel::FULL())
234
-		{
235
-			//Interestingly the fullmetadata outputs this metadata..even if the thing is expanded
236
-			$this->_writer
237
-				->writeName($link->title . ODataConstants::JSON_LIGHT_METADATA_LINK_NAVIGATION_SUFFIX_STRING)
238
-				->writeValue($link->url);;
239
-		}
240
-
241
-
242
-		if($link->isExpanded)
243
-		{
244
-			$this->_writer->writeName($link->title);
245
-
246
-			if(is_null($link->expandedResult)) {
247
-				$this->_writer->writeValue("null");
248
-			} else {
249
-				$this->writeExpandedLink($link);
250
-			}
251
-		}
252
-
253
-		return $this;
254
-	}
255
-
256
-	protected function writeExpandedLink(ODataLink $link)
257
-	{
258
-
259
-
260
-		if ($link->isCollection) {
261
-			$this->_writer->startArrayScope();
262
-			$this->writeFeed($link->expandedResult);
263
-		} else {
264
-			$this->_writer->startObjectScope();
265
-			$this->writeEntry($link->expandedResult);
266
-		}
267
-
268
-
269
-		$this->_writer->endScope();
270
-	}
271
-
272
-	/**
273
-	 * Writes the next page link.
274
-	 *
275
-	 * @param ODataLink $nextPageLinkUri Uri for next page link.
276
-	 *
277
-	 * @return JsonLightODataWriter
278
-	 */
279
-	protected function writeNextPageLink(ODataLink $nextPageLinkUri = null)
280
-	{
281
-		/*
32
+    /**
33
+     * @var JsonLightMetadataLevel
34
+     */
35
+    protected $metadataLevel;
36
+
37
+
38
+    /**
39
+     *
40
+     * The service base uri
41
+     * @var string
42
+     */
43
+    protected $baseUri;
44
+
45
+
46
+    public function __construct(JsonLightMetadataLevel $metadataLevel, $absoluteServiceUri)
47
+    {
48
+        if(strlen($absoluteServiceUri) == 0)
49
+        {
50
+            throw new \Exception("absoluteServiceUri must not be empty or null");
51
+        }
52
+        $this->baseUri = $absoluteServiceUri;
53
+
54
+        $this->_writer = new JsonWriter('');
55
+        $this->urlKey = ODataConstants::JSON_URL_STRING;
56
+        $this->dataArrayName = ODataConstants::JSON_LIGHT_VALUE_NAME;
57
+        $this->rowCountName = ODataConstants::JSON_LIGHT_ROWCOUNT_STRING;
58
+        $this->metadataLevel = $metadataLevel;
59
+    }
60
+
61
+
62
+    /**
63
+     * Determines if the given writer is capable of writing the response or not
64
+     * @param Version $responseVersion the OData version of the response
65
+     * @param string $contentType the Content Type of the response
66
+     * @return boolean true if the writer can handle the response, false otherwise
67
+     */
68
+    public function canHandle(Version $responseVersion, $contentType)
69
+    {
70
+        if($responseVersion != Version::v3()){
71
+            return false;
72
+        }
73
+
74
+        $parts = explode(";", $contentType);
75
+
76
+        //It must be app/json and have the right odata= piece
77
+        $metadata = array_filter($parts, function ($item) { strpos($item, 'odata') !== false; });
78
+        return in_array(MimeTypes::MIME_APPLICATION_JSON, $parts) && (empty($metadata) || in_array($this->metadataLevel->getValue(), $metadata));
79
+    }
80
+
81
+
82
+
83
+    /**
84
+     * Write the given OData model in a specific response format
85
+     *
86
+     * @param  ODataURL|ODataURLCollection|ODataPropertyContent|ODataFeed|ODataEntry $model Object of requested content.
87
+     *
88
+     * @return JsonLightODataWriter
89
+     */
90
+    public function write($model){
91
+        $this->_writer->startObjectScope();
92
+
93
+        if ($model instanceof ODataURL) {
94
+            $this->writeTopLevelMeta("url");
95
+            $this->writeURL($model);
96
+        } elseif ($model instanceof ODataURLCollection) {
97
+            $this->writeTopLevelMeta("urlCollection");
98
+            $this->writeURLCollection($model);
99
+        } elseif ($model instanceof ODataPropertyContent) {
100
+            $this->writeTopLevelMeta( $model->properties[0]->typeName );
101
+            $this->writeTopLevelProperty($model->properties[0]);
102
+        } elseif ($model instanceof ODataFeed) {
103
+            $this->writeTopLevelMeta($model->title);
104
+            $this->writeRowCount($model->rowCount);
105
+            $this->writeNextPageLink($model->nextPageLink);
106
+            $this->_writer
107
+                ->writeName($this->dataArrayName)
108
+                ->startArrayScope();
109
+            $this->writeFeed($model);
110
+            $this->_writer->endScope();
111
+        }elseif ($model instanceof ODataEntry) {
112
+            $this->writeTopLevelMeta($model->resourceSetName . "/@Element");
113
+            $this->writeEntry($model);
114
+        }
115
+
116
+        $this->_writer->endScope();
117
+
118
+        return $this;
119
+    }
120
+
121
+
122
+    /**
123
+     *
124
+     * @param ODataProperty $property
125
+     *
126
+     * @return JsonLightODataWriter
127
+     */
128
+    protected function writeTopLevelProperty(ODataProperty $property)
129
+    {
130
+        $this->writePropertyMeta($property);
131
+        if ($property->value == null) {
132
+            $this->_writer->writeName(ODataConstants::JSON_LIGHT_VALUE_NAME);
133
+            $this->_writer->writeValue("null");
134
+        } elseif ($property->value instanceof ODataPropertyContent) {
135
+            //In the case of complex properties at the top level we don't write the name of the property,
136
+            //just the sub properties.
137
+            $this->writeComplexPropertyMeta($property)
138
+                ->writeProperties($property->value);
139
+        } elseif ($property->value instanceof ODataBagContent) {
140
+            $this->_writer->writeName(ODataConstants::JSON_LIGHT_VALUE_NAME);
141
+            $this->writeBagContent($property->value);
142
+        } else {
143
+            $this->_writer->writeName(ODataConstants::JSON_LIGHT_VALUE_NAME);
144
+            $this->_writer->writeValue($property->value, $property->typeName);
145
+        }
146
+
147
+        return $this;
148
+    }
149
+
150
+
151
+
152
+    protected function writeTopLevelMeta($fragment)
153
+    {
154
+        if($this->metadataLevel == JsonLightMetadataLevel::NONE())
155
+        {
156
+            return;
157
+        }
158
+
159
+        $this->_writer
160
+            ->writeName(ODataConstants::JSON_LIGHT_METADATA_STRING)
161
+            ->writeValue($this->baseUri . '/' . ODataConstants::URI_METADATA_SEGMENT . '#' . $fragment);
162
+
163
+    }
164
+
165
+
166
+    protected function writePropertyMeta(ODataProperty $property)
167
+    {
168
+        if($this->metadataLevel != JsonLightMetadataLevel::FULL())
169
+        {
170
+            //Only full meta level outputs this info
171
+            return $this;
172
+        }
173
+
174
+        if(is_null($property->value))
175
+        {
176
+            //it appears full metadata doesn't output types for nulls...
177
+            return $this;
178
+        }
179
+
180
+
181
+        switch($property->typeName)
182
+        {
183
+            //The type metadata is only included on certain types of properties
184
+            //Note this also excludes Complex types
185
+
186
+            case "Edm.Decimal":
187
+            case "Edm.DateTime":
188
+                $this->_writer
189
+                    ->writeName($property->name . ODataConstants::JSON_LIGHT_METADATA_PROPERTY_TYPE_SUFFIX_STRING)
190
+                    ->writeValue($property->typeName);
191
+        }
192
+
193
+
194
+        return $this;
195
+    }
196
+
197
+    /**
198
+     *
199
+     * @param ODataEntry $entry Entry to write metadata for.
200
+     *
201
+     * @return JsonLightODataWriter
202
+     */
203
+    protected function writeEntryMetadata(ODataEntry $entry){
204
+
205
+        if($this->metadataLevel != JsonLightMetadataLevel::FULL())
206
+        {
207
+            //Only full meta level outputs this info
208
+            return $this;
209
+        }
210
+
211
+        $this->_writer
212
+            ->writeName(ODataConstants::JSON_LIGHT_METADATA_TYPE_STRING)
213
+            ->writeValue($entry->type)
214
+            ->writeName(ODataConstants::JSON_LIGHT_METADATA_ID_STRING)
215
+            ->writeValue($entry->id)
216
+            ->writeName(ODataConstants::JSON_LIGHT_METADATA_ETAG_STRING)
217
+            ->writeValue($entry->eTag)
218
+            ->writeName(ODataConstants::JSON_LIGHT_METADATA_EDIT_LINK_STRING)
219
+            ->writeValue($entry->editLink)
220
+        ;
221
+
222
+        return $this;
223
+    }
224
+
225
+
226
+    /**
227
+     * @param ODataLink $link Link to write.
228
+     *
229
+     * @return JsonLightODataWriter
230
+     */
231
+    protected function writeLink(ODataLink $link){
232
+
233
+        if($this->metadataLevel == JsonLightMetadataLevel::FULL())
234
+        {
235
+            //Interestingly the fullmetadata outputs this metadata..even if the thing is expanded
236
+            $this->_writer
237
+                ->writeName($link->title . ODataConstants::JSON_LIGHT_METADATA_LINK_NAVIGATION_SUFFIX_STRING)
238
+                ->writeValue($link->url);;
239
+        }
240
+
241
+
242
+        if($link->isExpanded)
243
+        {
244
+            $this->_writer->writeName($link->title);
245
+
246
+            if(is_null($link->expandedResult)) {
247
+                $this->_writer->writeValue("null");
248
+            } else {
249
+                $this->writeExpandedLink($link);
250
+            }
251
+        }
252
+
253
+        return $this;
254
+    }
255
+
256
+    protected function writeExpandedLink(ODataLink $link)
257
+    {
258
+
259
+
260
+        if ($link->isCollection) {
261
+            $this->_writer->startArrayScope();
262
+            $this->writeFeed($link->expandedResult);
263
+        } else {
264
+            $this->_writer->startObjectScope();
265
+            $this->writeEntry($link->expandedResult);
266
+        }
267
+
268
+
269
+        $this->_writer->endScope();
270
+    }
271
+
272
+    /**
273
+     * Writes the next page link.
274
+     *
275
+     * @param ODataLink $nextPageLinkUri Uri for next page link.
276
+     *
277
+     * @return JsonLightODataWriter
278
+     */
279
+    protected function writeNextPageLink(ODataLink $nextPageLinkUri = null)
280
+    {
281
+        /*
282 282
 		// "__next" : uri
283 283
 		if ($nextPageLinkUri != null) {
284 284
 			$this->_writer
@@ -288,48 +288,48 @@  discard block
 block discarded – undo
288 288
 
289 289
 		return $this;
290 290
 		*/
291
-	}
291
+    }
292 292
 
293 293
 
294
-	/**
295
-	 * Begin write complex property.
296
-	 *
297
-	 * @param ODataProperty $property property to write.
298
-	 *
299
-	 * @return JsonLightODataWriter
300
-	 */
301
-	protected function writeComplexProperty(ODataProperty $property)
302
-	{
294
+    /**
295
+     * Begin write complex property.
296
+     *
297
+     * @param ODataProperty $property property to write.
298
+     *
299
+     * @return JsonLightODataWriter
300
+     */
301
+    protected function writeComplexProperty(ODataProperty $property)
302
+    {
303 303
 
304
-		// {
305
-		$this->_writer->startObjectScope();
304
+        // {
305
+        $this->_writer->startObjectScope();
306 306
 
307
-		$this->writeComplexPropertyMeta($property)
308
-			->writeProperties($property->value);
307
+        $this->writeComplexPropertyMeta($property)
308
+            ->writeProperties($property->value);
309 309
 
310
-		$this->_writer->endScope();
310
+        $this->_writer->endScope();
311 311
 
312
-		return $this;
313
-	}
312
+        return $this;
313
+    }
314 314
 
315
-	protected function writeComplexPropertyMeta(ODataProperty $property)
316
-	{
317
-		if($this->metadataLevel == JsonLightMetadataLevel::FULL()){
318
-			$this->_writer
319
-				->writeName(ODataConstants::JSON_LIGHT_METADATA_TYPE_STRING)
320
-				->writeValue($property->typeName);
321
-		}
315
+    protected function writeComplexPropertyMeta(ODataProperty $property)
316
+    {
317
+        if($this->metadataLevel == JsonLightMetadataLevel::FULL()){
318
+            $this->_writer
319
+                ->writeName(ODataConstants::JSON_LIGHT_METADATA_TYPE_STRING)
320
+                ->writeValue($property->typeName);
321
+        }
322 322
 
323
-		return $this;
324
-	}
323
+        return $this;
324
+    }
325 325
 
326
-	protected function writeBagContent(ODataBagContent $bag)
327
-	{
326
+    protected function writeBagContent(ODataBagContent $bag)
327
+    {
328 328
 
329
-		$this->_writer
329
+        $this->_writer
330 330
 
331 331
 
332
-			/*
332
+            /*
333 333
 			->writeName(ODataConstants::JSON_METADATA_STRING) //__metadata : { Type : "typename" }
334 334
 			->startObjectScope()
335 335
 
@@ -339,24 +339,24 @@  discard block
 block discarded – undo
339 339
 			*/
340 340
 
341 341
 
342
-			->startArrayScope(); // [
342
+            ->startArrayScope(); // [
343 343
 
344
-		foreach ($bag->propertyContents as $content) {
345
-			if ($content instanceof ODataPropertyContent) {
346
-				$this->_writer->startObjectScope();
347
-				$this->writeProperties($content);
348
-				$this->_writer->endScope();
349
-			} else {
350
-				// retrieving the collection datatype in order
351
-				//to write in json specific format, with in chords or not
352
-				preg_match('#\((.*?)\)#', $bag->type, $type);
353
-				$this->_writer->writeValue($content, $type[1]);
354
-			}
355
-		}
344
+        foreach ($bag->propertyContents as $content) {
345
+            if ($content instanceof ODataPropertyContent) {
346
+                $this->_writer->startObjectScope();
347
+                $this->writeProperties($content);
348
+                $this->_writer->endScope();
349
+            } else {
350
+                // retrieving the collection datatype in order
351
+                //to write in json specific format, with in chords or not
352
+                preg_match('#\((.*?)\)#', $bag->type, $type);
353
+                $this->_writer->writeValue($content, $type[1]);
354
+            }
355
+        }
356 356
 
357 357
 
358
-		$this->_writer->endScope();  // ]
359
-		return $this;
360
-	}
358
+        $this->_writer->endScope();  // ]
359
+        return $this;
360
+    }
361 361
 
362 362
 }
Please login to merge, or discard this patch.
Spacing   +18 added lines, -18 removed lines patch added patch discarded remove patch
@@ -45,7 +45,7 @@  discard block
 block discarded – undo
45 45
 
46 46
 	public function __construct(JsonLightMetadataLevel $metadataLevel, $absoluteServiceUri)
47 47
 	{
48
-		if(strlen($absoluteServiceUri) == 0)
48
+		if (strlen($absoluteServiceUri) == 0)
49 49
 		{
50 50
 			throw new \Exception("absoluteServiceUri must not be empty or null");
51 51
 		}
@@ -67,14 +67,14 @@  discard block
 block discarded – undo
67 67
 	 */
68 68
 	public function canHandle(Version $responseVersion, $contentType)
69 69
 	{
70
-		if($responseVersion != Version::v3()){
70
+		if ($responseVersion != Version::v3()) {
71 71
 			return false;
72 72
 		}
73 73
 
74 74
 		$parts = explode(";", $contentType);
75 75
 
76 76
 		//It must be app/json and have the right odata= piece
77
-		$metadata = array_filter($parts, function ($item) { strpos($item, 'odata') !== false; });
77
+		$metadata = array_filter($parts, function($item) { strpos($item, 'odata') !== false; });
78 78
 		return in_array(MimeTypes::MIME_APPLICATION_JSON, $parts) && (empty($metadata) || in_array($this->metadataLevel->getValue(), $metadata));
79 79
 	}
80 80
 
@@ -87,7 +87,7 @@  discard block
 block discarded – undo
87 87
 	 *
88 88
 	 * @return JsonLightODataWriter
89 89
 	 */
90
-	public function write($model){
90
+	public function write($model) {
91 91
 		$this->_writer->startObjectScope();
92 92
 
93 93
 		if ($model instanceof ODataURL) {
@@ -97,7 +97,7 @@  discard block
 block discarded – undo
97 97
 			$this->writeTopLevelMeta("urlCollection");
98 98
 			$this->writeURLCollection($model);
99 99
 		} elseif ($model instanceof ODataPropertyContent) {
100
-			$this->writeTopLevelMeta( $model->properties[0]->typeName );
100
+			$this->writeTopLevelMeta($model->properties[0]->typeName);
101 101
 			$this->writeTopLevelProperty($model->properties[0]);
102 102
 		} elseif ($model instanceof ODataFeed) {
103 103
 			$this->writeTopLevelMeta($model->title);
@@ -151,7 +151,7 @@  discard block
 block discarded – undo
151 151
 
152 152
 	protected function writeTopLevelMeta($fragment)
153 153
 	{
154
-		if($this->metadataLevel == JsonLightMetadataLevel::NONE())
154
+		if ($this->metadataLevel == JsonLightMetadataLevel::NONE())
155 155
 		{
156 156
 			return;
157 157
 		}
@@ -165,20 +165,20 @@  discard block
 block discarded – undo
165 165
 
166 166
 	protected function writePropertyMeta(ODataProperty $property)
167 167
 	{
168
-		if($this->metadataLevel != JsonLightMetadataLevel::FULL())
168
+		if ($this->metadataLevel != JsonLightMetadataLevel::FULL())
169 169
 		{
170 170
 			//Only full meta level outputs this info
171 171
 			return $this;
172 172
 		}
173 173
 
174
-		if(is_null($property->value))
174
+		if (is_null($property->value))
175 175
 		{
176 176
 			//it appears full metadata doesn't output types for nulls...
177 177
 			return $this;
178 178
 		}
179 179
 
180 180
 
181
-		switch($property->typeName)
181
+		switch ($property->typeName)
182 182
 		{
183 183
 			//The type metadata is only included on certain types of properties
184 184
 			//Note this also excludes Complex types
@@ -200,9 +200,9 @@  discard block
 block discarded – undo
200 200
 	 *
201 201
 	 * @return JsonLightODataWriter
202 202
 	 */
203
-	protected function writeEntryMetadata(ODataEntry $entry){
203
+	protected function writeEntryMetadata(ODataEntry $entry) {
204 204
 
205
-		if($this->metadataLevel != JsonLightMetadataLevel::FULL())
205
+		if ($this->metadataLevel != JsonLightMetadataLevel::FULL())
206 206
 		{
207 207
 			//Only full meta level outputs this info
208 208
 			return $this;
@@ -228,22 +228,22 @@  discard block
 block discarded – undo
228 228
 	 *
229 229
 	 * @return JsonLightODataWriter
230 230
 	 */
231
-	protected function writeLink(ODataLink $link){
231
+	protected function writeLink(ODataLink $link) {
232 232
 
233
-		if($this->metadataLevel == JsonLightMetadataLevel::FULL())
233
+		if ($this->metadataLevel == JsonLightMetadataLevel::FULL())
234 234
 		{
235 235
 			//Interestingly the fullmetadata outputs this metadata..even if the thing is expanded
236 236
 			$this->_writer
237 237
 				->writeName($link->title . ODataConstants::JSON_LIGHT_METADATA_LINK_NAVIGATION_SUFFIX_STRING)
238
-				->writeValue($link->url);;
238
+				->writeValue($link->url); ;
239 239
 		}
240 240
 
241 241
 
242
-		if($link->isExpanded)
242
+		if ($link->isExpanded)
243 243
 		{
244 244
 			$this->_writer->writeName($link->title);
245 245
 
246
-			if(is_null($link->expandedResult)) {
246
+			if (is_null($link->expandedResult)) {
247 247
 				$this->_writer->writeValue("null");
248 248
 			} else {
249 249
 				$this->writeExpandedLink($link);
@@ -314,7 +314,7 @@  discard block
 block discarded – undo
314 314
 
315 315
 	protected function writeComplexPropertyMeta(ODataProperty $property)
316 316
 	{
317
-		if($this->metadataLevel == JsonLightMetadataLevel::FULL()){
317
+		if ($this->metadataLevel == JsonLightMetadataLevel::FULL()) {
318 318
 			$this->_writer
319 319
 				->writeName(ODataConstants::JSON_LIGHT_METADATA_TYPE_STRING)
320 320
 				->writeValue($property->typeName);
@@ -355,7 +355,7 @@  discard block
 block discarded – undo
355 355
 		}
356 356
 
357 357
 
358
-		$this->_writer->endScope();  // ]
358
+		$this->_writer->endScope(); // ]
359 359
 		return $this;
360 360
 	}
361 361
 
Please login to merge, or discard this patch.