diff --git a/CHANGELOG.md b/CHANGELOG.md index f7499fff72..d726dc5047 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix null reference exception when a parameter is defined without a schema. (CLI). - Log a message to stderr if a request is skipped due to missing data. (CLI) [#2210](https://github.com/microsoft/kiota/issues/2210) - Fixes code file generation in typescript [#3419](https://github.com/microsoft/kiota/issues/3419) +- Writes fully qualified name of custom types when a type with a similar name exists in the class in PHP. ## [1.6.1] - 2023-09-11 diff --git a/it/config.json b/it/config.json index bcc2b59723..f62d8a954f 100644 --- a/it/config.json +++ b/it/config.json @@ -144,7 +144,7 @@ }, { "Language": "php", - "Rationale": "https://github.com/microsoft/kiota/issues/2956" + "Rationale": "https://github.com/microsoft/kiota/issues/3029" }, { "Language": "python", @@ -238,7 +238,7 @@ }, { "Language": "php", - "Rationale": "https://github.com/microsoft/kiota/issues/2964" + "Rationale": "https://github.com/microsoft/kiota/issues/3029" }, { "Language": "java", @@ -258,10 +258,6 @@ "Language": "go", "Rationale": "https://github.com/microsoft/kiota/issues/2834" }, - { - "Language": "php", - "Rationale": "https://github.com/microsoft/kiota/issues/2964" - }, { "Language": "java", "Rationale": "https://github.com/microsoft/kiota/issues/2842" @@ -322,4 +318,4 @@ } ] } -} \ No newline at end of file +} diff --git a/src/Kiota.Builder/Writers/Php/CodeMethodWriter.cs b/src/Kiota.Builder/Writers/Php/CodeMethodWriter.cs index 515925f4ac..aaf53cc7e7 100644 --- a/src/Kiota.Builder/Writers/Php/CodeMethodWriter.cs +++ b/src/Kiota.Builder/Writers/Php/CodeMethodWriter.cs @@ -705,7 +705,7 @@ private void WriteRequestExecutorBody(CodeMethod codeElement, CodeClass parentCl joinedParams = string.Join(", ", callParams); } - var returnTypeName = conventions.TranslateType(codeElement.ReturnType); + var returnTypeName = conventions.GetTypeString(codeElement.ReturnType, codeElement, false); writer.WriteLine($"$requestInfo = $this->{generatorMethodName}({joinedParams});"); writer.WriteLine("try {"); writer.IncreaseIndent(); diff --git a/src/Kiota.Builder/Writers/Php/CodePropertyWriter.cs b/src/Kiota.Builder/Writers/Php/CodePropertyWriter.cs index c7792bb90f..fa0ef3d459 100644 --- a/src/Kiota.Builder/Writers/Php/CodePropertyWriter.cs +++ b/src/Kiota.Builder/Writers/Php/CodePropertyWriter.cs @@ -12,17 +12,17 @@ public override void WriteCodeElement(CodeProperty codeElement, LanguageWriter w ArgumentNullException.ThrowIfNull(codeElement); ArgumentNullException.ThrowIfNull(writer); if (codeElement.ExistsInExternalBaseType) return; - var returnType = conventions.GetTypeString(codeElement.Type, codeElement); + var propertyType = conventions.GetTypeString(codeElement.Type, codeElement); var propertyName = codeElement.Name.ToFirstCharacterLowerCase(); var propertyAccess = conventions.GetAccessModifier(codeElement.Access); switch (codeElement.Kind) { case CodePropertyKind.RequestBuilder: - WriteRequestBuilderBody(codeElement, writer, returnType, propertyAccess, propertyName); + WriteRequestBuilderBody(codeElement, writer, propertyType, propertyAccess, propertyName); break; default: WritePropertyDocComment(codeElement, writer); - writer.WriteLine($"{propertyAccess} {(codeElement.Type.IsNullable ? "?" : string.Empty)}{returnType} ${propertyName}{(codeElement.Type.IsNullable ? " = null" : string.Empty)};"); + writer.WriteLine($"{propertyAccess} {(codeElement.Type.IsNullable ? "?" : string.Empty)}{propertyType} ${propertyName}{(codeElement.Type.IsNullable ? " = null" : string.Empty)};"); break; } writer.WriteLine(""); diff --git a/src/Kiota.Builder/Writers/Php/PhpConventionService.cs b/src/Kiota.Builder/Writers/Php/PhpConventionService.cs index 001a786ab9..edfb8f6246 100644 --- a/src/Kiota.Builder/Writers/Php/PhpConventionService.cs +++ b/src/Kiota.Builder/Writers/Php/PhpConventionService.cs @@ -48,13 +48,17 @@ public override string GetTypeString(CodeTypeBase code, CodeElement targetElemen throw new InvalidOperationException($"PHP does not support union types, the union type {code.Name} should have been filtered out by the refiner."); if (code is CodeType currentType) { + if (includeCollectionInformation && code.IsCollection) + { + return "array"; + } var typeName = TranslateType(currentType); if (!currentType.IsExternal && IsSymbolDuplicated(typeName, targetElement) && currentType.TypeDefinition is not null) { return $"\\{currentType.TypeDefinition.GetImmediateParentOfType().Name.ReplaceDotsWithSlashInNamespaces()}\\{typeName.ToFirstCharacterUpperCase()}"; } } - return code is { IsCollection: true } ? "array" : TranslateType(code); + return TranslateType(code); } public override string TranslateType(CodeType type) diff --git a/tests/Kiota.Builder.Tests/Writers/Php/CodeMethodWriterTests.cs b/tests/Kiota.Builder.Tests/Writers/Php/CodeMethodWriterTests.cs index 13941157c7..bee0dd083a 100644 --- a/tests/Kiota.Builder.Tests/Writers/Php/CodeMethodWriterTests.cs +++ b/tests/Kiota.Builder.Tests/Writers/Php/CodeMethodWriterTests.cs @@ -2342,4 +2342,48 @@ public async void WritesQueryParameterConstructor() Assert.Contains("$this->top = $top;", result); } + [Fact] + public async Task WritesFullyQualifiedNameWhenSimilarTypeAlreadyExists() + { + setup(); + var modelNamespace = root.AddNamespace("Models"); + var nestedModelNamespace = modelNamespace.AddNamespace("Models\\Security"); + var returnType1 = modelNamespace.AddClass(new CodeClass + { + Name = "ModelA" + }).First(); + var returnType2 = nestedModelNamespace.AddClass(new CodeClass + { + Name = "ModelA" + }).First(); + var returnType3 = root.AddClass(new CodeClass { Name = "Component" }).First(); + parentClass.Kind = CodeClassKind.RequestBuilder; + parentClass.AddProperty(new CodeProperty + { + Name = "requestAdapter", + Kind = CodePropertyKind.RequestAdapter, + Type = new CodeType { Name = "RequestAdapter" } + }, new CodeProperty + { + Name = "pathParameters", + Kind = CodePropertyKind.PathParameters, + Type = new CodeType { Name = "array", CollectionKind = CodeTypeBase.CodeTypeCollectionKind.Array } + }); + var getMethod = new CodeMethod { Name = "getAsync", Kind = CodeMethodKind.RequestExecutor, HttpMethod = HttpMethod.Get, ReturnType = new CodeType { TypeDefinition = returnType1, CollectionKind = CodeTypeBase.CodeTypeCollectionKind.Array } }; + var deleteMethod = new CodeMethod { Name = "deleteAsync", Kind = CodeMethodKind.RequestExecutor, HttpMethod = HttpMethod.Delete, ReturnType = new CodeType { TypeDefinition = returnType2 } }; + var testMethod = new CodeMethod { Name = "testMethod", Kind = CodeMethodKind.RequestExecutor, HttpMethod = HttpMethod.Post, ReturnType = new CodeType { TypeDefinition = returnType3, CollectionKind = CodeTypeBase.CodeTypeCollectionKind.Array } }; + parentClass.AddMethod(getMethod, deleteMethod, testMethod); + + await ILanguageRefiner.Refine(new GenerationConfiguration { Language = GenerationLanguage.PHP, UsesBackingStore = true }, root); + _codeMethodWriter = new CodeMethodWriter(new PhpConventionService(), true); + _codeMethodWriter.WriteCodeElement(getMethod, languageWriter); + _codeMethodWriter.WriteCodeElement(deleteMethod, languageWriter); + _codeMethodWriter.WriteCodeElement(testMethod, languageWriter); + var result = stringWriter.ToString(); + + Assert.Contains("return $this->requestAdapter->sendCollectionAsync($requestInfo, [\\Microsoft\\Graph\\Models\\ModelA::class, 'createFromDiscriminatorValue'], null);", result); + Assert.Contains("return $this->requestAdapter->sendAsync($requestInfo, [\\Microsoft\\Graph\\Models\\Security\\ModelA::class, 'createFromDiscriminatorValue'], null);", result); + Assert.Contains("return $this->requestAdapter->sendCollectionAsync($requestInfo, [Component::class, 'createFromDiscriminatorValue'], null);", result); + } + }