/** * Query for a related resource set or resource set reference pointed by the * given segment descriptor and update the descriptor with the result. * * @param SegmentDescriptor &$segmentDescriptor Describes the related resource * to query. * * @return void */ private function _handleSegmentTargetsToRelatedResource(SegmentDescriptor &$segmentDescriptor) { $projectedProperty = $segmentDescriptor->getProjectedProperty(); $projectedPropertyKind = $projectedProperty->getKind(); if ($projectedPropertyKind == ResourcePropertyKind::RESOURCESET_REFERENCE) { if ($segmentDescriptor->isSingleResult()) { $entityInstance = $this->_provider->getResourceFromRelatedResourceSet($segmentDescriptor->getPrevious()->getTargetResourceSetWrapper()->getResourceSet(), $segmentDescriptor->getPrevious()->getResult(), $segmentDescriptor->getTargetResourceSetWrapper()->getResourceSet(), $projectedProperty, $segmentDescriptor->getKeyDescriptor()); $segmentDescriptor->setResult($entityInstance); } else { $entityInstances = $this->_provider->getRelatedResourceSet($segmentDescriptor->getPrevious()->getTargetResourceSetWrapper()->getResourceSet(), $segmentDescriptor->getPrevious()->getResult(), $segmentDescriptor->getTargetResourceSetWrapper()->getResourceSet(), $segmentDescriptor->getProjectedProperty(), $this->_requestDescription->getInternalFilterInfo(), null, null, null, null); $segmentDescriptor->setResult($entityInstances); } } else { if ($projectedPropertyKind == ResourcePropertyKind::RESOURCE_REFERENCE) { $entityInstance = $this->_provider->getRelatedResourceReference($segmentDescriptor->getPrevious()->getTargetResourceSetWrapper()->getResourceSet(), $segmentDescriptor->getPrevious()->getResult(), $segmentDescriptor->getTargetResourceSetWrapper()->getResourceSet(), $segmentDescriptor->getProjectedProperty()); $segmentDescriptor->setResult($entityInstance); } else { //Unexpected state } } }
/** * Create SegmentDescriptors for a set of given segments, optionally * check for rights. * * @param array(string) $segments String array of segments to parse * @param boolean $checkRights Whether to check for rights or not * * @return void * * @throws ODataException Exception incase of any error found while * precessing segments */ private function _createSegmentDescriptors($segments, $checkRights) { if (empty($segments)) { $this->_segmentDescriptors[] = new SegmentDescriptor(); $this->_segmentDescriptors[0]->setTargetKind(RequestTargetKind::SERVICE_DIRECTORY); return; } $segmentCount = count($segments); $identifier = $keyPredicate = null; $this->_extractSegmentIdentifierAndKeyPredicate($segments[0], $identifier, $keyPredicate); $this->_segmentDescriptors[] = $this->_createFirstSegmentDescriptor($identifier, $keyPredicate, $checkRights); $previous = $this->_segmentDescriptors[0]; for ($i = 1; $i < $segmentCount; $i++) { if ($previous->getTargetKind() == RequestTargetKind::METADATA || $previous->getTargetKind() == RequestTargetKind::BATCH || $previous->getTargetKind() == RequestTargetKind::PRIMITIVE_VALUE || $previous->getTargetKind() == RequestTargetKind::BAG || $previous->getTargetKind() == RequestTargetKind::MEDIA_RESOURCE) { ODataException::resourceNotFoundError(Messages::segmentParserMustBeLeafSegment($previous->getIdentifier())); } $identifier = $keyPredicate = null; $this->_extractSegmentIdentifierAndKeyPredicate($segments[$i], $identifier, $keyPredicate); $hasPredicate = !is_null($keyPredicate); $descriptor = null; if ($previous->getTargetKind() == RequestTargetKind::PRIMITIVE) { if ($identifier !== ODataConstants::URI_VALUE_SEGMENT) { ODataException::resourceNotFoundError(Messages::segmentParserOnlyValueSegmentAllowedAfterPrimitivePropertySegment($identifier, $previous->getIdentifier())); } $this->_assertion(!$hasPredicate); $descriptor = SegmentDescriptor::createFrom($previous); $descriptor->setIdentifier(ODataConstants::URI_VALUE_SEGMENT); $descriptor->setTargetKind(RequestTargetKind::PRIMITIVE_VALUE); $descriptor->setSingleResult(true); } else { if (!is_null($previous->getPrevious()) && $previous->getPrevious()->getIdentifier() === ODataConstants::URI_LINK_SEGMENT && $identifier !== ODataConstants::URI_COUNT_SEGMENT) { ODataException::createBadRequestError(Messages::segmentParserNoSegmentAllowedAfterPostLinkSegment($identifier)); } else { if ($previous->getTargetKind() == RequestTargetKind::RESOURCE && $previous->isSingleResult() && $identifier === ODataConstants::URI_LINK_SEGMENT) { $this->_assertion(!$hasPredicate); $descriptor = SegmentDescriptor::createFrom($previous); $descriptor->setIdentifier(ODataConstants::URI_LINK_SEGMENT); $descriptor->setTargetKind(RequestTargetKind::LINK); } else { //Do a sanity check here if ($previous->getTargetKind() != RequestTargetKind::COMPLEX_OBJECT && $previous->getTargetKind() != RequestTargetKind::RESOURCE && $previous->getTargetKind() != RequestTargetKind::LINK) { ODataException::createInternalServerError(Messages::segmentParserInconsistentTargetKindState()); } if (!$previous->isSingleResult() && $identifier !== ODataConstants::URI_COUNT_SEGMENT) { ODataException::createBadRequestError(Messages::segmentParserCannotQueryCollection($previous->getIdentifier())); } $descriptor = new SegmentDescriptor(); $descriptor->setIdentifier($identifier); $descriptor->setTargetSource(RequestTargetSource::PROPERTY); $projectedProperty = $previous->getTargetResourceType()->tryResolvePropertyTypeByName($identifier); $descriptor->setProjectedProperty($projectedProperty); if ($identifier === ODataConstants::URI_COUNT_SEGMENT) { if ($previous->getTargetKind() != RequestTargetKind::RESOURCE) { ODataException::createBadRequestError(Messages::segmentParserCountCannotBeApplied($previous->getIdentifier())); } if ($previous->isSingleResult()) { ODataException::createBadRequestError(Messages::segmentParserCountCannotFollowSingleton($previous->getIdentifier())); } $descriptor->setTargetKind(RequestTargetKind::PRIMITIVE_VALUE); $descriptor->setSingleResult(true); $descriptor->setTargetResourceSetWrapper($previous->getTargetResourceSetWrapper()); $descriptor->setTargetResourceType($previous->getTargetResourceType()); } else { if ($identifier === ODataConstants::URI_VALUE_SEGMENT && $previous->getTargetKind() == RequestTargetKind::RESOURCE) { $descriptor->setSingleResult(true); $descriptor->setTargetResourceType($previous->getTargetResourceType()); $descriptor->setTargetKind(RequestTargetKind::MEDIA_RESOURCE); } else { if (is_null($projectedProperty)) { if (!is_null($previous->getTargetResourceType()) && !is_null($previous->getTargetResourceType()->tryResolveNamedStreamByName($identifier))) { $descriptor->setTargetKind(RequestTargetKind::MEDIA_RESOURCE); $descriptor->setSingleResult(true); $descriptor->setTargetResourceType($previous->getTargetResourceType()); } else { ODataException::createResourceNotFoundError($identifier); } } else { $descriptor->setTargetResourceType($projectedProperty->getResourceType()); $descriptor->setSingleResult($projectedProperty->getKind() != ResourcePropertyKind::RESOURCESET_REFERENCE); if ($previous->getTargetKind() == RequestTargetKind::LINK && $projectedProperty->getTypeKind() != ResourceTypeKind::ENTITY) { ODataException::createBadRequestError(Messages::segmentParserLinkSegmentMustBeFollowedByEntitySegment($identifier)); } switch ($projectedProperty->getKind()) { case ResourcePropertyKind::COMPLEX_TYPE: $descriptor->setTargetKind(RequestTargetKind::COMPLEX_OBJECT); break; case ResourcePropertyKind::BAG | ResourcePropertyKind::PRIMITIVE: case ResourcePropertyKind::BAG | ResourcePropertyKind::COMPLEX_TYPE: $descriptor->setTargetKind(RequestTargetKind::BAG); break; case ResourcePropertyKind::RESOURCE_REFERENCE: case ResourcePropertyKind::RESOURCESET_REFERENCE: $descriptor->setTargetKind(RequestTargetKind::RESOURCE); $resourceSetWrapper = $this->_providerWrapper->getResourceSetWrapperForNavigationProperty($previous->getTargetResourceSetWrapper(), $previous->getTargetResourceType(), $projectedProperty); if (is_null($resourceSetWrapper)) { ODataException::createResourceNotFoundError($projectedProperty->getName()); } $descriptor->setTargetResourceSetWrapper($resourceSetWrapper); break; default: if (!$projectedProperty->isKindOf(ResourcePropertyKind::PRIMITIVE)) { ODataException::createInternalServerError(Messages::segmentParserUnExpectedPropertyKind('Primitive')); } $descriptor->setTargetKind(RequestTargetKind::PRIMITIVE); break; } if ($hasPredicate) { $this->_assertion(!$descriptor->isSingleResult()); $keyDescriptor = $this->_createKeyDescriptor($identifier . '(' . $keyPredicate . ')', $projectedProperty->getResourceType(), $keyPredicate); $descriptor->setKeyDescriptor($keyDescriptor); if (!$keyDescriptor->isEmpty()) { $descriptor->setSingleResult(true); } } if ($checkRights && !is_null($descriptor->getTargetResourceSetWrapper())) { $descriptor->getTargetResourceSetWrapper()->checkResourceSetRightsForRead($descriptor->isSingleResult()); } } } } } } } $descriptor->setPrevious($previous); $previous->setNext($descriptor); $this->_segmentDescriptors[] = $descriptor; $previous = $descriptor; } if ($previous->getTargetKind() == RequestTargetKind::LINK) { ODataException::createBadRequestError(Messages::segmentParserMissingSegmentAfterLink()); } }
/** * Gets reference to the ResourceSetWrapper instance targetted by * the resource path, ResourceSetWrapper will present in the * following cases: * if the last segment descriptor describes * (a) resource set * http://server/NW.svc/Customers * http://server/NW.svc/Customers('ALFKI') * http://server/NW.svc/Customers('ALFKI')/Orders * http://server/NW.svc/Customers('ALFKI')/Orders(123) * http://server/NW.svc/Customers('ALFKI')/$links/Orders * (b) resource set reference * http://server/NW.svc/Orders(123)/Customer * http://server/NW.svc/Orders(123)/$links/Customer * (c) $count * http://server/NW.svc/Customers/$count * ResourceSet wrapper will be absent (NULL) in the following cases: * if the last segment descriptor describes * (a) Primitive * http://server/NW.svc/Customers('ALFKI')/Country * (b) $value on primitive type * http://server/NW.svc/Customers('ALFKI')/Country/$value * (c) Complex * http://server/NW.svc/Customers('ALFKI')/Address * (d) Bag * http://server/NW.svc/Employees(123)/Emails * (e) MLE * http://server/NW.svc/Employees(123)/$value * (f) Named Stream * http://server/NW.svc/Employees(123)/Thumnail48_48 * (g) metadata * http://server/NW.svc/$metadata * (h) service directory * http://server/NW.svc * (i) $bath * http://server/NW.svc/$batch * * @return ResourceSetWrapper/NULL */ public function getTargetResourceSetWrapper() { return $this->_lastSegmentDescriptor->getTargetResourceSetWrapper(); }