/** * Convert the given primitive value to string. * Note: This method will not handle null primitive value. * * @param ResourceType &$primtiveResourceType Type of the primitive property * whose value need to be converted. * @param mixed $primitiveValue Primitive value to convert. * @param string &$stringValue On return, this parameter will * contain converted value. * * @return void */ private function _primitiveToString(ResourceType &$primtiveResourceType, $primitiveValue, &$stringValue) { $type = $primtiveResourceType->getInstanceType(); if ($type instanceof Boolean) { $stringValue = $primitiveValue === true ? 'true' : 'false'; } else { if ($type instanceof Binary) { $stringValue = base64_encode($primitiveValue); } else { if ($type instanceof OString) { $stringValue = utf8_encode($primitiveValue); } else { $stringValue = strval($primitiveValue); } } } }
/** * To add a navigation property (resource set or resource reference) * to a resource type * * @param ResourceType $resourceType The resource type to add * the resource reference * or resource * reference set property to * @param string $name The name of the * property to add * @param ResourceSet $targetResourceSet The resource set the * resource reference * or reference * set property * ponits to * @param ResourcePropertyKind $resourcePropertyKind The property kind * * @return void */ private function _addReferencePropertyInternal(ResourceType $resourceType, $name, ResourceSet $targetResourceSet, $resourcePropertyKind) { try { $resourceType->getInstanceType()->getProperty($name); } catch (ReflectionException $exception) { throw new InvalidOperationException('Can\'t add a property which does not exist on the instance type.'); } if (!($resourcePropertyKind == ResourcePropertyKind::RESOURCESET_REFERENCE || $resourcePropertyKind == ResourcePropertyKind::RESOURCE_REFERENCE)) { throw new InvalidOperationException('Property kind should be ResourceSetReference or ResourceReference'); } $targetResourceType = $targetResourceSet->getResourceType(); $resourceProperty = new ResourceProperty($name, null, $resourcePropertyKind, $targetResourceType); $resourceType->addProperty($resourceProperty); //Create instance of AssociationSet for this relationship $sourceResourceSet = $resourceType->getCustomState(); if (is_null($sourceResourceSet)) { throw new InvalidOperationException('Failed to retrieve the custom state from ' . $resourceType->getName()); } //Customer_Orders_Orders, Order_Customer_Customers //(source type::name _ source property::name _ target set::name) $assoicationSetKey = $resourceType->getName() . '_' . $name . '_' . $targetResourceSet->getName(); $associationSet = new ResourceAssociationSet($assoicationSetKey, new ResourceAssociationSetEnd($sourceResourceSet, $resourceType, $resourceProperty), new ResourceAssociationSetEnd($targetResourceSet, $targetResourceSet->getResourceType(), null)); $this->associationSets[$assoicationSetKey] = $associationSet; }
/** * Get the instance type. If the property is of kind 'Complex', * 'ResourceReference' or 'ResourceSetReference' then this function returns * refernece to ReflectionClass instance for the type. If the property of * kind 'Primitive' then this function returns ITYpe instance for the type. * * @return ReflectionClass/IType */ public function getInstanceType() { return $this->_propertyResourceType->getInstanceType(); }
/** * test ResourceType class */ public function testResourceType() { try { $exceptionThrown = false; try { ResourceType::getPrimitiveResourceType(TypeCode::VOID); } catch (\InvalidArgumentException $exception) { $exceptionThrown = true; $this->assertStringEndsWith('is not a valid EdmPrimitiveType Enum value', $exception->getMessage()); } if (!$exceptionThrown) { $this->fail('An expected InvalidArgumentException for \'EdmPrimitiveType\' has not been raised'); } $int16ResType = new ResourceType(new Int16(), ResourceTypeKind::PRIMITIVE, 'Int16', 'Edm'); $exceptionThrown = false; try { $int32ResType = new ResourceType(new Int32(), ResourceTypeKind::PRIMITIVE, 'Int32', 'Edm', $int16ResType); } catch (\InvalidArgumentException $exception) { $this->AssertEquals('Primitive type cannot have base type', $exception->getMessage()); $exceptionThrown = true; } if (!$exceptionThrown) { $this->fail('An expected InvalidArgumentException for \'basetype\' has not been raised'); } $exceptionThrown = false; try { $int32ResType = new ResourceType(new Int32(), ResourceTypeKind::PRIMITIVE, 'Int32', 'Edm', null, true); } catch (\InvalidArgumentException $exception) { $this->AssertEquals('Primitive type cannot be abstract', $exception->getMessage()); $exceptionThrown = true; } if (!$exceptionThrown) { $this->fail('An expected InvalidArgumentException for \'abstract\' has not been raised'); } $exceptionThrown = false; try { $int32ResType = new ResourceType(null, ResourceTypeKind::PRIMITIVE, 'Int32', 'Edm'); } catch (\InvalidArgumentException $exception) { $this->assertStringEndsWith('should be an \'IType\' implementor instance', $exception->getMessage()); $exceptionThrown = true; } if (!$exceptionThrown) { $this->fail('An expected InvalidArgumentException for \'IType\' has not been raised'); } $exceptionThrown = false; try { $customerResType = new ResourceType(null, ResourceTypeKind::ENTITY, 'Customer', 'Northwind'); } catch (\InvalidArgumentException $exception) { $this->assertStringEndsWith('argument should be an \'ReflectionClass\' instance', $exception->getMessage()); $exceptionThrown = true; } if (!$exceptionThrown) { $this->fail('An expected InvalidArgumentException for \'ReflectionClass\' has not been raised'); } $customerResType = new ResourceType(new ReflectionClass('Customer2'), ResourceTypeKind::ENTITY, 'Customer', 'Northwind'); $this->AssertEquals($customerResType->getName(), 'Customer'); $this->AssertEquals($customerResType->getFullName(), 'Northwind.Customer'); $this->assertTrue($customerResType->getInstanceType() instanceof \ReflectionClass); $this->AssertEquals($customerResType->getNamespace(), 'Northwind'); $this->AssertEquals($customerResType->getResourceTypeKind(), ResourceTypeKind::ENTITY); $this->AssertEquals($customerResType->isMediaLinkEntry(), false); $exceptionThrown = false; try { $customerResType->validateType(); } catch (InvalidOperationException $exception) { $this->assertStringEndsWith('Please make sure the key properties are defined for this entity type', $exception->getMessage()); $exceptionThrown = true; } if (!$exceptionThrown) { $this->fail('An expected InvalidOperationException for \'No key defined\' has not been raised'); } $exceptionThrown = false; try { $int32ResourceType = ResourceType::getPrimitiveResourceType(EdmPrimitiveType::INT32); $primitiveResourceType = ResourceType::getPrimitiveResourceType(EdmPrimitiveType::STRING); $testProperty = new ResourceProperty('test', null, ResourcePropertyKind::PRIMITIVE, $primitiveResourceType); $int32ResourceType->addProperty($testProperty); } catch (InvalidOperationException $exception) { $this->assertStringEndsWith('ResourceType instances with a ResourceTypeKind equal to \'Primitive\'', $exception->getMessage()); $exceptionThrown = true; } if (!$exceptionThrown) { $this->fail('An expected InvalidOperationException for \'property on primitive\' has not been raised'); } $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); $addressResType = new ResourceType(new ReflectionClass('Address2'), ResourceTypeKind::COMPLEX, 'Address', 'Northwind'); $exceptionThrown = false; try { $booleanResourceType = ResourceType::getPrimitiveResourceType(EdmPrimitiveType::BOOLEAN); $isPrimaryPrimProperty = new ResourceProperty('IsPrimary', null, ResourcePropertyKind::PRIMITIVE | ResourcePropertyKind::KEY, $booleanResourceType); $addressResType->addProperty($isPrimaryPrimProperty); } catch (InvalidOperationException $exception) { $this->assertStringEndsWith('ResourceType instances with a ResourceTypeKind equal to \'EntityType\'', $exception->getMessage()); $exceptionThrown = true; } if (!$exceptionThrown) { $this->fail('An expected InvalidOperationException for \'Key on non-entity\' has not been raised'); } $booleanResourceType = ResourceType::getPrimitiveResourceType(EdmPrimitiveType::BOOLEAN); $isPrimaryPrimProperty = new ResourceProperty('IsPrimary', null, ResourcePropertyKind::PRIMITIVE, $booleanResourceType); $addressResType->addProperty($isPrimaryPrimProperty); $exceptionThrown = false; try { $addressResType->addProperty($isPrimaryPrimProperty); } catch (InvalidOperationException $exception) { $this->assertStringStartsWith('Property with same name \'IsPrimary\' already exists in type \'Address\'', $exception->getMessage()); $exceptionThrown = true; } if (!$exceptionThrown) { $this->fail('An expected InvalidArgumentException for \'Property duplication\' has not been raised'); } $exceptionThrown = false; try { $addressResType->setMediaLinkEntry(true); } catch (InvalidOperationException $exception) { $exceptionThrown = true; $this->assertStringStartsWith('Cannot apply the HasStreamAttribute', $exception->getMessage()); } if (!$exceptionThrown) { $this->fail('An expected InvalidOperationException for \'MLE on non-entity\' has not been raised'); } $customerAdrComplexType = new ResourceProperty('Address', null, ResourcePropertyKind::COMPLEX_TYPE, $addressResType); $customerResType->addProperty($customerIDPrimProperty); $customerResType->addProperty($customerNamePrimProperty); $customerResType->addProperty($ratingPrimProperty); $customerResType->addProperty($customerAdrComplexType); $customerResType->validateType(); $customerProperties = $customerResType->getPropertiesDeclaredOnThisType(); $this->AssertEquals(count($customerProperties), 4); $customerAllProperties = $customerResType->getAllProperties(); $this->AssertEquals(count($customerProperties), count($customerAllProperties)); $keys = array('CustomerID', 'CustomerName', 'Rating', 'Address'); $i = 0; foreach ($customerAllProperties as $key => $customerProperty) { $this->AssertEquals($key, $keys[$i++]); } $entityKeys = array('CustomerID'); $customerKeyProperties = $customerResType->getKeyProperties(); $i = 0; foreach ($customerKeyProperties as $key => $customerKeyProperty) { $this->AssertEquals($key, $entityKeys[$i++]); } $this->AssertEquals(count($customerResType->getETagProperties()), 0); $this->AssertEquals($customerResType->tryResolvePropertyTypeByName('PropNotExists'), null); $property = $customerResType->tryResolvePropertyTypeByName('CustomerName'); $this->AssertNotEquals($property, null); $this->AssertEquals($property->getName(), 'CustomerName'); $employeeResType = new ResourceType(new ReflectionClass('Employee2'), ResourceTypeKind::ENTITY, 'Employee', 'Northwind'); $stringResourceType = ResourceType::getPrimitiveResourceType(EdmPrimitiveType::STRING); $employeeResType->addProperty(new ResourceProperty('EmployeeID', null, ResourcePropertyKind::PRIMITIVE | ResourcePropertyKind::KEY, $stringResourceType)); $employeeResType->addProperty(new ResourceProperty('Emails', null, ResourcePropertyKind::PRIMITIVE | ResourcePropertyKind::BAG, $stringResourceType)); $employeeResType->setMediaLinkEntry(true); $employeeResType->addNamedStream(new ResourceStreamInfo('ThumNail_64X64')); $exceptionThrown = false; try { $employeeResType->addNamedStream(new ResourceStreamInfo('ThumNail_64X64')); } catch (InvalidOperationException $exception) { $exceptionThrown = true; $this->assertStringStartsWith('Named stream with the name \'ThumNail_64X64\' already exists in type \'Employee\'', $exception->getMessage()); } if (!$exceptionThrown) { $this->fail('An expected InvalidOperationException for \'named stream duplication\' has not been raised'); } $this->AssertEquals($employeeResType->hasNamedStream(), true); $b = array(); $this->AssertEquals($employeeResType->hasBagProperty($b), true); $namedStreams = $employeeResType->getAllNamedStreams(); $this->AssertEquals(count($namedStreams), 1); $this->AssertTrue(array_key_exists('ThumNail_64X64', $namedStreams)); $name = $employeeResType->tryResolveNamedStreamByName('ThumNail_64X64')->getName(); $this->AssertEquals($name, 'ThumNail_64X64'); } catch (\Exception $exception) { $this->fail('An unexpected Exception has been raised' . $exception->getMessage()); } }
/** * This function perform the following tasks with the help of internal helper * functions * (1) Read the orderby clause and perform basic syntax errors * (2) Build 'Order By Tree', creates anonymous sorter function for each leaf * node and check for error * (3) Build 'OrderInfo' structure, holds information about the navigation * properties used in the orderby clause (if any) and orderby path if * IDSQP implementor want to perform sorting * (4) Build top level anonymous sorter function * (4) Release resources hold by the 'Order By Tree' * (5) Create 'InternalOrderInfo' structure, which wraps 'OrderInfo' and top * level sorter function * * @param ResourceSetWrapper $resourceSetWrapper ResourceSetWrapper for * the resource targetted * by resource path. * @param ResourceType $resourceType ResourceType for the * resource targetted * by resource path. * @param string $orderBy The orderby clause. * @param MetadataQueryProviderWrapper $providerWrapper Reference to the * wrapper for IDSQP * and IDSMP impl. * * @return InternalOrderByInfo * * @throws ODataException If any error occur while parsing orderby clause */ public static function parseOrderByClause(ResourceSetWrapper $resourceSetWrapper, ResourceType $resourceType, $orderBy, MetadataQueryProviderWrapper $providerWrapper) { $orderByParser = new OrderByParser($providerWrapper); try { $orderByParser->_dummyObject = $resourceType->getInstanceType()->newInstance(); } catch (\ReflectionException $reflectionException) { throw ODataException::createInternalServerError(Messages::orderByParserFailedToCreateDummyObject()); } $orderByParser->_rootOrderByNode = new OrderByRootNode($resourceSetWrapper, $resourceType); $orderByPathSegments = $orderByParser->_readOrderBy($orderBy); $orderByParser->_buildOrderByTree($orderByPathSegments); $orderByParser->_createOrderInfo($orderByPathSegments); $orderByParser->_generateTopLevelComparisonFunction(); //Recursively release the resources $orderByParser->_rootOrderByNode->free(); //creates internal order info wrapper $internalOrderInfo = new InternalOrderByInfo($orderByParser->_orderByInfo, $orderByParser->_comparisonFunctions, $orderByParser->_topLevelComparisonFunction, $orderByParser->_dummyObject); unset($orderByParser->_orderByInfo); unset($orderByParser->_topLevelComparisonFunction); return $internalOrderInfo; }