コード例 #1
0
 /**
  * Build 'Projection Tree' from the given expand path segments
  * 
  * @param array(array(string)) $expandPathSegments Collection of expand 
  *                                                 paths.
  * 
  * @return void
  * 
  * @throws ODataException If any error occurs while processing the expand
  *                        path segments.
  */
 private function _buildProjectionTree($expandPathSegments)
 {
     foreach ($expandPathSegments as $expandSubPathSegments) {
         $currentNode = $this->_rootProjectionNode;
         foreach ($expandSubPathSegments as $expandSubPathSegment) {
             $resourceSetWrapper = $currentNode->getResourceSetWrapper();
             $resourceType = $currentNode->getResourceType();
             $resourceProperty = $resourceType->tryResolvePropertyTypeByName($expandSubPathSegment);
             if (is_null($resourceProperty)) {
                 ODataException::createSyntaxError(Messages::expandProjectionParserPropertyNotFound($resourceType->getFullName(), $expandSubPathSegment, false));
             } else {
                 if ($resourceProperty->getTypeKind() != ResourceTypeKind::ENTITY) {
                     ODataException::createBadRequestError(Messages::expandProjectionParserExpandCanOnlyAppliedToEntity($resourceType->getFullName(), $expandSubPathSegment));
                 }
             }
             $resourceSetWrapper = $this->_providerWrapper->getResourceSetWrapperForNavigationProperty($resourceSetWrapper, $resourceType, $resourceProperty);
             if (is_null($resourceSetWrapper)) {
                 ODataException::createBadRequestError(Messages::badRequestInvalidPropertyNameSpecified($resourceType->getFullName(), $expandSubPathSegment));
             }
             $singleResult = $resourceProperty->isKindOf(ResourcePropertyKind::RESOURCE_REFERENCE);
             $resourceSetWrapper->checkResourceSetRightsForRead($singleResult);
             $pageSize = $resourceSetWrapper->getResourceSetPageSize();
             $internalOrderByInfo = null;
             if ($pageSize != 0 && !$singleResult) {
                 $this->_rootProjectionNode->setPagedExpandedResult(true);
                 $rt = $resourceSetWrapper->getResourceType();
                 //assert($rt != null)
                 $keys = array_keys($rt->getKeyProperties());
                 //assert(!empty($keys))
                 $orderBy = null;
                 foreach ($keys as $key) {
                     $orderBy = $orderBy . $key . ', ';
                 }
                 $orderBy = rtrim($orderBy, ', ');
                 try {
                     $internalOrderByInfo = OrderByParser::parseOrderByClause($resourceSetWrapper, $rt, $orderBy, $this->_providerWrapper);
                 } catch (ODataException $odataException) {
                     throw $odataException;
                 }
             }
             $node = $currentNode->findNode($expandSubPathSegment);
             if (is_null($node)) {
                 $maxResultCount = $this->_providerWrapper->getConfiguration()->getMaxResultsPerCollection();
                 $node = new ExpandedProjectionNode($expandSubPathSegment, $resourceProperty, $resourceSetWrapper, $internalOrderByInfo, null, $pageSize == 0 ? null : $pageSize, $maxResultCount == PHP_INT_MAX ? null : $maxResultCount);
                 $currentNode->addNode($node);
             }
             $currentNode = $node;
         }
     }
 }
