/** * Process the $expand and $select option and update the request description. * * @return void * * @throws ODataException Throws bad request error in the following cases * (1) If $expand or select cannot be applied to the * requested resource. * (2) If projection is disabled by the developer * (3) If some error occurs while parsing the options */ private function _processExpandAndSelect() { $expand = $this->_dataService->getHost()->getQueryStringItem(ODataConstants::HTTPQUERY_STRING_EXPAND); if (!is_null($expand)) { $this->_checkExpandOrSelectApplicable(ODataConstants::HTTPQUERY_STRING_EXPAND); } $select = $this->_dataService->getHost()->getQueryStringItem(ODataConstants::HTTPQUERY_STRING_SELECT); if (!is_null($select)) { if (!$this->_dataService->getServiceConfiguration()->getAcceptProjectionRequests()) { ODataException::createBadRequestError(Messages::dataServiceConfigurationProjectionsNotAccepted()); } $this->_checkExpandOrSelectApplicable(ODataConstants::HTTPQUERY_STRING_SELECT); } // We will generate RootProjectionNode in case of $link request also, but // expand and select in this case must be null (we are ensuring this above) // 'RootProjectionNode' is required while generating next page Link if ($this->_expandSelectApplicable || $this->_requestDescription->isLinkUri()) { try { $rootProjectionNode = ExpandProjectionParser::parseExpandAndSelectClause($this->_requestDescription->getTargetResourceSetWrapper(), $this->_requestDescription->getTargetResourceType(), $this->_requestDescription->getInternalOrderByInfo(), $this->_requestDescription->getSkipCount(), $this->_requestDescription->getTopCount(), $expand, $select, $this->_dataService->getMetadataQueryProviderWrapper()); if ($rootProjectionNode->isSelectionSpecified()) { $this->_requestDescription->raiseMinimumVersionRequirement(2, 0, $this->_dataService); } if ($rootProjectionNode->hasPagedExpandedResult()) { $this->_requestDescription->raiseResponseVersion(2, 0, $this->_dataService); } $this->_requestDescription->setRootProjectionNode($rootProjectionNode); } catch (ODataException $odataException) { throw $odataException; } } }
/** * Ask data service to load stream provider instance. * * @return void * * @throws ODataException */ private function _loadStreamProvider() { if (is_null($this->_streamProvider)) { $maxServiceVersion = $this->_dataService->getServiceConfiguration()->getMaxDataServiceVersionObject(); if ($maxServiceVersion->compare(new Version(3, 0)) >= 0) { $this->_streamProvider = $this->_dataService->getService('IDataServiceStreamProvider2'); if (!is_null($this->_streamProvider) && (!is_object($this->_streamProvider) || array_search('ODataProducer\\Providers\\Stream\\IDataServiceStreamProvider2', class_implements($this->_streamProvider)) === false)) { ODataException::createInternalServerError(Messages::dataServiceStreamProviderWrapperInvalidStream2Instance()); } } if (is_null($this->_streamProvider)) { $this->_streamProvider = $this->_dataService->getService('IDataServiceStreamProvider'); if (!is_null($this->_streamProvider) && (!is_object($this->_streamProvider) || array_search('ODataProducer\\Providers\\Stream\\IDataServiceStreamProvider', class_implements($this->_streamProvider)) === false)) { ODataException::createInternalServerError(Messages::dataServiceStreamProviderWrapperInvalidStreamInstance()); } } } }
/** * Process the given request Uri and creates an instance of * RequestDescription from the processed uri. * * @param Url &$absoluteRequestUri The absolute request uri. * @param DataService &$dataService Reference to the data service * instance. * * @return RequestDescription * * @throws ODataException If any exception occurs while processing the segments * or incase of any version incompatibility. */ public static function process(Url &$absoluteRequestUri, DataService &$dataService) { $absoluteRequestUri = $dataService->getHost()->getAbsoluteRequestUri(); $absoluteServiceUri = $dataService->getHost()->getAbsoluteServiceUri(); $requestUriSegments = array_slice($absoluteRequestUri->getSegments(), $absoluteServiceUri->getSegmentCount()); $segmentDescriptors = null; try { $segmentDescriptors = SegmentParser::parseRequestUriSegements($requestUriSegments, $dataService->getMetadataQueryProviderWrapper(), true); } catch (ODataException $odataException) { throw $odataException; } $requestDescription = new RequestDescription($segmentDescriptors, $absoluteRequestUri); $requestTargetKind = $requestDescription->getTargetKind(); if ($requestTargetKind != RequestTargetKind::METADATA && $requestTargetKind != RequestTargetKind::BATCH && $requestTargetKind != RequestTargetKind::SERVICE_DIRECTORY) { if ($requestTargetKind != RequestTargetKind::PRIMITIVE_VALUE && $requestTargetKind != RequestTargetKind::MEDIA_RESOURCE) { $requestDescription->setContainerName($requestDescription->getIdentifier()); } else { // http://odata/NW.svc/Orders/$count // http://odata/NW.svc/Orders(123)/Customer/CustomerID/$value // http://odata/NW.svc/Employees(1)/$value // http://odata/NW.svc/Employees(1)/ThumbNail_48X48/$value $requestDescription->setContainerName($segmentDescriptors[count($segmentDescriptors) - 2]->getIdentifier()); } if ($requestDescription->getIdentifier() === ODataConstants::URI_COUNT_SEGMENT) { if (!$dataService->getServiceConfiguration()->getAcceptCountRequests()) { ODataException::createBadRequestError(Messages::dataServiceConfigurationCountNotAccepted()); } $requestDescription->setRequestCountOption(RequestCountOption::VALUE_ONLY); // use of $count requires request DataServiceVersion // and MaxDataServiceVersion // greater than or equal to 2.0 $requestDescription->raiseResponseVersion(2, 0, $dataService); $requestDescription->raiseMinimumVersionRequirement(2, 0, $dataService); } else { if ($requestDescription->isNamedStream()) { $requestDescription->raiseMinimumVersionRequirement(3, 0, $dataService); } else { if ($requestDescription->getTargetKind() == RequestTargetKind::RESOURCE) { if (!$requestDescription->isLinkUri()) { $resourceSetWrapper = $requestDescription->getTargetResourceSetWrapper(); //assert($resourceSetWrapper != null) $hasNamedStream = $resourceSetWrapper->hasNamedStreams($dataService->getMetadataQueryProviderWrapper()); $hasBagProperty = $resourceSetWrapper->hasBagProperty($dataService->getMetadataQueryProviderWrapper()); if ($hasNamedStream || $hasBagProperty) { $requestDescription->raiseResponseVersion(3, 0, $dataService); } } } else { if ($requestDescription->getTargetKind() == RequestTargetKind::BAG) { $requestDescription->raiseResponseVersion(3, 0, $dataService); } } } } } return $requestDescription; }
/** * This function is used to perform following checking (validation) * for capability negotiation. * (1) Check client request's 'DataServiceVersion' header value is * less than or equal to the minimum version required to intercept * the response * (2) Check client request's 'MaxDataServiceVersion' header value is * less than or equal to the version of protocol required to generate * the response * (3) Check the configured maximum protocol version is less than or equal * to the version of protocol required to generate the response * In addition to these checking, this function is also responsible for * initializing the properties respresenting 'DataServiceVersion' and * 'MaxDataServiceVersion'. * * @param RequestDescription $requestDescription The request description object * @param DataService $dataService The Service to check * * @return void * * @throws ODataException If any of the above 3 check fails. */ public static function checkVersion(RequestDescription $requestDescription, DataService $dataService) { if (is_null($requestDescription->_requestDataServiceVersion)) { $version = $dataService->getHost()->getRequestVersion(); //'DataServiceVersion' header not present in the request, so use //default value as the maximum version number that the server can //interpret. if (is_null($version)) { $knownVersions = $requestDescription::getKnownDataServiceVersions(); $version = $knownVersions[count($knownVersions) - 1]; } else { $version = $requestDescription::_validateAndGetVersion($version, ODataConstants::ODATAVERSIONHEADER); } $requestDescription->_requestDataServiceVersion = $version; } if (is_null($requestDescription->_requestMaxDataServiceVersion)) { $version = $dataService->getHost()->getRequestMaxVersion(); //'MaxDataServiceVersion' header not present in the request, so use //default value as the maximum version number that the server can //interpret. if (is_null($version)) { $knownVersions = $requestDescription::getKnownDataServiceVersions(); $version = $knownVersions[count($knownVersions) - 1]; } else { $version = $requestDescription::_validateAndGetVersion($version, ODataConstants::ODATAMAXVERSIONHEADER); } $requestDescription->_requestMaxDataServiceVersion = $version; } if ($requestDescription->_requestDataServiceVersion->compare($requestDescription->_minimumRequiredClientVersion) < 0) { ODataException::createBadRequestError(Messages::requestDescriptionDataServiceVersionTooLow($requestDescription->_requestDataServiceVersion->toString(), $requestDescription->_minimumRequiredClientVersion->toString())); } if ($requestDescription->_requestMaxDataServiceVersion->compare($requestDescription->_responseDataServiceVersion) < 0) { ODataException::createBadRequestError(Messages::requestDescriptionDataServiceVersionTooLow($requestDescription->_requestMaxDataServiceVersion->toString(), $requestDescription->_responseDataServiceVersion->toString())); } $configuration = $dataService->getServiceConfiguration(); $maxConfiguredProtocolVersion = $configuration->getMaxDataServiceVersionObject(); if ($maxConfiguredProtocolVersion->compare($requestDescription->_responseDataServiceVersion) < 0) { ODataException::createBadRequestError(Messages::requestDescriptionResponseVersionIsBiggerThanProtocolVersion($requestDescription->_responseDataServiceVersion->toString(), $maxConfiguredProtocolVersion->toString())); } }