/** * 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 &$segment Describes the related resource * to query. * * @return void */ private function _handleSegmentTargetsToRelatedResource(SegmentDescriptor $segment) { $projectedProperty = $segment->getProjectedProperty(); $projectedPropertyKind = $projectedProperty->getKind(); if ($projectedPropertyKind == ResourcePropertyKind::RESOURCESET_REFERENCE) { if ($segment->isSingleResult()) { $entityInstance = $this->providers->getResourceFromRelatedResourceSet($segment->getPrevious()->getTargetResourceSetWrapper(), $segment->getPrevious()->getResult(), $segment->getTargetResourceSetWrapper(), $projectedProperty, $segment->getKeyDescriptor()); $segment->setResult($entityInstance); } else { $queryResult = $this->providers->getRelatedResourceSet($this->request->queryType, $segment->getPrevious()->getTargetResourceSetWrapper(), $segment->getPrevious()->getResult(), $segment->getTargetResourceSetWrapper(), $segment->getProjectedProperty(), $this->request->getFilterInfo(), null, null, null); $segment->setResult($queryResult); } } else { if ($projectedPropertyKind == ResourcePropertyKind::RESOURCE_REFERENCE) { $entityInstance = $this->providers->getRelatedResourceReference($segment->getPrevious()->getTargetResourceSetWrapper(), $segment->getPrevious()->getResult(), $segment->getTargetResourceSetWrapper(), $segment->getProjectedProperty()); $segment->setResult($entityInstance); } else { //Unexpected state } } }
/** * Gets reference to the ResourceSetWrapper instance targeted 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->lastSegment->getTargetResourceSetWrapper(); }
private function createNextSegment(SegmentDescriptor $previous, $segment, $checkRights) { $previousKind = $previous->getTargetKind(); if ($previousKind == TargetKind::METADATA() || $previousKind == TargetKind::BATCH() || $previousKind == TargetKind::PRIMITIVE_VALUE() || $previousKind == TargetKind::BAG() || $previousKind == TargetKind::MEDIA_RESOURCE()) { //All these targets are terminal segments, there cannot be anything after them. throw ODataException::resourceNotFoundError(Messages::segmentParserMustBeLeafSegment($previous->getIdentifier())); } $identifier = $keyPredicate = null; $this->extractSegmentIdentifierAndKeyPredicate($segment, $identifier, $keyPredicate); $hasPredicate = !is_null($keyPredicate); $current = null; if ($previousKind == TargetKind::PRIMITIVE()) { if ($identifier !== ODataConstants::URI_VALUE_SEGMENT) { throw ODataException::resourceNotFoundError(Messages::segmentParserOnlyValueSegmentAllowedAfterPrimitivePropertySegment($identifier, $previous->getIdentifier())); } $this->_assertion(!$hasPredicate); $current = SegmentDescriptor::createFrom($previous); $current->setIdentifier(ODataConstants::URI_VALUE_SEGMENT); $current->setTargetKind(TargetKind::PRIMITIVE_VALUE()); $current->setSingleResult(true); } else { if (!is_null($previous->getPrevious()) && $previous->getPrevious()->getIdentifier() === ODataConstants::URI_LINK_SEGMENT && $identifier !== ODataConstants::URI_COUNT_SEGMENT) { throw ODataException::createBadRequestError(Messages::segmentParserNoSegmentAllowedAfterPostLinkSegment($identifier)); } else { if ($previousKind == TargetKind::RESOURCE() && $previous->isSingleResult() && $identifier === ODataConstants::URI_LINK_SEGMENT) { $this->_assertion(!$hasPredicate); $current = SegmentDescriptor::createFrom($previous); $current->setIdentifier(ODataConstants::URI_LINK_SEGMENT); $current->setTargetKind(TargetKind::LINK()); } else { //Do a sanity check here if ($previousKind != TargetKind::COMPLEX_OBJECT() && $previousKind != TargetKind::RESOURCE() && $previousKind != TargetKind::LINK()) { throw ODataException::createInternalServerError(Messages::segmentParserInconsistentTargetKindState()); } if (!$previous->isSingleResult() && $identifier !== ODataConstants::URI_COUNT_SEGMENT) { throw ODataException::createBadRequestError(Messages::segmentParserCannotQueryCollection($previous->getIdentifier())); } $current = new SegmentDescriptor(); $current->setIdentifier($identifier); $current->setTargetSource(TargetSource::PROPERTY); $projectedProperty = $previous->getTargetResourceType()->resolveProperty($identifier); $current->setProjectedProperty($projectedProperty); if ($identifier === ODataConstants::URI_COUNT_SEGMENT) { if ($previousKind != TargetKind::RESOURCE()) { throw ODataException::createBadRequestError(Messages::segmentParserCountCannotBeApplied($previous->getIdentifier())); } if ($previous->isSingleResult()) { throw ODataException::createBadRequestError(Messages::segmentParserCountCannotFollowSingleton($previous->getIdentifier())); } $current->setTargetKind(TargetKind::PRIMITIVE_VALUE()); $current->setSingleResult(true); $current->setTargetResourceSetWrapper($previous->getTargetResourceSetWrapper()); $current->setTargetResourceType($previous->getTargetResourceType()); } else { if ($identifier === ODataConstants::URI_VALUE_SEGMENT && $previousKind == TargetKind::RESOURCE()) { $current->setSingleResult(true); $current->setTargetResourceType($previous->getTargetResourceType()); $current->setTargetKind(TargetKind::MEDIA_RESOURCE()); } else { if (is_null($projectedProperty)) { if (!is_null($previous->getTargetResourceType()) && !is_null($previous->getTargetResourceType()->tryResolveNamedStreamByName($identifier))) { $current->setTargetKind(TargetKind::MEDIA_RESOURCE()); $current->setSingleResult(true); $current->setTargetResourceType($previous->getTargetResourceType()); } else { throw ODataException::createResourceNotFoundError($identifier); } } else { $current->setTargetResourceType($projectedProperty->getResourceType()); $current->setSingleResult($projectedProperty->getKind() != ResourcePropertyKind::RESOURCESET_REFERENCE); if ($previousKind == TargetKind::LINK() && $projectedProperty->getTypeKind() != ResourceTypeKind::ENTITY) { throw ODataException::createBadRequestError(Messages::segmentParserLinkSegmentMustBeFollowedByEntitySegment($identifier)); } switch ($projectedProperty->getKind()) { case ResourcePropertyKind::COMPLEX_TYPE: $current->setTargetKind(TargetKind::COMPLEX_OBJECT()); break; case ResourcePropertyKind::BAG | ResourcePropertyKind::PRIMITIVE: case ResourcePropertyKind::BAG | ResourcePropertyKind::COMPLEX_TYPE: $current->setTargetKind(TargetKind::BAG()); break; case ResourcePropertyKind::RESOURCE_REFERENCE: case ResourcePropertyKind::RESOURCESET_REFERENCE: $current->setTargetKind(TargetKind::RESOURCE()); $resourceSetWrapper = $this->providerWrapper->getResourceSetWrapperForNavigationProperty($previous->getTargetResourceSetWrapper(), $previous->getTargetResourceType(), $projectedProperty); if (is_null($resourceSetWrapper)) { throw ODataException::createResourceNotFoundError($projectedProperty->getName()); } $current->setTargetResourceSetWrapper($resourceSetWrapper); break; default: if (!$projectedProperty->isKindOf(ResourcePropertyKind::PRIMITIVE)) { throw ODataException::createInternalServerError(Messages::segmentParserUnExpectedPropertyKind('Primitive')); } $current->setTargetKind(TargetKind::PRIMITIVE()); break; } if ($hasPredicate) { $this->_assertion(!$current->isSingleResult()); $keyDescriptor = $this->_createKeyDescriptor($identifier . '(' . $keyPredicate . ')', $projectedProperty->getResourceType(), $keyPredicate); $current->setKeyDescriptor($keyDescriptor); if (!$keyDescriptor->isEmpty()) { $current->setSingleResult(true); } } if ($checkRights && !is_null($current->getTargetResourceSetWrapper())) { $current->getTargetResourceSetWrapper()->checkResourceSetRightsForRead($current->isSingleResult()); } } } } } } } return $current; }