/** * Test search InternalSkipToeknInfo::GetIndexOfFirstEntryInNextPage function */ public function testGetIndexOfFirstEntryInNextPage2() { try { $northWindMetadata = CreateNorthWindMetadata1::Create(); $configuration = new DataServiceConfiguration($northWindMetadata); $configuration->setEntitySetAccessRule('*', EntitySetRights::ALL); $metaQueryProverWrapper = new MetadataQueryProviderWrapper($northWindMetadata, null, $configuration, false); $resourceSetWrapper = $metaQueryProverWrapper->resolveResourceSet('Orders'); $resourceType = $resourceSetWrapper->getResourceType(); $orderBy = 'ShipName asc, Freight'; //Note: library will add prim key as last sort key $orderBy .= ', OrderID'; $qp = new NorthWindQueryProvider1(); $orders = $qp->getResourceSet($resourceSetWrapper->getResourceSet()); $internalOrderByInfo = OrderByParser::parseOrderByClause($resourceSetWrapper, $resourceType, $orderBy, $metaQueryProverWrapper); $compFun = $internalOrderByInfo->getSorterFunction(); $fun = $compFun->getReference(); usort($orders, $fun); $numRecords = count($orders); //----------------------------------------------------------------- //Search with a key that exactly matches $skipToken = utf8_decode(urldecode("'Antonio%20Moreno%20Taquer%C3%ADa',22.0000M,10365")); $skipToken = urldecode($skipToken); $internalSkipTokenInfo = SkipTokenParser::parseSkipTokenClause($resourceType, $internalOrderByInfo, $skipToken); $nextIndex = $internalSkipTokenInfo->getIndexOfFirstEntryInTheNextPage($orders); $this->assertTrue($nextIndex > 1); $this->assertTrue($nextIndex < $numRecords); //$nextIndex is the index of order record next to the searched record $this->assertEquals($orders[$nextIndex - 1]->OrderID, 10365); $this->assertEquals($orders[$nextIndex - 1]->Freight, 22.0); //----------------------------------------------------------------- //Search with a key that partially matches, in the DB there is no //order with ShipName 'An', but there are records start with //'An', so partial match, since its a parial match other two //key wont be used for comparsion $skipToken = "'An',22.0000M,10365"; $internalSkipTokenInfo = SkipTokenParser::parseSkipTokenClause($resourceType, $internalOrderByInfo, $skipToken); $nextIndex = $internalSkipTokenInfo->getIndexOfFirstEntryInTheNextPage($orders); $this->assertTrue($nextIndex > 1); $this->assertTrue($nextIndex < $numRecords); //Make sure this is the most matching record by comparing with previous record $prevOrder = $orders[$nextIndex - 1]; $r = strcmp($prevOrder->ShipName, $orders[$nextIndex]->ShipName); $this->assertTrue($r < 0); //Make sure this is the most matching record by comparing with next record $nextOrder = $orders[$nextIndex + 1]; $r = strcmp($nextOrder->ShipName, $orders[$nextIndex]->ShipName); $this->assertTrue($r >= 0); //----------------------------------------------------------------- //Search with a key that does not exists $skipToken = "'XXX',11,10365"; $internalSkipTokenInfo = SkipTokenParser::parseSkipTokenClause($resourceType, $internalOrderByInfo, $skipToken); $nextIndex = $internalSkipTokenInfo->getIndexOfFirstEntryInTheNextPage($orders); $this->assertTrue($nextIndex == -1); //----------------------------------------------------------------- } catch (\Exception $exception) { $this->fail('An unexpected Exception has been raised.' . $exception->getMessage()); } }
/** * Gets the namespace of the given resource type, * if it is null, then default to the container namespace. * * @param ResourceType $resourceType The resource type * * @return string The namespace of the resource type. */ protected function getResourceTypeNamespace(ResourceType $resourceType) { $resourceTypeNamespace = $resourceType->getNamespace(); if (empty($resourceTypeNamespace)) { $resourceTypeNamespace = $this->metadataQueryproviderWrapper->getContainerNamespace(); } return $resourceTypeNamespace; }
/** * Write the service document in Atom format. * * @param Object &$dummy Dummy object * * @return string */ public function writeRequest(&$dummy) { $this->_xmlWriter = new \XMLWriter(); $this->_xmlWriter->openMemory(); $this->_xmlWriter->startElementNs(null, ODataConstants::ATOM_PUBLISHING_SERVICE_ELEMENT_NAME, ODataConstants::APP_NAMESPACE); $this->_xmlWriter->writeAttributeNs(ODataConstants::XML_NAMESPACE_PREFIX, ODataConstants::XML_BASE_ATTRIBUTE_NAME, null, $this->_baseUri); $this->_xmlWriter->writeAttributeNs(ODataConstants::XMLNS_NAMESPACE_PREFIX, self::ATOM_NAMESPACE_PREFIX, null, ODataConstants::ATOM_NAMESPACE); $this->_xmlWriter->writeAttributeNs(ODataConstants::XMLNS_NAMESPACE_PREFIX, self::APP_NAMESPACE_PREFIX, null, ODataConstants::APP_NAMESPACE); $this->_xmlWriter->startElement(ODataConstants::ATOM_PUBLISHING_WORKSPACE_ELEMNT_NAME); $this->_xmlWriter->startElementNs(self::ATOM_NAMESPACE_PREFIX, ODataConstants::ATOM_TITLE_ELELMET_NAME, null); $this->_xmlWriter->text(ODataConstants::ATOM_PUBLISHING_WORKSPACE_DEFAULT_VALUE); $this->_xmlWriter->endElement(); foreach ($this->_metadataQueryproviderWrapper->getResourceSets() as $resourceSetWrapper) { //start collection node $this->_xmlWriter->startElement(ODataConstants::ATOM_PUBLISHING_COLLECTION_ELEMENT_NAME); $this->_xmlWriter->writeAttribute(ODataConstants::ATOM_HREF_ATTRIBUTE_NAME, $resourceSetWrapper->getName()); //start title node $this->_xmlWriter->startElementNs(self::ATOM_NAMESPACE_PREFIX, ODataConstants::ATOM_TITLE_ELELMET_NAME, null); $this->_xmlWriter->text($resourceSetWrapper->getName()); //end title node $this->_xmlWriter->endElement(); //end collection node $this->_xmlWriter->endElement(); } //End workspace and service nodes $this->_xmlWriter->endElement(); $this->_xmlWriter->endElement(); $serviceDocumentInAtom = $this->_xmlWriter->outputMemory(true); return $serviceDocumentInAtom; }
public function testWriteMetadata() { $northWindMetadata = CreateNorthWindMetadata1::Create(); $configuration = new DataServiceConfiguration($northWindMetadata); $configuration->setEntitySetAccessRule("*", EntitySetRights::ALL); $configuration->setMaxDataServiceVersion(DataServiceProtocolVersion::V3); $northWindQuery = new NorthWindQueryProvider1(); $metaQueryProverWrapper = new MetadataQueryProviderWrapper($northWindMetadata, $northWindQuery, $configuration, false); $metadataWriter = new MetadataWriter($metaQueryProverWrapper); $metadata = $metadataWriter->writeMetadata(); $this->assertNotNull($metadata); $this->assertEquals($metaQueryProverWrapper->getContainerName(), 'NorthWindEntities'); $this->assertEquals($metaQueryProverWrapper->getContainerNamespace(), 'NorthWind'); $this->assertStringStartsWith('<edmx:Edmx Version="1.0"', $metadata); $customerResourceSet = $metaQueryProverWrapper->resolveResourceSet('Customers'); $this->assertEquals($customerResourceSet->getName(), 'Customers'); $this->assertEquals($customerResourceSet->getResourceType()->getName(), 'Customer'); $customerEntityType = $metaQueryProverWrapper->resolveResourceType('Customer'); $this->assertEquals($customerEntityType->getResourceTypeKind(), ResourceTypeKind::ENTITY); }
/** * 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; } } }
/** * Write entity container * * @return nothing */ private function _writeEntityContainer() { $this->_iOdataWriter->startElement(ODataConstants::ENTITY_CONTAINER); $this->_iOdataWriter->writeAttribute(ODataConstants::NAME, $this->_metadataQueryproviderWrapper->getContainerName()); $this->_iOdataWriter->writeAttributeNs(ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX, ODataConstants::ISDEFAULT_ENTITY_CONTAINER_ATTRIBUTE, null, "true"); foreach ($this->_metadataManager->getResourceSets() as $resourceSet) { $this->_iOdataWriter->startElement(ODataConstants::ENTITY_SET); $this->_iOdataWriter->writeAttribute(ODataConstants::NAME, $resourceSet->getName()); $this->_iOdataWriter->writeAttribute(ODataConstants::ENTITY_TYPE, $resourceSet->getResourceType()->getFullName()); $this->_iOdataWriter->endElement(); } $this->_writeAssociationSets(); $this->_iOdataWriter->endElement(); }
/** * 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; }
/** * Write the service document in JSON format. * * @param Object &$dummy Dummy object * * @return string */ public function writeRequest(&$dummy) { // { "d" : $this->_writer->startObjectScope(); $this->_writer->writeDataWrapper(); // { $this->_writer->startObjectScope(); // "EntitySets" $this->_writer->writeName(ODataConstants::ENTITY_SET); // [ $this->_writer->startArrayScope(); foreach ($this->_metadataQueryproviderWrapper->getResourceSets() as $resourceSetWrapper) { $this->_writer->writeValue($resourceSetWrapper->getName()); } // ] $this->_writer->endScope(); // } $this->_writer->endScope(); // } $this->_writer->endScope(); //result $serviceDocumentInJson = $this->_writer->getJsonOutput(); return $serviceDocumentInJson; }
/** * Test whether order by parser identify and remove path duplication */ public function testOrderByWithPathDuplication() { try { $northWindMetadata = CreateNorthWindMetadata3::Create(); $configuration = new DataServiceConfiguration($northWindMetadata); $configuration->setEntitySetAccessRule('*', EntitySetRights::ALL); $metaQueryProverWrapper = new MetadataQueryProviderWrapper($northWindMetadata, null, $configuration, false); $resourceSetWrapper = $metaQueryProverWrapper->resolveResourceSet('Order_Details'); $resourceType = $resourceSetWrapper->getResourceType(); $orderBy = 'Order/Price desc, Product/ProductName asc, Order/Price asc'; $internalOrderInfo = OrderByParser::parseOrderByClause($resourceSetWrapper, $resourceType, $orderBy, $metaQueryProverWrapper); //The orderby path Order/Price appears twice, but parser will consider only first path $orderByInfo = $internalOrderInfo->getOrderByInfo(); //There are navigation (resource reference) properties in the orderby path so getNavigationPropertiesUsed should //not be null $naviUsed = $orderByInfo->getNavigationPropertiesUsed(); $this->assertFalse(is_null($naviUsed)); //3 path segment are there, but last one is duplicate of first one, so parser removes last one $this->assertEquals(count($naviUsed), 2); $this->assertTrue(is_array($naviUsed[0])); $this->assertTrue(is_array($naviUsed[1])); //one navgations used in first orderby 'Order' $this->assertEquals(count($naviUsed[0]), 1); //one navgations used in second orderby 'Prodcut' $this->assertEquals(count($naviUsed[1]), 1); $this->assertEquals($naviUsed[0][0]->getName(), 'Order'); $this->assertEquals($naviUsed[1][0]->getName(), 'Product'); $orderByPathSegments = $orderByInfo->getOrderByPathSegments(); $this->assertEquals(count($orderByPathSegments), 2); } catch (\Exception $exception) { $this->fail('An unexpected Exception has been raised' . $exception->getMessage()); } }
/** * Gets resource sets which are visible * * @return array(ResourceSetWrapper) */ public function getResourceSets() { return $this->_metadataQueryproviderWrapper->getResourceSets(); }
/** * 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; } } }
/** * Execute queries for expansion. * * @param array(mixed)/mixed &$result Resource(s) whose navigation properties * needs to be expanded. * * @return void */ private function _executeExpansion(&$result) { $expandedProjectionNodes = $this->_getExpandedProjectionNodes(); foreach ($expandedProjectionNodes as $expandedProjectionNode) { $isCollection = $expandedProjectionNode->getResourceProperty()->getKind() == ResourcePropertyKind::RESOURCESET_REFERENCE; $expandedPropertyName = $expandedProjectionNode->getResourceProperty()->getName(); if (is_array($result)) { foreach ($result as $entry) { // Check for null entry if ($isCollection) { $currentResourceSet = $this->_getCurrentResourceSetWrapper()->getResourceSet(); $resourceSetOfProjectedProperty = $expandedProjectionNode->getResourceSetWrapper()->getResourceSet(); $projectedProperty1 = $expandedProjectionNode->getResourceProperty(); $result1 = $this->_provider->getRelatedResourceSet($currentResourceSet, $entry, $resourceSetOfProjectedProperty, $projectedProperty1, null, null, null, null, null); if (!empty($result1)) { $internalOrderByInfo = $expandedProjectionNode->getInternalOrderByInfo(); if (!is_null($internalOrderByInfo)) { $orderByFunction = $internalOrderByInfo->getSorterFunction()->getReference(); usort($result1, $orderByFunction); unset($internalOrderByInfo); $takeCount = $expandedProjectionNode->getTakeCount(); if (!is_null($takeCount)) { $result1 = array_slice($result1, 0, $takeCount); } } $entry->{$expandedPropertyName} = $result1; $projectedProperty = $expandedProjectionNode->getResourceProperty(); $needPop = $this->_pushSegmentForNavigationProperty($projectedProperty); $this->_executeExpansion($result1); $this->_popSegment($needPop); } else { $entry->{$expandedPropertyName} = array(); } } else { $currentResourceSet1 = $this->_getCurrentResourceSetWrapper()->getResourceSet(); $resourceSetOfProjectedProperty1 = $expandedProjectionNode->getResourceSetWrapper()->getResourceSet(); $projectedProperty2 = $expandedProjectionNode->getResourceProperty(); $result1 = $this->_provider->getRelatedResourceReference($currentResourceSet1, $entry, $resourceSetOfProjectedProperty1, $projectedProperty2); $entry->{$expandedPropertyName} = $result1; if (!is_null($result1)) { $projectedProperty3 = $expandedProjectionNode->getResourceProperty(); $needPop = $this->_pushSegmentForNavigationProperty($projectedProperty3); $this->_executeExpansion($result1); $this->_popSegment($needPop); } } } } else { if ($isCollection) { $currentResourceSet2 = $this->_getCurrentResourceSetWrapper()->getResourceSet(); $resourceSetOfProjectedProperty2 = $expandedProjectionNode->getResourceSetWrapper()->getResourceSet(); $projectedProperty4 = $expandedProjectionNode->getResourceProperty(); $result1 = $this->_provider->getRelatedResourceSet($currentResourceSet2, $result, $resourceSetOfProjectedProperty2, $projectedProperty4, null, null, null, null, null); if (!empty($result1)) { $internalOrderByInfo = $expandedProjectionNode->getInternalOrderByInfo(); if (!is_null($internalOrderByInfo)) { $orderByFunction = $internalOrderByInfo->getSorterFunction()->getReference(); usort($result1, $orderByFunction); unset($internalOrderByInfo); $takeCount = $expandedProjectionNode->getTakeCount(); if (!is_null($takeCount)) { $result1 = array_slice($result1, 0, $takeCount); } } $result->{$expandedPropertyName} = $result1; $projectedProperty7 = $expandedProjectionNode->getResourceProperty(); $needPop = $this->_pushSegmentForNavigationProperty($projectedProperty7); $this->_executeExpansion($result1); $this->_popSegment($needPop); } else { $result->{$expandedPropertyName} = array(); } } else { $currentResourceSet3 = $this->_getCurrentResourceSetWrapper()->getResourceSet(); $resourceSetOfProjectedProperty3 = $expandedProjectionNode->getResourceSetWrapper()->getResourceSet(); $projectedProperty5 = $expandedProjectionNode->getResourceProperty(); $result1 = $this->_provider->getRelatedResourceReference($currentResourceSet3, $result, $resourceSetOfProjectedProperty3, $projectedProperty5); $result->{$expandedPropertyName} = $result1; if (!is_null($result1)) { $projectedProperty6 = $expandedProjectionNode->getResourceProperty(); $needPop = $this->_pushSegmentForNavigationProperty($projectedProperty6); $this->_executeExpansion($result1); $this->_popSegment($needPop); } } } } }
/** * Check wrapped resource set's resource type or any of the resource type derived * from the this resource type has bag property associated with it. * * @param MetadataQueryProviderWrapper $provider Metadata query provider wrapper * * @return boolean */ public function hasBagProperty(MetadataQueryProviderWrapper $provider) { $arrayToDetectLoop = array(); $hasBagProperty = $this->_resourceSet->getResourceType()->hasBagProperty($arrayToDetectLoop); unset($arrayToDetectLoop); // This will check only the resource type associated with // the resource set, we need to check presence of bag property // in resource type which is derived form this resource type also. if (!$hasBagProperty) { $derivedTypes = $provider->getDerivedTypes($this->_resourceSet->getResourceType()); if (!is_null($derivedTypes)) { foreach ($derivedTypes as $derivedType) { $arrayToDetectLoop = array(); if ($derivedType->hasBagProperty($arrayToDetectLoop)) { $hasBagProperty = true; break; } } } } return $hasBagProperty; }
/** * One can expand a navigation property only if corrosponding resource set is visible * */ public function testExpandWithNonVisibleResourceSet() { try { $northWindMetadata = CreateNorthWindMetadata3::Create(); $queryProvider = new NorthWindQueryProvider2(); $configuration = new DataServiceConfiguration($northWindMetadata); //Make 'Customers' and 'Orders' visible, make 'Order_Details' invisible $configuration->setEntitySetAccessRule('Customers', EntitySetRights::ALL); $configuration->setEntitySetAccessRule('Orders', EntitySetRights::ALL); $metaQueryProverWrapper = new MetadataQueryProviderWrapper($northWindMetadata, $queryProvider, $configuration, false); $customersResourceSetWrapper = $metaQueryProverWrapper->resolveResourceSet('Customers'); $customerResourceType = $customersResourceSetWrapper->getResourceType(); $exceptionThrown = false; try { $projectionTree = ExpandProjectionParser::parseExpandAndSelectClause($customersResourceSetWrapper, $customerResourceType, null, null, null, 'Orders/Order_Details', null, $metaQueryProverWrapper); } catch (ODataException $odataException) { $exceptionThrown = true; $this->assertStringEndsWith("(Check the resource set of the navigation property 'Order_Details' is visible)", $odataException->getMessage()); } if (!$exceptionThrown) { $this->fail('An expected ODataException for navigation to invisible resource set has not been thrown'); } } catch (\Exception $exception) { $this->fail('An unexpected Exception has been raised' . $exception->getMessage()); } }
/** * If last sub path segment specified in the select clause does not appear in the prjection tree, * then parser will create 'ProjectionNode' for them */ public function testPrjectionNodeCreation() { try { $northWindMetadata = CreateNorthWindMetadata3::Create(); $queryProvider = new NorthWindQueryProvider2(); $configuration = new DataServiceConfiguration($northWindMetadata); $configuration->setEntitySetAccessRule('*', EntitySetRights::ALL); $metaQueryProverWrapper = new MetadataQueryProviderWrapper($northWindMetadata, $queryProvider, $configuration, false); $ordersResourceSetWrapper = $metaQueryProverWrapper->resolveResourceSet('Orders'); $orderResourceType = $ordersResourceSetWrapper->getResourceType(); //test selection of properties which is not included in expand clause //1 primitve ('Order_Details/UnitPrice') and 1 link to navigation 'Customer' $projectionTreeRoot = ExpandProjectionParser::parseExpandAndSelectClause($ordersResourceSetWrapper, $orderResourceType, null, null, null, 'Order_Details', 'Order_Details/UnitPrice, Customer', $metaQueryProverWrapper); //expand option is absent $this->assertTrue($projectionTreeRoot->isExpansionSpecified()); //select is applied $this->assertTrue($projectionTreeRoot->isSelectionSpecified()); $this->assertFalse($projectionTreeRoot->canSelectAllImmediateProperties()); $this->assertFalse($projectionTreeRoot->canSelectAllProperties()); //there are 2 child nodes for the root $this->assertEquals(count($projectionTreeRoot->getChildNodes()), 2); //The child nodes one 'ProjectionNode' Customer and one 'ExpandedProjectionNode' for 'Order' $childNodes = $projectionTreeRoot->getChildNodes(); $this->assertTrue(array_key_exists('Order_Details', $childNodes)); $this->assertTrue(array_key_exists('Customer', $childNodes)); $this->assertTrue($childNodes['Order_Details'] instanceof ExpandedProjectionNode); $this->assertTrue($childNodes['Customer'] instanceof ProjectionNode); //'Order_Detials' has a child node $childNodes = $childNodes['Order_Details']->getChildNodes(); $this->assertEquals(count($childNodes), 1); $this->assertTrue(array_key_exists('UnitPrice', $childNodes)); $this->assertTrue($childNodes['UnitPrice'] instanceof ProjectionNode); } catch (\Exception $exception) { $this->fail('An unexpected Exception has been raised' . $exception->getMessage()); } }
/** * test the creation of nextlink from an object. * Test building of link with guid sub-value */ public function testCreationOfNextLink4() { try { $northWindMetadata = CreateNorthWindMetadata3::Create(); $configuration = new DataServiceConfiguration($northWindMetadata); $configuration->setEntitySetAccessRule('*', EntitySetRights::ALL); $metaQueryProverWrapper = new MetadataQueryProviderWrapper($northWindMetadata, null, $configuration, false); $resourceSetWrapper = $metaQueryProverWrapper->resolveResourceSet('Customers'); $resourceType = $resourceSetWrapper->getResourceType(); $orderBy = 'CustomerID, CustomerGuid'; $internalOrderByInfo = OrderByParser::parseOrderByClause($resourceSetWrapper, $resourceType, $orderBy, $metaQueryProverWrapper); $skipToken = "null, guid'05b242e752eb46bd8f0e6568b72cd9a5'"; $internalSkipTokenInfo = SkipTokenParser::parseSkipTokenClause($resourceType, $internalOrderByInfo, $skipToken); $keyObject = $internalSkipTokenInfo->getKeyObject(); $lastObject = new Customer2(); $lastObject->CustomerID = 'ABC'; $lastObject->CustomerGuid = '{05b242e7-52eb-46bd-8f0e-6568b72cd9a5}'; $nextLink = $internalSkipTokenInfo->buildNextPageLink($lastObject); $this->assertEquals($nextLink, "'ABC', guid'%7B05b242e7-52eb-46bd-8f0e-6568b72cd9a5%7D'"); } catch (\Exception $exception) { $this->fail('An unexpected Exception has been raised.' . $exception->getMessage()); } }
public function testGetTypes2() { try { //Try to get all resource sets with non of the resouce sets are visible $configuration = null; $metadataProvider = $this->_createMetadataAndConfiguration2($configuration); $metaQueryProverWrapper = new MetadataQueryProviderWrapper($metadataProvider, null, $configuration, false); $exceptionThrown = false; try { $metaQueryProverWrapper->getTypes(); } catch (ODataException $exception) { $exceptionThrown = true; $this->assertEquals($exception->getMessage(), 'More than one entity type with the name \'Order\' was found. Entity type names must be unique.'); } if (!$exceptionThrown) { $this->fail('An expected ODataException for entity type name repetition has not been thrown'); } } catch (\Exception $exception) { $this->fail('An unexpected Exception has been raised' . $exception->getMessage()); } }