/** * 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()); } }