diff --git a/src/main/java/com/wordnik/swagger/codegen/languages/PhpClientCodegen.java b/src/main/java/com/wordnik/swagger/codegen/languages/PhpClientCodegen.java index 737d5993f0c..9eed16f1004 100644 --- a/src/main/java/com/wordnik/swagger/codegen/languages/PhpClientCodegen.java +++ b/src/main/java/com/wordnik/swagger/codegen/languages/PhpClientCodegen.java @@ -42,14 +42,17 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { additionalProperties.put("artifactId", artifactId); additionalProperties.put("artifactVersion", artifactVersion); + languageSpecificPrimitives.add("int"); languageSpecificPrimitives.add("array"); languageSpecificPrimitives.add("string"); + languageSpecificPrimitives.add("DateTime"); typeMapping.put("long", "int"); typeMapping.put("integer", "int"); typeMapping.put("Array", "array"); typeMapping.put("String", "string"); typeMapping.put("List", "array"); + typeMapping.put("map", "array"); supportingFiles.add(new SupportingFile("Swagger.mustache", "", "Swagger.php")); } @@ -78,7 +81,7 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { else if (p instanceof MapProperty) { MapProperty mp = (MapProperty) p; Property inner = mp.getAdditionalProperties(); - return getSwaggerType(p) + "[String, " + getTypeDeclaration(inner) + "]"; + return getSwaggerType(p) + "[string]"; } return super.getTypeDeclaration(p); } @@ -99,152 +102,8 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { return null; return type; } -} -/* -package com.wordnik.swagger.codegen - -import com.wordnik.swagger.codegen.model._ - -import java.io.File - -object BasicPHPGenerator extends BasicPHPGenerator { - def main(args: Array[String]) = generateClient(args) -} - -class BasicPHPGenerator extends BasicGenerator { - // template used for models - modelTemplateFiles += "model.mustache" -> ".php" - - // template used for models - apiTemplateFiles += "api.mustache" -> ".php" - - // location of templates - override def templateDir = "php" - - // where to write generated code - override def destinationDir = "generated-code/php" - - // package for models - override def modelPackage: Option[String] = Some("models") - - // package for apis - override def apiPackage: Option[String] = Some("") - - // file suffix - override def fileSuffix = ".php" - - // reserved words which need special quoting - // These will all be object properties, in which context we don't need - // to worry about escaping them for PHP. - override def reservedWords = Set() - - // import/require statements for specific datatypes - override def importMapping = Map() - - - // response classes - override def processResponseClass(responseClass: String): Option[String] = { - typeMapping.contains(responseClass) match { - case true => Some(typeMapping(responseClass)) - case false => { - responseClass match { - case "void" => None - case e: String => { - responseClass.startsWith("List") match { - case true => Some("array") - case false => Some(responseClass) - } - } - } - } - } + public String toDefaultValue(Property p) { + return "null"; } - - - override def processResponseDeclaration(responseClass: String): Option[String] = { - typeMapping.contains(responseClass) match { - case true => Some(typeMapping(responseClass)) - case false => { - responseClass match { - case "void" => None - case e: String => { - responseClass.startsWith("List") match { - case true => { - val responseSubClass = responseClass.dropRight(1).substring(5) - typeMapping.contains(responseSubClass) match { - case true => Some("array[" + typeMapping(responseSubClass) + "]") - case false => Some("array[" + responseSubClass + "]") - } - } - case false => Some(responseClass) - } - } - } - } - } - } - override def typeMapping = Map( - "string" -> "string", - "str" -> "string", - "int" -> "int", - "float" -> "float", - "long" -> "int", - "double" -> "float", - "Array" -> "array", - "boolean" -> "bool", - "Date" -> "DateTime" - ) - - override def toDeclaredType(dt: String): String = { - val declaredType = typeMapping.getOrElse(dt, dt) - declaredType.startsWith("Array") match { - case true => { - val innerType = dt.dropRight(1).substring(6) - typeMapping.contains(innerType) match { - case true => "array[" + typeMapping(innerType) + "]" - case false => "array[" + innerType + "]" - } - } - case _ => declaredType - } - } - - override def toDeclaration(obj: ModelProperty) = { - var declaredType = toDeclaredType(obj.`type`) - - declaredType match { - case "Array" => declaredType = "array" - case e: String => { - e - } - } - - val defaultValue = toDefaultValue(declaredType, obj) - declaredType match { - case "array" => { - val inner = { - obj.items match { - case Some(items) => items.ref.getOrElse(items.`type`) - case _ => { - println("failed on " + declaredType + ", " + obj) - throw new Exception("no inner type defined") - } - } - } - declaredType += "[" + toDeclaredType(inner) + "]" - "array" - } - case _ => - } - (declaredType, defaultValue) - } - - // supporting classes - override def supportingFiles = List( - ("Swagger.mustache", destinationDir + File.separator + apiPackage.get, - "Swagger.php") - ) -} - -*/ \ No newline at end of file +} \ No newline at end of file diff --git a/src/test/scala/php/PhpModelTest.scala b/src/test/scala/php/PhpModelTest.scala new file mode 100644 index 00000000000..fc6f45b4193 --- /dev/null +++ b/src/test/scala/php/PhpModelTest.scala @@ -0,0 +1,259 @@ +package php + +import com.wordnik.swagger.codegen.languages.PhpClientCodegen +import com.wordnik.swagger.util.{ Json, SwaggerLoader } +import com.wordnik.swagger.models._ +import com.wordnik.swagger.models.properties._ + +import org.junit.runner.RunWith +import org.scalatest.junit.JUnitRunner +import org.scalatest.FlatSpec +import org.scalatest.Matchers + +import scala.collection.JavaConverters._ + +@RunWith(classOf[JUnitRunner]) +class PhpModelTest extends FlatSpec with Matchers { + + it should "convert a simple php model" in { + val model = new ModelImpl() + .description("a sample model") + .property("id", new LongProperty()) + .property("name", new StringProperty()) + .property("createdAt", new DateTimeProperty()) + .required("id") + .required("name") + + val codegen = new PhpClientCodegen() + val cm = codegen.fromModel("sample", model) + + cm.name should be ("sample") + cm.classname should be ("Sample") + cm.description should be ("a sample model") + cm.vars.size should be (3) + + val vars = cm.vars + vars.get(0).baseName should be ("id") + vars.get(0).datatype should be ("int") + vars.get(0).name should be ("id") + vars.get(0).defaultValue should be ("null") + vars.get(0).baseType should be ("int") + vars.get(0).hasMore should equal (true) + vars.get(0).required should equal (true) + vars.get(0).isPrimitiveType should equal (true) + vars.get(0).isNotContainer should equal (true) + + vars.get(1).baseName should be ("name") + vars.get(1).datatype should be ("string") + vars.get(1).name should be ("name") + vars.get(1).defaultValue should be ("null") + vars.get(1).baseType should be ("string") + vars.get(1).hasMore should equal (true) + vars.get(1).required should equal (true) + vars.get(0).isPrimitiveType should equal (true) + vars.get(1).isNotContainer should equal (true) + + vars.get(2).baseName should be ("createdAt") + vars.get(2).complexType should be (null) + vars.get(2).datatype should be ("DateTime") + vars.get(2).name should be ("createdAt") + vars.get(2).defaultValue should be ("null") + vars.get(2).baseType should be ("DateTime") + vars.get(2).hasMore should equal (null) + vars.get(2).required should equal (false) + vars.get(2).isNotContainer should equal (true) + + cm.imports.size() should be (0) + } + + it should "convert a model with list property" in { + val model = new ModelImpl() + .description("a sample model") + .property("id", new LongProperty()) + .property("urls", new ArrayProperty() + .items(new StringProperty())) + .required("id") + + val codegen = new PhpClientCodegen() + val cm = codegen.fromModel("sample", model) + + cm.name should be ("sample") + cm.classname should be ("Sample") + cm.description should be ("a sample model") + cm.vars.size should be (2) + + val vars = cm.vars + vars.get(0).baseName should be ("id") + vars.get(0).datatype should be ("int") + vars.get(0).name should be ("id") + vars.get(0).defaultValue should be ("null") + vars.get(0).baseType should be ("int") + vars.get(0).hasMore should equal (true) + vars.get(0).required should equal (true) + vars.get(0).isPrimitiveType should equal (true) + vars.get(0).isNotContainer should equal (true) + + vars.get(1).baseName should be ("urls") + vars.get(1).datatype should be ("array[string]") + vars.get(1).name should be ("urls") + vars.get(1).baseType should be ("array") + vars.get(1).hasMore should be (null) + vars.get(1).containerType should equal ("array") + vars.get(1).required should equal (false) + vars.get(1).isPrimitiveType should equal (true) + vars.get(1).isContainer should equal (true) + } + + it should "convert a model with a map property" in { + val model = new ModelImpl() + .description("a sample model") + .property("translations", new MapProperty() + .additionalProperties(new StringProperty())) + .required("id") + + val codegen = new PhpClientCodegen() + val cm = codegen.fromModel("sample", model) + + cm.name should be ("sample") + cm.classname should be ("Sample") + cm.description should be ("a sample model") + cm.vars.size should be (1) + + val vars = cm.vars + vars.get(0).baseName should be ("translations") + vars.get(0).datatype should be ("array[string]") + vars.get(0).name should be ("translations") + vars.get(0).baseType should be ("array") + vars.get(0).containerType should be ("map") + vars.get(0).required should equal (false) + vars.get(0).isContainer should equal (true) + vars.get(0).isPrimitiveType should equal (true) + } + + it should "convert a model with complex property" in { + val model = new ModelImpl() + .description("a sample model") + .property("children", new RefProperty("#/definitions/Children")) + + val codegen = new PhpClientCodegen() + val cm = codegen.fromModel("sample", model) + + cm.name should be ("sample") + cm.classname should be ("Sample") + cm.description should be ("a sample model") + cm.vars.size should be (1) + + val vars = cm.vars + vars.get(0).baseName should be ("children") + vars.get(0).datatype should be ("Children") + vars.get(0).name should be ("children") + vars.get(0).baseType should be ("Children") + vars.get(0).required should equal (false) + vars.get(0).isNotContainer should equal (true) + } +/* + it should "convert a model with complex list property" in { + val model = new ModelImpl() + .description("a sample model") + .property("children", new ArrayProperty() + .items(new RefProperty("#/definitions/Children"))) + + val codegen = new PhpClientCodegen() + val cm = codegen.fromModel("sample", model) + + cm.name should be ("sample") + cm.classname should be ("Sample") + cm.description should be ("a sample model") + cm.vars.size should be (1) + + val vars = cm.vars + vars.get(0).baseName should be ("children") + vars.get(0).complexType should be ("SWGChildren") + vars.get(0).datatype should be ("NSArray*") + vars.get(0).name should be ("children") + vars.get(0).baseType should be ("NSArray") + vars.get(0).containerType should be ("array") + vars.get(0).required should equal (false) + vars.get(0).isContainer should equal (true) + } + + it should "convert a model with complex map property" in { + val model = new ModelImpl() + .description("a sample model") + .property("children", new MapProperty() + .additionalProperties(new RefProperty("#/definitions/Children"))) + + val codegen = new PhpClientCodegen() + val cm = codegen.fromModel("sample", model) + + cm.name should be ("sample") + cm.classname should be ("Sample") + cm.description should be ("a sample model") + cm.vars.size should be (1) + (cm.imports.asScala.toSet & Set("SWGChildren")).size should be (1) + + val vars = cm.vars + vars.get(0).baseName should be ("children") + vars.get(0).complexType should be ("SWGChildren") + vars.get(0).datatype should be ("NSDictionary*") + vars.get(0).name should be ("children") + vars.get(0).baseType should be ("NSDictionary") + vars.get(0).containerType should be ("map") + vars.get(0).required should equal (false) + vars.get(0).isContainer should equal (true) + vars.get(0).isNotContainer should be (null) + } + + it should "convert an array model" in { + val model = new ArrayModel() + .description("an array model") + .items(new RefProperty("#/definitions/Children")) + val codegen = new PhpClientCodegen() + val cm = codegen.fromModel("sample", model) + + cm.name should be ("sample") + cm.classname should be ("Sample") + cm.description should be ("an array model") + cm.vars.size should be (0) + cm.parent should be ("NSMutableArray") + cm.imports.size should be (3) + (cm.imports.asScala.toSet & Set("SWGChildren", "NSArray", "NSMutableArray")).size should be (3) + } + + it should "convert an map model" in { + val model = new ModelImpl() + .description("an map model") + .additionalProperties(new RefProperty("#/definitions/Children")) + + val codegen = new PhpClientCodegen() + val cm = codegen.fromModel("sample", model) + + cm.name should be ("sample") + cm.classname should be ("Sample") + cm.description should be ("an map model") + cm.vars.size should be (0) + cm.parent should be ("NSMutableDictionary") + cm.imports.size should be (3) + (cm.imports.asScala.toSet & Set("SWGChildren", "NSDictionary", "NSMutableDictionary")).size should be (3) + } + + it should "create proper imports per #316" in { + val model = new SwaggerLoader().read("src/test/resources/postBodyTest.json") + val codegen = new PhpClientCodegen() + + val animalPaths = model.getPaths() + val animalOps = animalPaths.get("/animals") + animalOps.getPost() should not be (null) + val animalCo = codegen.fromOperation("/animals", "POST", animalOps.getPost()) + animalCo.imports.size should be (1) + animalCo.imports.contains("SWGAnimal") should equal (true) + + val insectPaths = model.getPaths() + val insectOps = insectPaths.get("/insects") + insectOps.getPost() should not be (null) + val insectCo = codegen.fromOperation("/insects", "POST", insectOps.getPost()) + insectCo.imports.size should be (1) + insectCo.imports.contains("SWGInsect") should equal (true) + } + */ +} \ No newline at end of file