/** * Get the Multiplicity of the relationship end * * @return string */ public function getMultiplicity() { if (!is_null($this->_fromProperty) && $this->_fromProperty->getKind() == ResourcePropertyKind::RESOURCE_REFERENCE) { return ODataConstants::ZERO_OR_ONE; } return ODataConstants::MANY; }
public function testGetResourceAssociationSetEndIsNotVisible() { $fakePropName = "Fake Prop"; Phockito::when($this->mockResourceProperty->getName())->return($fakePropName); Phockito::when($this->mockResourceType->resolvePropertyDeclaredOnThisType($fakePropName))->return($this->mockResourceProperty); $fakeTypeName = "Fake Type"; Phockito::when($this->mockResourceType->getName())->return($fakeTypeName); $fakeSetName = "Fake Set"; Phockito::when($this->mockResourceSet->getName())->return($fakeSetName); Phockito::when($this->mockResourceSet->getResourceType())->return($this->mockResourceType); Phockito::when($this->mockResourceSet2->getResourceType())->return($this->mockResourceType2); //Indicate the resource set is visible Phockito::when($this->mockServiceConfig->getEntitySetAccessRule($this->mockResourceSet))->return(EntitySetRights::READ_SINGLE); //Indicate the resource set is visible Phockito::when($this->mockServiceConfig->getEntitySetAccessRule($this->mockResourceSet2))->return(EntitySetRights::NONE); Phockito::when($this->mockMetadataProvider->getResourceAssociationSet($this->mockResourceSet, $this->mockResourceType, $this->mockResourceProperty))->return($this->mockResourceAssociationSet); Phockito::when($this->mockResourceAssociationSet->getResourceAssociationSetEnd($this->mockResourceSet, $this->mockResourceType, $this->mockResourceProperty))->return($this->mockResourceAssociationSetEnd); Phockito::when($this->mockResourceAssociationSet->getRelatedResourceAssociationSetEnd($this->mockResourceSet, $this->mockResourceType, $this->mockResourceProperty))->return($this->mockResourceAssociationSetEnd); Phockito::when($this->mockResourceAssociationSetEnd->getResourceSet())->return($this->mockResourceSet2); Phockito::when($this->mockResourceAssociationSetEnd->getResourceType())->return($this->mockResourceType2); $wrapper = $this->getMockedWrapper(); $actual = $wrapper->getResourceAssociationSet($this->mockResourceSet, $this->mockResourceType, $this->mockResourceProperty); $this->assertNull($actual); }
/** * Gets the ResourceAssociationType instance for the given * ResourceAssociationSet and one of it's end. * * This function first searches the ResourceAssociationType cache, * if found return it otherwise create the Association type for the given * association set, cache and return it. * * Creation of ResourceAssociationType includes two sub-tasks: * 1. Deciding name of 'ResourceAssociationType' * (see the function _getAssociationTypeName) * 2. Deciding names for two 'ResourceAssociationTypeEnd' of the * 'ResourceAssociationType' * Refer ./AssociationSetAndTypeNamingRules.txt for naming rules. * * @param ResourceAssociationSet $resourceAssociationSet Association set to get the association type * @param ResourceSetWrapper $resourceSet Resource set for one of the ends of given association set * @param ResourceType $resourceType Resource type for one of the ends of given association set * @param ResourceProperty $navigationProperty Resource property for one of the ends of given association set * * * @return ResourceAssociationType The association type for the given association set * */ private function _getResourceAssociationType(ResourceAssociationSet $resourceAssociationSet, ResourceSetWrapper $resourceSet, ResourceType $resourceType, ResourceProperty $navigationProperty) { $resourceTypeNamespace = $this->getResourceTypeNamespace($resourceType); $resourceAssociationTypesInNamespace =& $this->getResourceAssociationTypesForNamespace($resourceTypeNamespace); $associationTypeLookupKey = $resourceType->getName() . '_' . $navigationProperty->getName(); if (array_key_exists($associationTypeLookupKey, $resourceAssociationTypesInNamespace)) { return $resourceAssociationTypesInNamespace[$associationTypeLookupKey]; } //Generate resource association type end names //Refer ./AssociationSetAndTypeNamingRules.txt $associationTypeEnd1Name = $associationTypeEnd2Name = null; $isBiDirectional = $resourceAssociationSet->isBidirectional(); if ($isBiDirectional) { $associationTypeEnd1Name = $resourceAssociationSet->getEnd1()->getResourceType()->getName() . '_' . $resourceAssociationSet->getEnd1()->getResourceProperty()->getName(); $associationTypeEnd2Name = $resourceAssociationSet->getEnd2()->getResourceType()->getName() . '_' . $resourceAssociationSet->getEnd2()->getResourceProperty()->getName(); } else { if (!is_null($resourceAssociationSet->getEnd1()->getResourceProperty())) { $associationTypeEnd1Name = $resourceAssociationSet->getEnd1()->getResourceType()->getName(); $associationTypeEnd2Name = $resourceAssociationSet->getEnd1()->getResourceProperty()->getName(); } else { $associationTypeEnd1Name = $resourceAssociationSet->getEnd2()->getResourceProperty()->getName(); $associationTypeEnd2Name = $resourceAssociationSet->getEnd2()->getResourceType()->getName(); } } //Generate resource association type name //Refer ./AssociationSetAndTypeNamingRules.txt $resourceAssociationTypeName = $this->_getAssociationTypeName($resourceAssociationSet); //Create and cache the association type $resourceAssociationType = new ResourceAssociationType($resourceAssociationTypeName, $resourceTypeNamespace, new ResourceAssociationTypeEnd($associationTypeEnd1Name, $resourceAssociationSet->getEnd1()->getResourceType(), $resourceAssociationSet->getEnd1()->getResourceProperty(), $resourceAssociationSet->getEnd2()->getResourceProperty()), new ResourceAssociationTypeEnd($associationTypeEnd2Name, $resourceAssociationSet->getEnd2()->getResourceType(), $resourceAssociationSet->getEnd2()->getResourceProperty(), $resourceAssociationSet->getEnd1()->getResourceProperty())); $resourceAssociationTypesInNamespace[$associationTypeLookupKey] = $resourceAssociationType; if ($isBiDirectional) { $relatedAssociationSetEnd = $resourceAssociationSet->getRelatedResourceAssociationSetEnd($resourceSet->getResourceSet(), $resourceType, $navigationProperty); $relatedEndLookupKey = $relatedAssociationSetEnd->getResourceType()->getName() . '_' . $relatedAssociationSetEnd->getResourceProperty()->getName(); $resourceAssociationTypesInNamespace[$relatedEndLookupKey] = $resourceAssociationType; } return $resourceAssociationType; }
/** * Get related resource for a resource * * @param ResourceSet $sourceResourceSet The source resource set * @param mixed $sourceEntityInstance The source resource * @param ResourceSet $targetResourceSet The resource set of * the navigation property * @param ResourceProperty $targetProperty The navigation property to be * retrieved * * @return object|null The related resource if exists else null */ public function getRelatedResourceReference(ResourceSet $sourceResourceSet, $sourceEntityInstance, ResourceSet $targetResourceSet, ResourceProperty $targetProperty) { $result = null; $srcClass = get_class($sourceEntityInstance); $navigationPropName = $targetProperty->getName(); if ($srcClass === 'Order') { if ($navigationPropName === 'Customer') { if (empty($sourceEntityInstance->CustomerID)) { $result = null; } else { $query = "SELECT * FROM Customers WHERE CustomerID = '{$sourceEntityInstance->CustomerID}'"; $stmt = sqlsrv_query($this->_connectionHandle, $query); if ($stmt === false) { $errorAsString = self::_getSQLSRVError(); throw ODataException::createInternalServerError($errorAsString); } if (!sqlsrv_has_rows($stmt)) { $result = null; } $result = $this->_serializeCustomer(sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)); } } else { die('Customer does not have navigation porperty with name: ' . $navigationPropName); } } else { if ($srcClass === 'Order_Details') { if ($navigationPropName === 'Order') { if (empty($sourceEntityInstance->OrderID)) { $result = null; } else { $query = "SELECT * FROM Orders WHERE OrderID = {$sourceEntityInstance->OrderID}"; $stmt = sqlsrv_query($this->_connectionHandle, $query); if ($stmt === false) { $errorAsString = self::_getSQLSRVError(); throw ODataException::createInternalServerError($errorAsString); } if (!sqlsrv_has_rows($stmt)) { $result = null; } $result = $this->_serializeOrder(sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)); } } else { die('Order_Details does not have navigation porperty with name: ' . $navigationPropName); } } } return $result; }
/** * Write primitive property facets. * * @param ResourceProperty $primitveProperty primitive property * * @return void */ private function _writePrimitivePropertyFacets(ResourceProperty $primitveProperty) { $nullable = true; if ($primitveProperty->isKindOf(ResourcePropertyKind::KEY)) { $nullable = false; } $this->_xmlWriter->writeAttribute(ODataConstants::NULLABLE, $nullable ? "true" : "false"); }
/** * Writes a primitive value and related information to the given * ODataProperty instance. * * @param mixed &$primitiveValue The primitive value to write. * @param ResourceProperty &$resourceProperty The metadata of the primitive * property value. * @param ODataProperty &$odataProperty ODataProperty instance to which * the primitive value and related * information to write out. * * @throws ODataException If given value is not primitive. * * @return void */ private function _writePrimitiveValue(&$primitiveValue, ResourceProperty &$resourceProperty, ODataProperty &$odataProperty) { if (is_object($primitiveValue)) { //TODO ERROR: The property 'PropertyName' //is defined as primitive type but value is an object } $odataProperty->name = $resourceProperty->getName(); $odataProperty->typeName = $resourceProperty->getInstanceType()->getFullTypeName(); if (is_null($primitiveValue)) { $odataProperty->value = null; } else { $resourceType = $resourceProperty->getResourceType(); $this->_primitiveToString($resourceType, $primitiveValue, $odataProperty->value); } }
/** * Pushes a segment for the current navigation property being written out. * Note: Refer 'ObjectModelSerializerNotes.txt' for more details about * 'Segment Stack' and this method. * Note: Calls to this method should be balanced with calls to popSegment. * * @param ResourceProperty &$resourceProperty Current navigation property * being written out * * @return bool true if a segment was pushed, false otherwise * * @throws InvalidOperationException If this function invoked with non-navigation * property instance. */ private function _pushSegmentForNavigationProperty(ResourceProperty &$resourceProperty) { if ($resourceProperty->getTypeKind() == ResourceTypeKind::ENTITY) { $this->assert(!empty($this->_segmentNames), '!is_empty($this->_segmentNames'); $currentResourceSetWrapper = $this->_getCurrentResourceSetWrapper(); $currentResourceType = $currentResourceSetWrapper->getResourceType(); $currentResourceSetWrapper = $this->service->getProvidersWrapper()->getResourceSetWrapperForNavigationProperty($currentResourceSetWrapper, $currentResourceType, $resourceProperty); $this->assert(!is_null($currentResourceSetWrapper), '!null($currentResourceSetWrapper)'); return $this->_pushSegment($resourceProperty->getName(), $currentResourceSetWrapper); } else { throw new InvalidOperationException('pushSegmentForNavigationProperty should not be called with non-entity type'); } }
/** * Gets the ResourceAssociationSet instance for the given source * association end. * * @param ResourceSet $sourceResourceSet Resource set * of the source * association end * @param ResourceType $sourceResourceType Resource type of the source * association end * @param ResourceProperty $targetResourceProperty Resource property of * the source * association end * * @return ResourceAssociationSet */ public function getResourceAssociationSet(ResourceSet $sourceResourceSet, ResourceType $sourceResourceType, ResourceProperty $targetResourceProperty) { //e.g. //ResourceSet => Representing 'Customers' entity set //ResourceType => Representing'Customer' entity type //ResourceProperty => Representing 'Orders' property //We have created ResourceAssoicationSet while adding //ResourceSetReference or ResourceReference //and kept in $this->associationSets //$metadata->addResourceSetReferenceProperty( // $customersEntityType, // 'Orders', // $ordersResourceSet // ); $targetResourceSet = $targetResourceProperty->getResourceType()->getCustomState(); if (is_null($targetResourceSet)) { throw new InvalidOperationException('Failed to retrieve the custom state from ' . $targetResourceProperty->getResourceType()->getName()); } //Customer_Orders_Orders, Order_Customer_Customers $key = $sourceResourceType->getName() . '_' . $targetResourceProperty->getName() . '_' . $targetResourceSet->getName(); if (array_key_exists($key, $this->associationSets)) { return $this->associationSets[$key]; } return null; }
public function testResourceProperty() { $addressResType = new ResourceType(new \ReflectionClass('UnitTests\\POData\\Facets\\NorthWind1\\Address2'), ResourceTypeKind::COMPLEX, 'Address', 'Northwind'); $booleanResourcetype = ResourceType::getPrimitiveResourceType(EdmPrimitiveType::BOOLEAN); $isPrimaryPrimProperty = new ResourceProperty('IsPrimary', null, ResourcePropertyKind::PRIMITIVE, $booleanResourcetype); $addressResType->addProperty($isPrimaryPrimProperty); try { $addressComplexProperty = new ResourceProperty('Address', null, ResourcePropertyKind::COMPLEX_TYPE | ResourcePropertyKind::KEY, $addressResType); $this->fail('An expected InvalidArgumentException for \'invalid ResourcePropertyKind\' has not been raised'); } catch (\InvalidArgumentException $exception) { $this->assertStringEndsWith('not a valid ResourcePropertyKind enum value or valid combination of ResourcePropertyKind enum values', $exception->getMessage()); } $stringResourceType = ResourceType::getPrimitiveResourceType(EdmPrimitiveType::STRING); try { $addressComplexProperty = new ResourceProperty('Address', null, ResourcePropertyKind::COMPLEX_TYPE, $stringResourceType); $this->fail('An expected InvalidArgumentException for \'Property and ResourceType kind mismatch\' has not been raised'); } catch (\InvalidArgumentException $exception) { $this->assertStringStartsWith('The \'$kind\' parameter does not match with the type of the resource type', $exception->getMessage()); } $customerResType = new ResourceType(new \ReflectionClass('UnitTests\\POData\\Facets\\NorthWind1\\Customer2'), ResourceTypeKind::ENTITY, 'Customer', 'Northwind'); $stringResourceType = ResourceType::getPrimitiveResourceType(EdmPrimitiveType::STRING); $customerIDPrimProperty = new ResourceProperty('CustomerID', null, ResourcePropertyKind::PRIMITIVE | ResourcePropertyKind::KEY, $stringResourceType); $customerNamePrimProperty = new ResourceProperty('CustomerName', null, ResourcePropertyKind::PRIMITIVE, $stringResourceType); $intResourceType = ResourceType::getPrimitiveResourceType(EdmPrimitiveType::INT32); $ratingPrimProperty = new ResourceProperty('Rating', null, ResourcePropertyKind::PRIMITIVE, $intResourceType); $customerResType->addProperty($customerIDPrimProperty); $customerResType->addProperty($customerNamePrimProperty); $customerResType->addProperty($ratingPrimProperty); $this->assertTrue($customerIDPrimProperty->isKindOf(ResourcePropertyKind::KEY)); $this->assertTrue($customerIDPrimProperty->isKindOf(ResourcePropertyKind::PRIMITIVE)); $customerReferenceSetProperty = new ResourceProperty('Customers', null, ResourcePropertyKind::RESOURCESET_REFERENCE, $customerResType); $this->assertEquals($customerReferenceSetProperty->getName(), 'Customers'); $this->assertEquals($customerReferenceSetProperty->getKind(), ResourcePropertyKind::RESOURCESET_REFERENCE); $this->assertEquals($customerReferenceSetProperty->getInstanceType() instanceof \ReflectionClass, true); $this->assertEquals($customerReferenceSetProperty->getResourceType()->getName(), 'Customer'); $this->assertEquals($customerReferenceSetProperty->getTypeKind(), ResourceTypeKind::ENTITY); $this->assertFalse($customerReferenceSetProperty->isKindOf(ResourcePropertyKind::RESOURCE_REFERENCE)); }
/** * Get the resource type of the property hold by this expression * * @return ResourceType */ public function getResourceType() { return $this->resourceProperty->getResourceType(); }
/** * To check this relationship belongs to a specific resource set, type * and property * * @param ResourceSet $resourceSet Resource set for the association * end * @param ResourceType $resourceType Resource type for the association * end * @param ResourceProperty $resourceProperty Resource property for the * association end * * @return boolean */ public function isBelongsTo(ResourceSet $resourceSet, ResourceType $resourceType, ResourceProperty $resourceProperty) { return strcmp($resourceSet->getName(), $this->_resourceSet->getName()) == 0 && $this->_resourceType->isAssignableFrom($resourceType) && (is_null($resourceProperty) && is_null($this->_resourceProperty) || !is_null($resourceProperty) && !is_null($this->_resourceProperty) && strcmp($resourceProperty->getName(), $this->_resourceProperty->getName()) == 0); }
/** * Get related resource for a resource * * @param ResourceSet $sourceResourceSet The source resource set * @param mixed $sourceEntityInstance The source resource * @param ResourceSet $targetResourceSet The resource set of * the navigation property * @param ResourceProperty $targetProperty The navigation property to be * retrieved * * @return object|null The related resource if exists else null */ public function getRelatedResourceReference(ResourceSet $sourceResourceSet, $sourceEntityInstance, ResourceSet $targetResourceSet, ResourceProperty $targetProperty) { $result = null; $srcClass = get_class($sourceEntityInstance); $navigationPropName = $targetProperty->getName(); switch (true) { case $srcClass == 'Post': if ($navigationPropName == 'User') { $query = "SELECT * FROM `wp_users` WHERE ID = {$sourceEntityInstance->Author}"; $stmt = mysql_query($query); $stmt = mysql_query($query); $data = mysql_fetch_assoc($stmt); $result = $this->_serializeUser($data); if ($stmt === false) { die(mysql_error()); } if (!mysql_num_rows($stmt)) { $result = null; } } else { die('Post does not have navigation porperty with name: ' . $navigationPropName); } break; case $srcClass == 'Comment': if ($navigationPropName == 'User') { $query = "SELECT * FROM `wp_users` WHERE ID = {$sourceEntityInstance->UserID}"; $stmt = mysql_query($query); if ($stmt === false) { die(mysql_error()); } if (!mysql_num_rows($stmt)) { $result = null; } $data = mysql_fetch_assoc($stmt); $result = $this->_serializeUser($data); } elseif ($navigationPropName == 'Post') { $query = "SELECT * FROM `wp_posts` WHERE" . " wp_posts.post_type = 'post'" . " AND wp_posts.post_status = 'publish'" . " AND wp_posts.ID = {$sourceEntityInstance->PostID}"; $stmt = mysql_query($query); if ($stmt === false) { die(mysql_error()); } if (!mysql_num_rows($stmt)) { $result = null; } $data = mysql_fetch_assoc($stmt); $result = $this->_serializePost($data); } else { die('Comment does not have navigation porperty with name: ' . $navigationPropName); } break; } mysql_free_result($stmt); return $result; }
/** * Gets the resource type on which the resource property is declared on, * If property is not declared in the given resource type, then this * function drill down to the inheritance hierarchy of the given resource * type to find out the base class in which the property is declared * * @param ResourceType $resourceType The resource type to start looking * @param ResourceProperty $resourceProperty The resource property in question * * @return ResourceType|null Returns reference to the ResourceType on which * the $resourceProperty is declared, NULL if * $resourceProperty is not declared anywhere * in the inheritance hierarchy */ private function _getResourceTypeWherePropertyIsDeclared(ResourceType $resourceType, ResourceProperty $resourceProperty) { $type = $resourceType; while ($type !== null) { if ($type->resolvePropertyDeclaredOnThisType($resourceProperty->getName()) !== null) { break; } $type = $type->getBaseType(); } return $type; }
/** * Gets instance type of the ResourceProperty instance corresponding to * this sub path segment If this sub path segment is last segment then * this function returns 'IType' otherwise 'ReflectionClass'. * * @return ReflectionClass|IType */ public function getInstanceType() { return $this->_resourceProperty->getInstanceType(); }
/** * Add a property belongs to this resource type instance * * @param ResourceProperty $property Property to add * * @throws InvalidOperationException * @return void */ public function addProperty(ResourceProperty $property) { if ($this->_resourceTypeKind == ResourceTypeKind::PRIMITIVE) { throw new InvalidOperationException(Messages::resourceTypeNoAddPropertyForPrimitive()); } $name = $property->getName(); foreach (array_keys($this->_propertiesDeclaredOnThisType) as $propertyName) { if (strcasecmp($propertyName, $name) == 0) { throw new InvalidOperationException(Messages::resourceTypePropertyWithSameNameAlreadyExists($propertyName, $this->_name)); } } if ($property->isKindOf(ResourcePropertyKind::KEY)) { if ($this->_resourceTypeKind != ResourceTypeKind::ENTITY) { throw new InvalidOperationException(Messages::resourceTypeKeyPropertiesOnlyOnEntityTypes()); } if ($this->_baseType != null) { throw new InvalidOperationException(Messages::resourceTypeNoKeysInDerivedTypes()); } } if ($property->isKindOf(ResourcePropertyKind::ETAG) && $this->_resourceTypeKind != ResourceTypeKind::ENTITY) { throw new InvalidOperationException(Messages::resourceTypeETagPropertiesOnlyOnEntityTypes()); } //Check for Base class properties $this->_propertiesDeclaredOnThisType[$name] = $property; // Set $this->_allProperties to null, this is very important because the // first call to getAllProperties will initilaize $this->_allProperties, // further call to getAllProperties will not reinitialize _allProperties // so if addProperty is called after calling getAllProperties then the // property just added will not be reflected in $this->_allProperties unset($this->_allProperties); $this->_allProperties = array(); }