/** * Applies the query options to the resource(s) retrieved from the data source. * * @param SegmentDescriptor &$segmentDescriptor The descriptor which holds * resource(s) on which query * options to be applied. * * @return void */ private function _applyQueryOptions(SegmentDescriptor &$segmentDescriptor) { // This function will not set RequestDescription::Count value if IDSQP2::canApplyQueryOptions // returns false, this function assumes IDSQP2 has already set the count value in the global // variable named _odata_server_count. temporary fix for Drupal OData Plugin support global $_odata_server_count; $result = $segmentDescriptor->getResult(); //Apply $filter option if (!is_null($result)) { $internalFilterInfo = $this->_requestDescription->getInternalFilterInfo(); if (!is_null($internalFilterInfo)) { if (!$internalFilterInfo->isCustomExpression()) { // The QP implementation is not going to perform the filtering // opted for PHPExpressionProvider so run the filtering. $filterFunction = $internalFilterInfo->getFilterFunction()->getReference(); if (is_array($result)) { $count = count($result); for ($i = 0; $i < $count; $i++) { if (!$filterFunction($result[$i])) { unset($result[$i]); } } $result = array_merge($result); } else { if (!$filterFunction($result)) { unset($result); $result = null; } } unset($filterFunction); } else { // The QP2 implementation performed the filtering so don't perform // filtering using library generated filter function. } unset($internalFilterInfo); } } // $inlinecount=allpages should ignore the query options // $skiptoken, $top and $skip so take count before applying these options if ($this->_requestDescription->getRequestCountOption() != RequestCountOption::NONE && is_array($result)) { if ($this->_provider->canApplyQueryOptions()) { $this->_requestDescription->setCountValue(count($result)); } else { $this->_requestDescription->setCountValue($_odata_server_count); } } // Library applies query options only if the IDSQP2::canApplyQueryOptions returns true, IDSQP::canApplyQueryOptions // always returns true. $applicableForSetQuery = $this->_provider->canApplyQueryOptions() && is_array($result) && !empty($result); if ($applicableForSetQuery) { //Apply (implicit and explicit) $orderby option $internalOrderByInfo = $this->_requestDescription->getInternalOrderByInfo(); if (!is_null($internalOrderByInfo)) { $orderByFunction = $internalOrderByInfo->getSorterFunction()->getReference(); usort($result, $orderByFunction); } //Apply $skiptoken option $internalSkipTokenInfo = $this->_requestDescription->getInternalSkipTokenInfo(); if (!is_null($internalSkipTokenInfo)) { $matchingIndex = $internalSkipTokenInfo->getIndexOfFirstEntryInTheNextPage($result); $result = array_slice($result, $matchingIndex); } //Apply $top and $skip option if (!empty($result)) { $top = $this->_requestDescription->getTopCount(); $skip = $this->_requestDescription->getSkipCount(); if (!is_null($top) && !is_null($skip)) { $result = array_slice($result, $skip, $top); } else { if (is_null($top)) { $result = array_slice($result, $skip); } else { if (is_null($skip)) { $result = array_slice($result, 0, $top); } } } //$skip and $top affects $count so consider here. if ($this->_requestDescription->getRequestCountOption() == RequestCountOption::VALUE_ONLY) { $this->_requestDescription->setCountValue(count($result)); } } } $segmentDescriptor->setResult($result); }
/** * Create SegmentDescriptor for the first segment * * @param string $segmentIdentifier The identifier part of the * first segment * @param string $keyPredicate The predicate part of the first * segment if any else NULL * @param boolean $checkRights Whether to check the rights on * this segment * * @return SegmentDescriptor Descriptor for the first segment * * @throws ODataException Exception if any validation fails */ private function _createFirstSegmentDescriptor($segmentIdentifier, $keyPredicate, $checkRights) { $descriptor = new SegmentDescriptor(); $descriptor->setIdentifier($segmentIdentifier); if ($segmentIdentifier === ODataConstants::URI_METADATA_SEGMENT) { $this->_assertion(is_null($keyPredicate)); $descriptor->setTargetKind(RequestTargetKind::METADATA); return $descriptor; } if ($segmentIdentifier === ODataConstants::URI_BATCH_SEGMENT) { $this->_assertion(is_null($keyPredicate)); $descriptor->setTargetKind(RequestTargetKind::BATCH); return $descriptor; } if ($segmentIdentifier === ODataConstants::URI_COUNT_SEGMENT) { ODataException::createBadRequestError(Messages::segmentParserSegmentNotAllowedOnRoot(ODataConstants::URI_COUNT_SEGMENT)); } if ($segmentIdentifier === ODataConstants::URI_LINK_SEGMENT) { ODataException::createBadRequestError(Messages::segmentParserSegmentNotAllowedOnRoot(ODataConstants::URI_LINK_SEGMENT)); } $resourceSetWrapper = $this->_providerWrapper->resolveResourceSet($segmentIdentifier); if ($resourceSetWrapper === null) { ODataException::createResourceNotFoundError($segmentIdentifier); } $descriptor->setTargetResourceSetWrapper($resourceSetWrapper); $descriptor->setTargetResourceType($resourceSetWrapper->getResourceType()); $descriptor->setTargetSource(RequestTargetSource::ENTITY_SET); $descriptor->setTargetKind(RequestTargetKind::RESOURCE); if ($keyPredicate !== null) { $keyDescriptor = $this->_createKeyDescriptor($segmentIdentifier . '(' . $keyPredicate . ')', $resourceSetWrapper->getResourceType(), $keyPredicate); $descriptor->setKeyDescriptor($keyDescriptor); if (!$keyDescriptor->isEmpty()) { $descriptor->setSingleResult(true); } } if ($checkRights) { $resourceSetWrapper->checkResourceSetRightsForRead($descriptor->isSingleResult()); } return $descriptor; }
/** * Checks whether etag headers are allowed for this request. * * @return boolean True if ETag header (If-Match or If-NoneMatch) * is allowed for the request, False otherwise. */ public function isETagHeaderAllowed() { return $this->_lastSegmentDescriptor->isSingleResult() && $this->_requestCountOption != RequestCountOption::VALUE_ONLY && !$this->isLinkUri() && (is_null($this->_rootProjectionNode) || !$this->_rootProjectionNode->isExpansionSpecified()); }