diff --git a/CHANGELOG.md b/CHANGELOG.md index 33071ba5df..bb9ad34780 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added +- Added missing mappings in PHP for uint8 and int8. [#1473](https://github.com/microsoft/kiota/pull/1473) ### Changed diff --git a/abstractions/php/src/Serialization/ParseNode.php b/abstractions/php/src/Serialization/ParseNode.php index 3bd6527ee8..70cae99e3e 100644 --- a/abstractions/php/src/Serialization/ParseNode.php +++ b/abstractions/php/src/Serialization/ParseNode.php @@ -5,7 +5,6 @@ use DateInterval; use DateTime; use Microsoft\Kiota\Abstractions\Enum; -use Microsoft\Kiota\Abstractions\Types\Byte; use Microsoft\Kiota\Abstractions\Types\Date; use Microsoft\Kiota\Abstractions\Types\Time; use Psr\Http\Message\StreamInterface; @@ -93,18 +92,6 @@ public function getTimeValue(): ?Time; */ public function getEnumValue(string $targetEnum): ?Enum; - /** - * @param string $targetClass - * @return Enum[]|null - */ - public function getCollectionOfEnumValues(string $targetClass): ?array; - - /** - * Return a byte value. - * @return Byte|null - */ - public function getByteValue(): ?Byte; - /** * Get a Stream from node. * @return StreamInterface|null diff --git a/abstractions/php/src/Serialization/SerializationWriter.php b/abstractions/php/src/Serialization/SerializationWriter.php index cd656cc6f6..f61b26589a 100644 --- a/abstractions/php/src/Serialization/SerializationWriter.php +++ b/abstractions/php/src/Serialization/SerializationWriter.php @@ -4,7 +4,6 @@ use DateInterval; use DateTime; use Microsoft\Kiota\Abstractions\Enum; -use Microsoft\Kiota\Abstractions\Types\Byte; use Microsoft\Kiota\Abstractions\Types\Date; use Microsoft\Kiota\Abstractions\Types\Time; use Psr\Http\Message\StreamInterface; @@ -122,13 +121,6 @@ public function writeTimeValue(?string $key, ?Time $value): void; * @return void */ public function writeDateIntervalValue(?string $key, ?DateInterval $value): void; - /** - * Write a byte value. - * @param string|null $key - * @param Byte|null $value - * @return void - */ - public function writeByteValue(?string $key, ?Byte $value): void; /** * @param string|null $key diff --git a/abstractions/php/src/Types/Byte.php b/abstractions/php/src/Types/Byte.php deleted file mode 100644 index 817455bd3f..0000000000 --- a/abstractions/php/src/Types/Byte.php +++ /dev/null @@ -1,32 +0,0 @@ - 255) { - throw new InvalidArgumentException("Byte should be a value between 0-255 inclusive {$value} given"); - } - $this->value = $value; - } - - public function __toString(): string - { - return (string)$this->value; - } -} \ No newline at end of file diff --git a/serialization/php/json/composer.json b/serialization/php/json/composer.json index b8ae6e9dd0..0f35f53ba6 100644 --- a/serialization/php/json/composer.json +++ b/serialization/php/json/composer.json @@ -12,7 +12,10 @@ "repositories": [ { "type": "path", - "url": "../../../abstractions/php" + "url": "../../../abstractions/php", + "options": { + "symlink": false + } } ], "autoload": { diff --git a/serialization/php/json/src/JsonParseNode.php b/serialization/php/json/src/JsonParseNode.php index a0236a7def..aeaa90cb0a 100644 --- a/serialization/php/json/src/JsonParseNode.php +++ b/serialization/php/json/src/JsonParseNode.php @@ -11,7 +11,6 @@ use Microsoft\Kiota\Abstractions\Serialization\AdditionalDataHolder; use Microsoft\Kiota\Abstractions\Serialization\Parsable; use Microsoft\Kiota\Abstractions\Serialization\ParseNode; -use Microsoft\Kiota\Abstractions\Types\Byte; use Microsoft\Kiota\Abstractions\Types\Date; use Microsoft\Kiota\Abstractions\Types\Time; use Psr\Http\Message\StreamInterface; @@ -238,8 +237,6 @@ public function getAnyValue(string $type) { return $this->getDateValue(); case Time::class: return $this->getTimeValue(); - case Byte::class: - return $this->getByteValue(); default: if (is_subclass_of($type, Enum::class)){ return $this->getEnumValue($type); @@ -268,13 +265,6 @@ public function getTimeValue(): ?Time { return ($this->jsonNode !== null) ? new Time($this->jsonNode) : null; } - /** - * @inheritDoc - */ - public function getByteValue(): ?Byte { - return ($this->jsonNode !== null) ? new Byte($this->jsonNode) : null; - } - /** * @inheritDoc * @throws Exception diff --git a/serialization/php/json/src/JsonSerializationWriter.php b/serialization/php/json/src/JsonSerializationWriter.php index d5c2a4582f..f88497e08d 100644 --- a/serialization/php/json/src/JsonSerializationWriter.php +++ b/serialization/php/json/src/JsonSerializationWriter.php @@ -333,9 +333,6 @@ public function writeAnyValue(?string $key, $value): void{ case Time::class: $this->writeTimeValue($key, $value); break; - case Byte::class: - $this->writeByteValue($key, $value); - break; case DateTime::class: $this->writeDateTimeValue($key, $value); break; @@ -464,19 +461,4 @@ public function writeDateIntervalValue(?string $key, ?DateInterval $value): void $this->writePropertyValue($key, $val); } } - - /** - * @inheritDoc - */ - public function writeByteValue(?string $key, ?Byte $value): void { - - - if ($value !== null) { - if (!empty($key)) { - $this->writePropertyName($key); - } - $val = (int)(string)($value); - $this->writePropertyValue($key, $val); - } - } } \ No newline at end of file diff --git a/serialization/php/json/tests/JsonParseNodeTest.php b/serialization/php/json/tests/JsonParseNodeTest.php index 6aac23eeda..09698a6c17 100644 --- a/serialization/php/json/tests/JsonParseNodeTest.php +++ b/serialization/php/json/tests/JsonParseNodeTest.php @@ -8,7 +8,6 @@ use GuzzleHttp\Psr7\Utils; use Microsoft\Kiota\Abstractions\Enum; use Microsoft\Kiota\Abstractions\Serialization\ParseNode; -use Microsoft\Kiota\Abstractions\Types\Byte; use Microsoft\Kiota\Abstractions\Types\Date; use Microsoft\Kiota\Abstractions\Types\Time; use Microsoft\Kiota\Serialization\Json\JsonParseNode; @@ -95,16 +94,6 @@ public function testGetAnyValue(): void { $this->assertEquals('Silas Kenneth', $expectedString); } - public function testGetByteValue(): void { - $this->parseNode = new JsonParseNode('23'); - $expected = $this->parseNode->getByteValue(); - $this->assertInstanceOf(Byte::class, $expected); - $this->assertEquals(23, (string)$expected); - $this->expectException(Exception::class); - $this->parseNode = new JsonParseNode('-192'); - $this->parseNode->getByteValue(); - } - public function testGetEnumValue(): void { $this->parseNode = new JsonParseNode('married'); /** @var Enum $expected */ diff --git a/serialization/php/json/tests/JsonSerializationWriterTest.php b/serialization/php/json/tests/JsonSerializationWriterTest.php index 5922342f76..65b8c9c786 100644 --- a/serialization/php/json/tests/JsonSerializationWriterTest.php +++ b/serialization/php/json/tests/JsonSerializationWriterTest.php @@ -3,7 +3,6 @@ namespace Microsoft\Kiota\Serialization\Tests; use Microsoft\Kiota\Abstractions\Serialization\SerializationWriter; -use Microsoft\Kiota\Abstractions\Types\Byte; use Microsoft\Kiota\Abstractions\Types\Date; use Microsoft\Kiota\Abstractions\Types\Time; use Microsoft\Kiota\Serialization\Json\JsonSerializationWriter; @@ -135,9 +134,9 @@ public function testWriteEnumValue(): void{ public function testWriteAnyValue(): void { $this->jsonSerializationWriter = new JsonSerializationWriter(); - $byte = new Byte(23); - $this->jsonSerializationWriter->writeAnyValue("to", $byte); - $expected = '"to":23'; + $time = new Time('11:00:00'); + $this->jsonSerializationWriter->writeAnyValue("created", $time); + $expected = '"created":"11:00:00"'; $actual = $this->jsonSerializationWriter->getSerializedContent()->getContents(); $this->assertEquals($expected, $actual); } @@ -198,17 +197,6 @@ public function testGetSerializedContent(): void{ $this->assertEquals($expected, $actual); } - /** - */ - public function testWriteByteValue(): void{ - $this->jsonSerializationWriter = new JsonSerializationWriter(); - $byte = new Byte(23); - $this->jsonSerializationWriter->writeAnyValue("to", $byte); - $expected = '"to":23'; - $actual = $this->jsonSerializationWriter->getSerializedContent()->getContents(); - $this->assertEquals($expected, $actual); - } - /** */ public function testWriteStringValue(): void { diff --git a/src/Kiota.Builder/Writers/Php/PhpConventionService.cs b/src/Kiota.Builder/Writers/Php/PhpConventionService.cs index 550ba34bdb..85a755e9c9 100644 --- a/src/Kiota.Builder/Writers/Php/PhpConventionService.cs +++ b/src/Kiota.Builder/Writers/Php/PhpConventionService.cs @@ -60,8 +60,9 @@ public override string TranslateType(CodeType type) return typeName?.ToLowerInvariant() switch { "boolean" => "bool", - "double" or "decimal" => "float", - "integer" or "int32" or "int64" => "int", + "double" => "float", + "decimal" or "byte" => "string", + "integer" or "int32" or "int64" or "sbyte" => "int", "object" or "string" or "array" or "float" or "void" => typeName.ToLowerInvariant(), "binary" => "StreamInterface", _ => typeName.ToFirstCharacterUpperCase() diff --git a/tests/Kiota.Builder.Tests/Writers/Php/CodeMethodWriterTests.cs b/tests/Kiota.Builder.Tests/Writers/Php/CodeMethodWriterTests.cs index 3bb1893873..174ac214a1 100644 --- a/tests/Kiota.Builder.Tests/Writers/Php/CodeMethodWriterTests.cs +++ b/tests/Kiota.Builder.Tests/Writers/Php/CodeMethodWriterTests.cs @@ -1,20 +1,17 @@ using System; +using System.Collections.Generic; using System.IO; using System.Linq; -using Kiota.Builder.Extensions; using Kiota.Builder.Refiners; -using Kiota.Builder.Writers; -using Kiota.Builder.Writers.Php; using Xunit; - namespace Kiota.Builder.Writers.Php.Tests { public class CodeMethodWriterTests: IDisposable { private const string DefaultPath = "./"; private const string DefaultName = "name"; - private readonly StringWriter tw; - private readonly LanguageWriter writer; + private readonly StringWriter stringWriter; + private readonly LanguageWriter languageWriter; private readonly CodeMethod method; private readonly CodeClass parentClass; private const string MethodName = "methodName"; @@ -24,13 +21,13 @@ public class CodeMethodWriterTests: IDisposable private const string ParamName = "paramName"; private readonly CodeMethodWriter _codeMethodWriter; private readonly ILanguageRefiner _refiner; - private readonly CodeNamespace root; + private readonly CodeNamespace root = CodeNamespace.InitRootNamespace(); public CodeMethodWriterTests() { - writer = LanguageWriter.GetLanguageWriter(GenerationLanguage.PHP, DefaultPath, DefaultName); - tw = new StringWriter(); - writer.SetTextWriter(tw); + languageWriter = LanguageWriter.GetLanguageWriter(GenerationLanguage.PHP, DefaultPath, DefaultName); + stringWriter = new StringWriter(); + languageWriter.SetTextWriter(stringWriter); root = CodeNamespace.InitRootNamespace(); root.Name = "Microsoft\\Graph"; _codeMethodWriter = new CodeMethodWriter(new PhpConventionService()); @@ -52,9 +49,8 @@ public CodeMethodWriterTests() [Fact] public void WriteABasicMethod() { - var declaration = method; - _codeMethodWriter.WriteCodeElement(declaration, writer); - var result = tw.ToString(); + _codeMethodWriter.WriteCodeElement(method, languageWriter); + var result = stringWriter.ToString(); Assert.Contains("public function", result); } @@ -71,37 +67,31 @@ public void WriteMethodWithNoDescription() }, Parent = parentClass }; - _codeMethodWriter.WriteCodeElement(codeMethod, writer); - var result = tw.ToString(); + _codeMethodWriter.WriteCodeElement(codeMethod, languageWriter); + var result = stringWriter.ToString(); Assert.DoesNotContain("/*", result); } public void Dispose() { - tw?.Dispose(); + stringWriter?.Dispose(); GC.SuppressFinalize(this); } [Fact] public void WriteRequestExecutor() { - var codeClass = parentClass; - codeClass.AddProperty(new CodeProperty() - { - Kind = CodePropertyKind.RequestAdapter, Name = "requestAdapter" - }); - codeClass.AddProperty(new CodeProperty() + CodeProperty[] properties = { - Kind = CodePropertyKind.UrlTemplate, Name = "urlTemplate" - }); - codeClass.AddProperty(new CodeProperty() - { - Kind = CodePropertyKind.PathParameters, Name = "pathParameters" - }); + new CodeProperty { Kind = CodePropertyKind.RequestAdapter, Name = "requestAdapter" }, + new CodeProperty { Kind = CodePropertyKind.UrlTemplate, Name = "urlTemplate" }, + new CodeProperty { Kind = CodePropertyKind.PathParameters, Name = "pathParameters" }, + }; + parentClass.AddProperty(properties); var codeMethod = new CodeMethod() { - Name = "get", + Name = "post", HttpMethod = HttpMethod.Post, ReturnType = new CodeType() { @@ -132,8 +122,8 @@ public void WriteRequestExecutor() Name = "RequestInformation" } }; - codeClass.AddMethod(codeMethod); - codeClass.AddMethod(codeMethodRequestGenerator); + parentClass.AddMethod(codeMethod); + parentClass.AddMethod(codeMethodRequestGenerator); var error4XX = root.AddClass(new CodeClass{ Name = "Error4XX", }).First(); @@ -146,8 +136,8 @@ public void WriteRequestExecutor() codeMethod.AddErrorMapping("4XX", new CodeType {Name = "Error4XX", TypeDefinition = error4XX}); codeMethod.AddErrorMapping("5XX", new CodeType {Name = "Error5XX", TypeDefinition = error5XX}); codeMethod.AddErrorMapping("403", new CodeType {Name = "Error403", TypeDefinition = error401}); - _codeMethodWriter.WriteCodeElement(codeMethod, writer); - var result = tw.ToString(); + _codeMethodWriter.WriteCodeElement(codeMethod, languageWriter); + var result = stringWriter.ToString(); Assert.Contains("Promise", result); Assert.Contains("$requestInfo = $this->createPostRequestInformation();", result); @@ -157,127 +147,68 @@ public void WriteRequestExecutor() Assert.Contains("return $this->requestAdapter->sendPrimitiveAsync($requestInfo, StreamInterface::class, $responseHandler, $errorMappings);", result); } - [Fact] - public void WriteSerializer() + public static IEnumerable SerializerProperties => new List { - var classHolding = parentClass; - classHolding.Kind = CodeClassKind.Model; - classHolding.AddProperty( - new CodeProperty() - { - Type = new CodeType() - { - Name = "string" - }, - Name = "name", - Access = AccessModifier.Private, - Kind = CodePropertyKind.Custom - }); - classHolding.AddProperty( - new CodeProperty() - { - Name = "email", - Access = AccessModifier.Private, - Type = new CodeType() - { - Name = "EmailAddress", - TypeDefinition = new CodeClass() - { - Name = "EmailAddress", - Kind = CodeClassKind.Model - } - }, - Kind = CodePropertyKind.Custom - }); - classHolding.AddProperty(new CodeProperty - { - Name = "status", - Access = AccessModifier.Private, - Type = new CodeType - { - Name = "Status", - TypeDefinition = new CodeEnum {Name = "Status", Description = "Status Enum"} - } - }); - classHolding.AddProperty(new CodeProperty - { - Name = "architectures", - Access = AccessModifier.Private, - Type = new CodeType - { - CollectionKind = CodeTypeBase.CodeTypeCollectionKind.Array, - Name = "Architecture", - TypeDefinition = new CodeEnum {Name = "Architecture", Description = "Arch Enum, accepts x64, x86, hybrid"} - } - }); - classHolding.AddProperty(new CodeProperty - { - Name = "age", Access = AccessModifier.Private, Type = new CodeType {Name = "int"} - }); - classHolding.AddProperty(new CodeProperty - { - Name = "height", Access = AccessModifier.Private, Type = new CodeType {Name = "float"} - }); - classHolding.AddProperty(new CodeProperty - { - Name = "slept", Access = AccessModifier.Private, Type = new CodeType {Name = "bool"} - }); - classHolding.AddProperty(new CodeProperty + new object[] { - Name = "emails", - Access = AccessModifier.Private, - Type = new CodeType - { - CollectionKind = CodeTypeBase.CodeTypeCollectionKind.Array, - Name = "Email", TypeDefinition = new CodeClass {Name = "Email", Kind = CodeClassKind.Model} - } - }); - classHolding.AddProperty(new CodeProperty - { - Name = "temperatures", - Access = AccessModifier.Private, - Type = new CodeType - { - CollectionKind = CodeTypeBase.CodeTypeCollectionKind.Array, - Name = "int" - } - }); - classHolding.AddProperty(new CodeProperty + new CodeProperty { Name = "name", Type = new CodeType { Name = "string" }, Access = AccessModifier.Private, Kind = CodePropertyKind.Custom }, + "$writer->writeStringValue('name', $this->name);" + }, + new object[] { - Name = "dateValue", - Access = AccessModifier.Private, - Type = new CodeType + new CodeProperty { Name = "email", Type = new CodeType { - Name = "DateTime" - } - }); - classHolding.AddProperty(new CodeProperty + Name = "EmailAddress", TypeDefinition = new CodeClass { Name = "EmailAddress", Kind = CodeClassKind.Model} + }, Access = AccessModifier.Private, Kind = CodePropertyKind.Custom }, + "$writer->writeObjectValue('email', $this->email);" + }, + new object[] { - Name = "duration", - Access = AccessModifier.Private, - Type = new CodeType + new CodeProperty { Name = "status", Type = new CodeType { Name = "Status", TypeDefinition = new CodeEnum { - Name = "duration" - } - }); - classHolding.AddProperty(new CodeProperty + Name = "Status", Description = "Status Enum" + }}, Access = AccessModifier.Private }, + "$writer->writeEnumValue('status', $this->status);" + }, + new object[] { - Name = "stream", - Access = AccessModifier.Private, - Type = new CodeType + new CodeProperty { Name = "architectures", Type = new CodeType { - Name = "streaminterface" - } - }); - classHolding.AddProperty(new CodeProperty + Name = "Architecture", CollectionKind = CodeTypeBase.CodeTypeCollectionKind.Array, TypeDefinition = new CodeEnum { Name = "Architecture", Description = "Arch Enum, accepts x64, x86, hybrid"} + }, Access = AccessModifier.Private, Kind = CodePropertyKind.Custom }, + "$writer->writeCollectionOfEnumValues('architectures', $this->architectures);" + }, + new object[] { new CodeProperty { Name = "emails", Type = new CodeType { - Name = "other", - Access = AccessModifier.Private, - Type = new CodeType - { - Name = "other" - } - }); + Name = "Email", TypeDefinition = new CodeClass { Name = "Email", Kind = CodeClassKind.Model}, CollectionKind = CodeTypeBase.CodeTypeCollectionKind.Array }, Access = AccessModifier.Private}, + "$writer->writeCollectionOfObjectValues('emails', $this->emails);" + }, + new object[] { new CodeProperty { Name = "temperatures", Type = new CodeType { Name = "int", CollectionKind = CodeTypeBase.CodeTypeCollectionKind.Array }, Access = AccessModifier.Private}, + "$writer->writeCollectionOfPrimitiveValues('temperatures', $this->temperatures);" + }, + // Primitive int tests + new object[] { new CodeProperty { Name = "age", Type = new CodeType { Name = "integer" }, Access = AccessModifier.Private}, "$writer->writeIntegerValue('age', $this->age);" }, + new object[] { new CodeProperty { Name = "age", Type = new CodeType { Name = "int32" }, Access = AccessModifier.Private}, "$writer->writeIntegerValue('age', $this->age);" }, + new object[] { new CodeProperty { Name = "age", Type = new CodeType { Name = "int64" }, Access = AccessModifier.Private}, "$writer->writeIntegerValue('age', $this->age);" }, + new object[] { new CodeProperty { Name = "age", Type = new CodeType { Name = "sbyte" }, Access = AccessModifier.Private}, "$writer->writeIntegerValue('age', $this->age);" }, + // Float tests + new object[] { new CodeProperty { Name = "height", Type = new CodeType { Name = "float" }, Access = AccessModifier.Private}, "$writer->writeFloatValue('height', $this->height);" }, + new object[] { new CodeProperty { Name = "height", Type = new CodeType { Name = "double" }, Access = AccessModifier.Private}, "$writer->writeFloatValue('height', $this->height);" }, + // Bool tests + new object[] { new CodeProperty { Name = "married", Type = new CodeType { Name = "boolean" }, Access = AccessModifier.Private}, "$writer->writeBooleanValue('married', $this->married);" }, + new object[] { new CodeProperty { Name = "slept", Type = new CodeType { Name = "bool" }, Access = AccessModifier.Private}, "$writer->writeBooleanValue('slept', $this->slept);" }, + // Decimal and byte tests + new object[] { new CodeProperty { Name = "money", Type = new CodeType { Name = "decimal" }, Access = AccessModifier.Private}, "$writer->writeStringValue('money', $this->money);" }, + new object[] { new CodeProperty { Name = "money", Type = new CodeType { Name = "byte" }, Access = AccessModifier.Private}, "$writer->writeStringValue('money', $this->money);" }, + new object[] { new CodeProperty { Name = "dateValue", Type = new CodeType { Name = "DateTime" }, Access = AccessModifier.Private}, "$writer->writeDateTimeValue('dateValue', $this->dateValue);" }, + new object[] { new CodeProperty { Name = "duration", Type = new CodeType { Name = "duration" }, Access = AccessModifier.Private}, "$writer->writeDateIntervalValue('duration', $this->duration);" }, + new object[] { new CodeProperty { Name = "stream", Type = new CodeType { Name = "binary" }, Access = AccessModifier.Private}, "$writer->writeBinaryContent('stream', $this->stream);" }, + }; + + [Theory] + [MemberData(nameof(SerializerProperties))] + public void WriteSerializer(CodeProperty property, string expected) + { var codeMethod = new CodeMethod() { Name = "serialize", @@ -296,28 +227,20 @@ public void WriteSerializer() Name = "SerializationWriter" } }); - classHolding.AddMethod(codeMethod); - _codeMethodWriter.WriteCodeElement(codeMethod, writer); - var result = tw.ToString(); - - Assert.Contains("public function serialize(", result); - Assert.Contains("$writer->writeStringValue('name', $this->name);", result); - Assert.Contains("$writer->writeObjectValue('email', $this->email);", result); - Assert.Contains("$writer->writeIntegerValue('age', $this->age", result); - Assert.Contains("$writer->writeCollectionOfEnumValues('architectures', $this->architectures);",result); - Assert.Contains("$writer->writeCollectionOfObjectValues('emails', $this->emails);", result); - Assert.Contains("$writer->writeFloatValue('height', $this->height);", result); - Assert.Contains("$writer->writeBooleanValue('slept', $this->slept);", result); - Assert.Contains("$writer->writeEnumValue('status', $this->status);", result); - Assert.Contains("$writer->writeCollectionOfPrimitiveValues('temperatures', $this->temperatures);", result); + parentClass.AddMethod(codeMethod); + parentClass.AddProperty(property); + parentClass.Kind = CodeClassKind.Model; + _codeMethodWriter.WriteCodeElement(codeMethod, languageWriter); + var result = stringWriter.ToString(); + Assert.Contains("public function serialize(SerializationWriter $writer)", result); + Assert.Contains(expected, stringWriter.ToString()); } [Fact] public void WriteRequestGenerator() { - var methodClass = parentClass; - methodClass.Kind = CodeClassKind.RequestBuilder; - methodClass.AddProperty( + parentClass.Kind = CodeClassKind.RequestBuilder; + parentClass.AddProperty( new CodeProperty() { Name = "urlTemplate", @@ -407,10 +330,10 @@ public void WriteRequestGenerator() }); - methodClass.AddMethod(codeMethod); + parentClass.AddMethod(codeMethod); - _codeMethodWriter.WriteCodeElement(codeMethod, writer); - var result = tw.ToString(); + _codeMethodWriter.WriteCodeElement(codeMethod, languageWriter); + var result = stringWriter.ToString(); Assert.Contains( "public function createPostRequestInformation(Message $body, ?RequestConfig $requestConfiguration = null): RequestInformation", @@ -426,9 +349,7 @@ public void WriteRequestGenerator() [Fact] public void WriteIndexerBody() { - var currentClass = parentClass; - - currentClass.AddProperty( + parentClass.AddProperty( new CodeProperty() { Name = "pathParameters", @@ -503,181 +424,75 @@ public void WriteIndexerBody() Kind = CodeParameterKind.Path }); - currentClass.AddMethod(codeMethod); + parentClass.AddMethod(codeMethod); _refiner.Refine(parentClass.Parent as CodeNamespace); - writer.Write(codeMethod); - var result = tw.ToString(); + languageWriter.Write(codeMethod); + var result = stringWriter.ToString(); Assert.Contains("$urlTplParams['message_id'] = $id;", result); Assert.Contains("public function messageById(string $id): MessageRequestBuilder {", result); Assert.Contains("return new MessageRequestBuilder($urlTplParams, $this->requestAdapter);", result); } - - [Fact] - public void WriteDeserializer() + + public static IEnumerable DeserializerProperties => new List { - var currentClass = parentClass; - parentClass.AddUsing( - new CodeUsing + new object[] { - Name = "SampleUsing", - Declaration = new CodeType - { - Name = "SampleUsing", - IsExternal = false, - Parent = parentClass.Parent, - TypeDefinition = new CodeClass - { - Description = "Just a class", - Name = "SampleUsing", - Kind = CodeClassKind.Model, - Parent = currentClass.Parent.Parent - } - } + new CodeProperty { Name = "name", Type = new CodeType { Name = "string" }, Access = AccessModifier.Private, Kind = CodePropertyKind.Custom }, + "'name' => function (ParseNode $n) use ($o) { $o->setName($n->getStringValue()); }," }, - new CodeUsing - { - Name = "SampleUsing", - Declaration = new CodeType - { - Name = "SampleUsing", - IsExternal = false, - Parent = parentClass.Parent, - TypeDefinition = new CodeClass - { - Name = "SampleUsing", - Parent = currentClass.Parent.Parent, - Kind = CodeClassKind.Model - } - } - }); - currentClass.Kind = CodeClassKind.Model; - currentClass.AddProperty( - new CodeProperty() - { - Name = "name", - Access = AccessModifier.Private, - Kind = CodePropertyKind.Custom, - Type = new CodeType() {Name = "string"} - }, - new CodeProperty - { - Name = "users", - Access = AccessModifier.Private, - Kind = CodePropertyKind.Custom, - Type = new CodeType - { - CollectionKind = CodeTypeBase.CodeTypeCollectionKind.Array, - Name = "EmailAddress", - TypeDefinition = new CodeClass - { - Name = "EmailAddress", - Description = "Email", - Kind = CodeClassKind.Model, - Parent = parentClass.Parent, - } - } - }, - new CodeProperty - { - Name = "years", - Access = AccessModifier.Private, - Kind = CodePropertyKind.Custom, - Type = new CodeType - { - CollectionKind = CodeTypeBase.CodeTypeCollectionKind.Array, - Name = "int" - } - }, - new CodeProperty - { - Name = "archs", - Access = AccessModifier.Private, - Kind = CodePropertyKind.Custom, - Type = new CodeType - { - CollectionKind = CodeTypeBase.CodeTypeCollectionKind.Array, - Name = "Arch", - TypeDefinition = new CodeEnum - { - Parent = parentClass, - Name = "Arch" - } - } - }, - new CodeProperty - { - Name = "age", - Access = AccessModifier.Private, - Kind = CodePropertyKind.Custom, - Type = new CodeType - { - Name = "int" - } - }, - new CodeProperty - { - Name = "height", - Access = AccessModifier.Private, - Kind = CodePropertyKind.Custom, - Type = new CodeType - { - Name = "double" - } - }, - new CodeProperty - { - Name = "height2", - Access = AccessModifier.Private, - Kind = CodePropertyKind.Custom, - Type = new CodeType - { - Name = "decimal" - } - }, - new CodeProperty - { - Name = "story", - Access = AccessModifier.Private, - Kind = CodePropertyKind.Custom, - Type = new CodeType - { - Name = "StreamInterface" - } - }, - new CodeProperty - { - Name = "likes", - Access = AccessModifier.Private, - Kind = CodePropertyKind.Custom, - Type = new CodeType - { - Name = "number" - } - }, - new CodeProperty - { - Name = "custom", - Access = AccessModifier.Private, - Kind = CodePropertyKind.Custom, - Type = new CodeType - { - Name = "Custom" - } - }, - new CodeProperty + new object[] + { + new CodeProperty { Name = "age", Type = new CodeType { Name = "int32" }, Access = AccessModifier.Private, Kind = CodePropertyKind.Custom }, + "'age' => function (ParseNode $n) use ($o) { $o->setAge($n->getIntegerValue()); }," + }, + new object[] + { + new CodeProperty { Name = "height", Type = new CodeType { Name = "double" }, Access = AccessModifier.Private, Kind = CodePropertyKind.Custom }, + "'height' => function (ParseNode $n) use ($o) { $o->setHeight($n->getFloatValue()); }," + }, + new object[] + { + new CodeProperty { Name = "height", Type = new CodeType { Name = "decimal" }, Access = AccessModifier.Private, Kind = CodePropertyKind.Custom }, + "'height' => function (ParseNode $n) use ($o) { $o->setHeight($n->getStringValue()); }," + }, + new object[] + { + new CodeProperty { Name = "DOB", Type = new CodeType { Name = "DateTimeOffset" }, Access = AccessModifier.Private, Kind = CodePropertyKind.Custom }, + "'dOB' => function (ParseNode $n) use ($o) { $o->setDOB($n->getDateTimeValue()); }," + }, + new object[] + { + new CodeProperty { Name = "story", Type = new CodeType { Name = "binary" }, Access = AccessModifier.Private, Kind = CodePropertyKind.Custom }, + "'story' => function (ParseNode $n) use ($o) { $o->setStory($n->getBinaryContent()); }," + }, + new object[] { new CodeProperty { Name = "users", Type = new CodeType { - Name = "DOB", - Access = AccessModifier.Private, - Type = new CodeType + Name = "EmailAddress", TypeDefinition = new CodeClass { - Name = "DateTimeOffset" - } - } - ); - + Name = "EmailAddress", Kind = CodeClassKind.Model, Description = "Email", Parent = GetParentClassInStaticContext() + }, CollectionKind = CodeTypeBase.CodeTypeCollectionKind.Array }, Access = AccessModifier.Private}, + "'users' => function (ParseNode $n) use ($o) { $o->setUsers($n->getCollectionOfObjectValues(array(EmailAddress::class, 'createFromDiscriminatorValue')));" + }, + new object[] { new CodeProperty { Name = "years", Type = new CodeType { Name = "int", CollectionKind = CodeTypeBase.CodeTypeCollectionKind.Array }, Access = AccessModifier.Private}, + "'years' => function (ParseNode $n) use ($o) { $o->setYears($n->getCollectionOfPrimitiveValues())" + }, + }; + private static CodeClass GetParentClassInStaticContext() + { + CodeClass parent = new CodeClass() { Name = "parent" }; + CodeNamespace rootNamespace = CodeNamespace.InitRootNamespace(); + rootNamespace.AddClass(parent); + return parent; + } + + [Theory] + [MemberData(nameof(DeserializerProperties))] + public void WriteDeserializer(CodeProperty property, string expected) + { + parentClass.Kind = CodeClassKind.Model; var deserializerMethod = new CodeMethod() { Name = "getDeserializationFields", @@ -690,23 +505,11 @@ public void WriteDeserializer() Name = "array" } }; - - currentClass.AddMethod(deserializerMethod); + parentClass.AddMethod(deserializerMethod); + parentClass.AddProperty(property); _refiner.Refine(parentClass.Parent as CodeNamespace); - writer.Write(deserializerMethod); - var result = tw.ToString(); - - Assert.Contains("'name' => function (ParseNode $n) use ($o) { $o->setName($n->getStringValue()); },", result); - Assert.Contains("'story' => function (ParseNode $n) use ($o) { $o->setStory($n->getBinaryContent()); }", result); - Assert.Contains( - "'years' => function (ParseNode $n) use ($o) { $o->setYears($n->getCollectionOfPrimitiveValues())", - result); - Assert.Contains( - "'users' => function (ParseNode $n) use ($o) { $o->setUsers($n->getCollectionOfObjectValues(array(EmailAddress::class, 'createFromDiscriminatorValue')));", - result); - Assert.Contains( - "'dOB' => function (ParseNode $n) use ($o) { $o->setDOB($n->getDateTimeValue());", - result); + languageWriter.Write(deserializerMethod); + Assert.Contains(expected, stringWriter.ToString()); } [Fact] @@ -752,9 +555,8 @@ public void WriteDeserializerMergeWhenHasParent() currentClass.AddMethod(deserializerMethod); _refiner.Refine(parentClass.Parent as CodeNamespace); - _codeMethodWriter.WriteCodeElement(deserializerMethod, writer); - var result = tw.ToString(); - + _codeMethodWriter.WriteCodeElement(deserializerMethod, languageWriter); + var result = stringWriter.ToString(); Assert.Contains("array_merge(parent::getFieldDeserializers()", result); } @@ -772,8 +574,8 @@ public void WriteConstructorBody() var closingClass = parentClass; parentClass.AddMethod(constructor); - _codeMethodWriter.WriteCodeElement(constructor, writer); - var result = tw.ToString(); + _codeMethodWriter.WriteCodeElement(constructor, languageWriter); + var result = stringWriter.ToString(); Assert.Contains("public function __construct", result); } @@ -798,8 +600,8 @@ public void WriteGetter() Parent = parentClass }; - _codeMethodWriter.WriteCodeElement(getter, writer); - var result = tw.ToString(); + _codeMethodWriter.WriteCodeElement(getter, languageWriter); + var result = stringWriter.ToString(); Assert.Contains(": EmailAddress {", result); Assert.Contains("public function getEmailAddress", result); } @@ -828,8 +630,8 @@ public void WriteGetterAdditionalData() Parent = parentClass }; - _codeMethodWriter.WriteCodeElement(getter, writer); - var result = tw.ToString(); + _codeMethodWriter.WriteCodeElement(getter, languageWriter); + var result = stringWriter.ToString(); Assert.Contains("public function getAdditionalData(): array", result); Assert.Contains("return $this->additionalData;", result); } @@ -862,8 +664,8 @@ public void WriteSetter() Name = "emailAddress" } }); - _codeMethodWriter.WriteCodeElement(setter, writer); - var result = tw.ToString(); + _codeMethodWriter.WriteCodeElement(setter, languageWriter); + var result = stringWriter.ToString(); Assert.Contains("public function setEmailAddress(EmailAddress $value)", result); Assert.Contains(": void {", result); @@ -894,8 +696,8 @@ public void WriteRequestBuilderWithParametersBody() } }); - _codeMethodWriter.WriteCodeElement(codeMethod, writer); - var result = tw.ToString(); + _codeMethodWriter.WriteCodeElement(codeMethod, languageWriter); + var result = stringWriter.ToString(); Assert.Contains("function messageById(string $id): MessageRequestBuilder {", result); Assert.Contains("return new MessageRequestBuilder($this->pathParameters, $this->requestAdapter, $id);", result); } @@ -957,8 +759,8 @@ public void WriteRequestBuilderConstructor() } }); - writer.Write(method); - var result = tw.ToString(); + languageWriter.Write(method); + var result = stringWriter.ToString(); Assert.Contains("__construct", result); Assert.Contains($"$this->{propName} = {defaultValue};", result); Assert.Contains("$this->pathParameters = array_merge($this->pathParameters, $urlTplParams);", result); @@ -1006,8 +808,8 @@ public void WriteFactoryMethod() Optional = false, }); _refiner.Refine(parentClass.Parent as CodeNamespace); - writer.Write(factoryMethod); - var result = tw.ToString(); + languageWriter.Write(factoryMethod); + var result = stringWriter.ToString(); Assert.Contains("case 'childModel': return new ChildModel();", result); Assert.Contains("$mappingValueNode = ParseNode::getChildNode(\"@odata.type\");", result); } @@ -1046,8 +848,8 @@ public void WriteApiConstructor() codeMethod.SerializerModules = new() {"Microsoft\\Kiota\\Serialization\\Serializer"}; parentClass.AddMethod(codeMethod); _refiner.Refine(parentClass.Parent as CodeNamespace); - writer.Write(codeMethod); - var result = tw.ToString(); + languageWriter.Write(codeMethod); + var result = stringWriter.ToString(); Assert.Contains("$this->requestAdapter = $requestAdapter", result); Assert.Contains("public function __construct(RequestAdapter $requestAdapter)", result); } diff --git a/tests/Kiota.Builder.Tests/Writers/Php/CodePropertyWriterTests.cs b/tests/Kiota.Builder.Tests/Writers/Php/CodePropertyWriterTests.cs index 3cea8e6252..0e0cfcfaaf 100644 --- a/tests/Kiota.Builder.Tests/Writers/Php/CodePropertyWriterTests.cs +++ b/tests/Kiota.Builder.Tests/Writers/Php/CodePropertyWriterTests.cs @@ -1,4 +1,4 @@ -using System; +using System.Collections.Generic; using System.IO; using Kiota.Builder.Refiners; using Xunit; @@ -11,23 +11,23 @@ public class CodePropertyWriterTests private const string DefaultName = "Name"; private readonly CodeClass parentClass; private readonly CodePropertyWriter propertyWriter; - private readonly LanguageWriter writer; - private readonly StringWriter tw; + private readonly LanguageWriter languageWriter; + private readonly StringWriter stringWriter; private readonly ILanguageRefiner _refiner; private readonly CodeNamespace root = CodeNamespace.InitRootNamespace(); public CodePropertyWriterTests() { - tw = new StringWriter(); + stringWriter = new StringWriter(); + languageWriter = LanguageWriter.GetLanguageWriter(GenerationLanguage.PHP, DefaultPath, DefaultName); + languageWriter.SetTextWriter(stringWriter); parentClass = new CodeClass() { Name = "ParentClass", Description = "This is an amazing class", Kind = CodeClassKind.Model }; + root.AddClass(parentClass); _refiner = new PhpRefiner(new() {Language = GenerationLanguage.PHP}); propertyWriter = new CodePropertyWriter(new PhpConventionService()); - root.AddClass(parentClass); - writer = LanguageWriter.GetLanguageWriter(GenerationLanguage.PHP, DefaultPath, DefaultName); - writer.SetTextWriter(tw); } [Fact] public void WritePropertyDocs() @@ -41,11 +41,10 @@ public void WritePropertyDocs() Name = "emailAddress" } }; - var cls = parentClass; - cls.AddProperty(property); - propertyWriter.WriteCodeElement(property, writer); + parentClass.AddProperty(property); + propertyWriter.WriteCodeElement(property, languageWriter); - var result = tw.ToString(); + var result = stringWriter.ToString(); Assert.Contains("@var EmailAddress|null $email", result); Assert.Contains("private ?EmailAddress $email = null;", result); } @@ -64,11 +63,10 @@ public void WritePropertyRequestBuilder() }, Kind = CodePropertyKind.RequestBuilder }; - var cls = parentClass; - cls.AddProperty(property); - propertyWriter.WriteCodeElement(property, writer); + parentClass.AddProperty(property); + propertyWriter.WriteCodeElement(property, languageWriter); - var result = tw.ToString(); + var result = stringWriter.ToString(); Assert.Contains("public function message(): MessageRequestBuilder", result); Assert.Contains("return new MessageRequestBuilder($this->pathParameters, $this->requestAdapter);", result); } @@ -84,13 +82,11 @@ public void WriteCollectionKindProperty() Access = AccessModifier.Private, Type = new CodeType() {Name = "array", CollectionKind = CodeTypeBase.CodeTypeCollectionKind.Array} }; - var currentClass = parentClass; - currentClass.Kind = CodeClassKind.Model; - - currentClass.AddProperty(property); + parentClass.Kind = CodeClassKind.Model; + parentClass.AddProperty(property); _refiner.Refine(root); - propertyWriter.WriteCodeElement(property, writer); - var result = tw.ToString(); + propertyWriter.WriteCodeElement(property, languageWriter); + var result = stringWriter.ToString(); Assert.Contains("private array $additionalData;", result); Assert.Contains("@var array", result); } @@ -108,18 +104,16 @@ public void WriteCollectionNonAdditionalData() Name = "recipient", CollectionKind = CodeTypeBase.CodeTypeCollectionKind.Array } }; - var currentClass = parentClass; - currentClass.AddProperty(property); + parentClass.AddProperty(property); - propertyWriter.WriteCodeElement(property, writer); - var result = tw.ToString(); + propertyWriter.WriteCodeElement(property, languageWriter); + var result = stringWriter.ToString(); Assert.Contains("@var array|null", result); } [Fact] public void WriteRequestAdapter() { - var currentClass = parentClass; var adapter = new CodeProperty() { Name = "adapter", @@ -127,19 +121,66 @@ public void WriteRequestAdapter() Access = AccessModifier.Private, Kind = CodePropertyKind.RequestAdapter }; - - - currentClass.AddProperty(adapter); - currentClass.AddProperty(new CodeProperty() + parentClass.AddProperty(adapter); + parentClass.AddProperty(new CodeProperty() { Name = "pathSegment", Kind = CodePropertyKind.PathParameters }); - propertyWriter.WriteCodeElement(adapter, writer); - var result = tw.ToString(); + propertyWriter.WriteCodeElement(adapter, languageWriter); + var result = stringWriter.ToString(); Assert.Contains("private RequestAdapter $adapter;", result); } + + [Fact] + public void WritePrimitiveFloatProperty() + { + CodeProperty property = new CodeProperty() + { + Name = "property", + Type = new CodeType() + { + Name = "double" + }, + Access = AccessModifier.Protected + }; + parentClass.AddProperty(property); + propertyWriter.WriteCodeElement(property, languageWriter); + var result = stringWriter.ToString(); + Assert.Contains($"protected ?float $property = null;", result); + } + + public static IEnumerable StringProperties => new List + { + new object[] { new CodeProperty { Name = "property", Type = new CodeType { Name = "decimal" } } }, + new object[] { new CodeProperty { Name = "property", Type = new CodeType { Name = "byte" } } } + }; + + [Theory] + [MemberData(nameof(StringProperties))] + public void WritePrimitiveStringProperty(CodeProperty property) + { + parentClass.AddProperty(property); + propertyWriter.WriteCodeElement(property, languageWriter); + Assert.Contains("public ?string $property = null;", stringWriter.ToString()); + } + + public static IEnumerable IntProperties => new List + { + new object[] { new CodeProperty { Name = "property", Type = new CodeType { Name = "integer" }, Access = AccessModifier.Protected} }, + new object[] { new CodeProperty { Name = "property", Type = new CodeType { Name = "int32" }, Access = AccessModifier.Protected} }, + new object[] { new CodeProperty { Name = "property", Type = new CodeType { Name = "sbyte" }, Access = AccessModifier.Protected} }, + new object[] { new CodeProperty { Name = "property", Type = new CodeType { Name = "int64" }, Access = AccessModifier.Protected} } + }; + [Theory] + [MemberData(nameof(IntProperties))] + public void WritePrimitiveIntProperty(CodeProperty property) + { + parentClass.AddProperty(property); + propertyWriter.WriteCodeElement(property, languageWriter); + Assert.Contains("protected ?int $property = null;", stringWriter.ToString()); + } [Fact] public void WriteQueryParameter() @@ -156,8 +197,8 @@ public void WriteQueryParameter() } }; parentClass.AddProperty(queryParameter); - propertyWriter.WriteCodeElement(queryParameter, writer); - var result = tw.ToString(); + propertyWriter.WriteCodeElement(queryParameter, languageWriter); + var result = stringWriter.ToString(); Assert.Contains("@QueryParameter(\"%24select\")", result); Assert.Contains("@var array|null $select", result);