Пример #1
0
 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;
 }