コード例 #2
0
ファイル: SegmentParser.php プロジェクト: i-geo/odataphpprod
 /**
  * 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());
     }
 }
コード例 #3
0
ファイル: OrderByParser.php プロジェクト: i-geo/odataphpprod
 /**
  * Build 'OrderBy Tree' from the given orderby path segments, also build 
  * comparsion function for each path segment.
  * 
  * @param array(array) &$ordeyByPathSegments Collection of orderby path segments,
  *                                           this is passed by reference
  *                                           since we need this function to 
  *                                           modify this array in two cases:
  *                                           1. if asc or desc present, then the 
  *                                              corrosponding sub path segment 
  *                                              should be removed
  *                                           2. remove duplicate orderby path 
  *                                              segment
  * 
  * @return void
  * 
  * @throws ODataException If any error occurs while processing the orderby path 
  *                        segments
  */
 private function _buildOrderByTree(&$ordeyByPathSegments)
 {
     foreach ($ordeyByPathSegments as $index1 => &$ordeyBySubPathSegments) {
         $currentNode = $this->_rootOrderByNode;
         $currentObject = $this->_dummyObject;
         $ascending = true;
         $subPathCount = count($ordeyBySubPathSegments);
         // Check sort order is specified in the path, if so set a
         // flag and remove that segment
         if ($subPathCount > 1) {
             if ($ordeyBySubPathSegments[$subPathCount - 1] === '*desc') {
                 $ascending = false;
                 unset($ordeyBySubPathSegments[$subPathCount - 1]);
                 $subPathCount--;
             } else {
                 if ($ordeyBySubPathSegments[$subPathCount - 1] === '*asc') {
                     unset($ordeyBySubPathSegments[$subPathCount - 1]);
                     $subPathCount--;
                 }
             }
         }
         $ancestors = array($this->_rootOrderByNode->getResourceSetWrapper()->getName());
         foreach ($ordeyBySubPathSegments as $index2 => $orderBySubPathSegment) {
             $isLastSegment = $index2 == $subPathCount - 1;
             $resourceSetWrapper = null;
             $resourceType = $currentNode->getResourceType();
             $resourceProperty = $resourceType->tryResolvePropertyTypeByName($orderBySubPathSegment);
             if (is_null($resourceProperty)) {
                 ODataException::createSyntaxError(Messages::orderByParserPropertyNotFound($resourceType->getFullName(), $orderBySubPathSegment));
             }
             if ($resourceProperty->isKindOf(ResourcePropertyKind::BAG)) {
                 ODataException::createBadRequestError(Messages::orderByParserBagPropertyNotAllowed($resourceProperty->getName()));
             } else {
                 if ($resourceProperty->isKindOf(ResourcePropertyKind::PRIMITIVE)) {
                     if (!$isLastSegment) {
                         ODataException::createBadRequestError(Messages::orderByParserPrimitiveAsIntermediateSegment($resourceProperty->getName()));
                     }
                     $type = $resourceProperty->getInstanceType();
                     if ($type instanceof Binary) {
                         ODataException::createBadRequestError(Messages::orderbyParserSortByBinaryPropertyNotAllowed($resourceProperty->getName()));
                     }
                 } else {
                     if ($resourceProperty->getKind() == ResourcePropertyKind::RESOURCESET_REFERENCE || $resourceProperty->getKind() == ResourcePropertyKind::RESOURCE_REFERENCE) {
                         $this->_assertion($currentNode instanceof OrderByRootNode || $currentNode instanceof OrderByNode);
                         $resourceSetWrapper = $currentNode->getResourceSetWrapper();
                         $this->_assertion(!is_null($resourceSetWrapper));
                         $resourceSetWrapper = $this->_providerWrapper->getResourceSetWrapperForNavigationProperty($resourceSetWrapper, $resourceType, $resourceProperty);
                         if (is_null($resourceSetWrapper)) {
                             ODataException::createBadRequestError(Messages::badRequestInvalidPropertyNameSpecified($resourceType->getFullName(), $orderBySubPathSegment));
                         }
                         if ($resourceProperty->getKind() == ResourcePropertyKind::RESOURCESET_REFERENCE) {
                             ODataException::createBadRequestError(Messages::orderbyParserResourceSetReferenceNotAllowed($resourceProperty->getName(), $resourceType->getFullName()));
                         }
                         $resourceSetWrapper->checkResourceSetRightsForRead(true);
                         if ($isLastSegment) {
                             ODataException::createBadRequestError(Messages::orderByParserSortByNavigationPropertyIsNotAllowed($resourceProperty->getName()));
                         }
                         $ancestors[] = $orderBySubPathSegment;
                     } else {
                         if ($resourceProperty->isKindOf(ResourcePropertyKind::COMPLEX_TYPE)) {
                             if ($isLastSegment) {
                                 ODataException::createBadRequestError(Messages::orderByParserSortByComplexPropertyIsNotAllowed($resourceProperty->getName()));
                             }
                             $ancestors[] = $orderBySubPathSegment;
                         } else {
                             ODataException::createInternalServerError(Messages::orderByParserUnexpectedPropertyType());
                         }
                     }
                 }
             }
             $node = $currentNode->findNode($orderBySubPathSegment);
             if (is_null($node)) {
                 if ($resourceProperty->isKindOf(ResourcePropertyKind::PRIMITIVE)) {
                     $node = new OrderByLeafNode($orderBySubPathSegment, $resourceProperty, $ascending);
                     $this->_comparisonFunctions[] = $node->buildComparisonFunction($ancestors);
                 } else {
                     if ($resourceProperty->getKind() == ResourcePropertyKind::RESOURCE_REFERENCE) {
                         $node = new OrderByNode($orderBySubPathSegment, $resourceProperty, $resourceSetWrapper);
                         // Initialize this member variable (identified by
                         // $resourceProperty) of parent object.
                         try {
                             $dummyProperty = new \ReflectionProperty($currentObject, $resourceProperty->getName());
                             $object = $resourceProperty->getInstanceType()->newInstance();
                             $dummyProperty->setValue($currentObject, $object);
                             $currentObject = $object;
                         } catch (\ReflectionException $reflectionException) {
                             throw ODataException::createInternalServerError(Messages::orderByParserFailedToAccessOrInitializeProperty($resourceProperty->getName(), $resourceType->getName()));
                         }
                     } else {
                         if ($resourceProperty->getKind() == ResourcePropertyKind::COMPLEX_TYPE) {
                             $node = new OrderByNode($orderBySubPathSegment, $resourceProperty, null);
                             // Initialize this member variable
                             // (identified by $resourceProperty)of parent object.
                             try {
                                 $dummyProperty = new \ReflectionProperty($currentObject, $resourceProperty->getName());
                                 $object = $resourceProperty->getInstanceType()->newInstance();
                                 $dummyProperty->setValue($currentObject, $object);
                                 $currentObject = $object;
                             } catch (\ReflectionException $reflectionException) {
                                 throw ODataException::createInternalServerError(Messages::orderByParserFailedToAccessOrInitializeProperty($resourceProperty->getName(), $resourceType->getName()));
                             }
                         }
                     }
                 }
                 $currentNode->addNode($node);
             } else {
                 try {
                     $dummyProperty = new \ReflectionProperty($currentObject, $resourceProperty->getName());
                     $currentObject = $dummyProperty->getValue($currentObject);
                 } catch (\ReflectionException $reflectionException) {
                     throw ODataException::createInternalServerError(Messages::orderByParserFailedToAccessOrInitializeProperty($resourceProperty->getName(), $resourceType->getName()));
                 }
                 if ($node instanceof OrderByLeafNode) {
                     //remove duplicate orderby path
                     unset($ordeyByPathSegments[$index1]);
                 }
             }
             $currentNode = $node;
         }
     }
 }