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 9eed16f1004..f27044c2db7 100644 --- a/src/main/java/com/wordnik/swagger/codegen/languages/PhpClientCodegen.java +++ b/src/main/java/com/wordnik/swagger/codegen/languages/PhpClientCodegen.java @@ -44,6 +44,7 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { languageSpecificPrimitives.add("int"); languageSpecificPrimitives.add("array"); + languageSpecificPrimitives.add("map"); languageSpecificPrimitives.add("string"); languageSpecificPrimitives.add("DateTime"); @@ -52,7 +53,7 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { typeMapping.put("Array", "array"); typeMapping.put("String", "string"); typeMapping.put("List", "array"); - typeMapping.put("map", "array"); + typeMapping.put("map", "map"); supportingFiles.add(new SupportingFile("Swagger.mustache", "", "Swagger.php")); } @@ -81,7 +82,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]"; + return getSwaggerType(p) + "[string," + getTypeDeclaration(inner) + "]"; } return super.getTypeDeclaration(p); } diff --git a/src/main/resources/php/Swagger.mustache b/src/main/resources/php/Swagger.mustache index ae3f29ed560..7e1f24f49b6 100644 --- a/src/main/resources/php/Swagger.mustache +++ b/src/main/resources/php/Swagger.mustache @@ -11,117 +11,116 @@ * @param string $className the class to attempt to load */ function swagger_autoloader($className) { - $currentDir = dirname(__FILE__); - if (file_exists($currentDir . '/' . $className . '.php')) { - include $currentDir . '/' . $className . '.php'; - } elseif (file_exists($currentDir . '/models/' . $className . '.php')) { - include $currentDir . '/models/' . $className . '.php'; - } + $currentDir = dirname(__FILE__); + if (file_exists($currentDir . '/' . $className . '.php')) { + include $currentDir . '/' . $className . '.php'; + } elseif (file_exists($currentDir . '/models/' . $className . '.php')) { + include $currentDir . '/models/' . $className . '.php'; + } } spl_autoload_register('swagger_autoloader'); class APIClient { - public static $POST = "POST"; - public static $GET = "GET"; - public static $PUT = "PUT"; - public static $DELETE = "DELETE"; + public static $POST = "POST"; + public static $GET = "GET"; + public static $PUT = "PUT"; + public static $DELETE = "DELETE"; - /** - * @param string $apiKey your API key - * @param string $apiServer the address of the API server - */ - function __construct($apiKey, $apiServer) { - $this->apiKey = $apiKey; - $this->apiServer = $apiServer; - } + /** + * @param string $apiKey your API key + * @param string $apiServer the address of the API server + */ + function __construct($apiKey, $apiServer) { + $this->apiKey = $apiKey; + $this->apiServer = $apiServer; + } /** - * @param string $resourcePath path to method endpoint - * @param string $method method to call - * @param array $queryParams parameters to be place in query URL - * @param array $postData parameters to be placed in POST body - * @param array $headerParams parameters to be place in request header - * @return mixed - */ - public function callAPI($resourcePath, $method, $queryParams, $postData, - $headerParams) { + * @param string $resourcePath path to method endpoint + * @param string $method method to call + * @param array $queryParams parameters to be place in query URL + * @param array $postData parameters to be placed in POST body + * @param array $headerParams parameters to be place in request header + * @return mixed + */ + public function callAPI($resourcePath, $method, $queryParams, $postData, + $headerParams) { - $headers = array(); + $headers = array(); # Allow API key from $headerParams to override default $added_api_key = False; - if ($headerParams != null) { - foreach ($headerParams as $key => $val) { - $headers[] = "$key: $val"; - if ($key == 'api_key') { - $added_api_key = True; - } - } - } - if (! $added_api_key) { - $headers[] = "api_key: " . $this->apiKey; - } + if ($headerParams != null) { + foreach ($headerParams as $key => $val) { + $headers[] = "$key: $val"; + if ($key == 'api_key') { + $added_api_key = True; + } + } + } + if (! $added_api_key) { + $headers[] = "api_key: " . $this->apiKey; + } - if (is_object($postData) or is_array($postData)) { - $postData = json_encode($this->sanitizeForSerialization($postData)); - } + if (is_object($postData) or is_array($postData)) { + $postData = json_encode($this->sanitizeForSerialization($postData)); + } - $url = $this->apiServer . $resourcePath; + $url = $this->apiServer . $resourcePath; - $curl = curl_init(); - curl_setopt($curl, CURLOPT_TIMEOUT, 5); - // return the result on success, rather than just TRUE - curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); - curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); + $curl = curl_init(); + curl_setopt($curl, CURLOPT_TIMEOUT, 5); + // return the result on success, rather than just TRUE + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); - if (! empty($queryParams)) { - $url = ($url . '?' . http_build_query($queryParams)); - } + if (! empty($queryParams)) { + $url = ($url . '?' . http_build_query($queryParams)); + } - if ($method == self::$POST) { - curl_setopt($curl, CURLOPT_POST, true); - curl_setopt($curl, CURLOPT_POSTFIELDS, $postData); - } else if ($method == self::$PUT) { - curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PUT"); - curl_setopt($curl, CURLOPT_POSTFIELDS, $postData); - } else if ($method == self::$DELETE) { - curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "DELETE"); - curl_setopt($curl, CURLOPT_POSTFIELDS, $postData); - } else if ($method != self::$GET) { - throw new Exception('Method ' . $method . ' is not recognized.'); - } - curl_setopt($curl, CURLOPT_URL, $url); + if ($method == self::$POST) { + curl_setopt($curl, CURLOPT_POST, true); + curl_setopt($curl, CURLOPT_POSTFIELDS, $postData); + } else if ($method == self::$PUT) { + curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PUT"); + curl_setopt($curl, CURLOPT_POSTFIELDS, $postData); + } else if ($method == self::$DELETE) { + curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "DELETE"); + curl_setopt($curl, CURLOPT_POSTFIELDS, $postData); + } else if ($method != self::$GET) { + throw new Exception('Method ' . $method . ' is not recognized.'); + } + curl_setopt($curl, CURLOPT_URL, $url); - // Make the request - $response = curl_exec($curl); - $response_info = curl_getinfo($curl); + // Make the request + $response = curl_exec($curl); + $response_info = curl_getinfo($curl); - // Handle the response - if ($response_info['http_code'] == 0) { - throw new Exception("TIMEOUT: api call to " . $url . - " took more than 5s to return" ); - } else if ($response_info['http_code'] == 200) { - $data = json_decode($response); - } else if ($response_info['http_code'] == 401) { - throw new Exception("Unauthorized API request to " . $url . - ": ".json_decode($response)->message ); - } else if ($response_info['http_code'] == 404) { - $data = null; - } else { - throw new Exception("Can't connect to the api: " . $url . - " response code: " . - $response_info['http_code']); - } + // Handle the response + if ($response_info['http_code'] == 0) { + throw new Exception("TIMEOUT: api call to " . $url . + " took more than 5s to return" ); + } else if ($response_info['http_code'] == 200) { + $data = json_decode($response); + } else if ($response_info['http_code'] == 401) { + throw new Exception("Unauthorized API request to " . $url . + ": ".json_decode($response)->message ); + } else if ($response_info['http_code'] == 404) { + $data = null; + } else { + throw new Exception("Can't connect to the api: " . $url . + " response code: " . + $response_info['http_code']); + } + return $data; + } - return $data; - } - - /** - * Build a JSON POST object - */ + /** + * Build a JSON POST object + */ protected function sanitizeForSerialization($data) { if (is_scalar($data) || null === $data) { @@ -146,41 +145,41 @@ class APIClient { return $sanitized; } - /** - * Take value and turn it into a string suitable for inclusion in - * the path, by url-encoding. - * @param string $value a string which will be part of the path - * @return string the serialized object - */ - public static function toPathValue($value) { - return rawurlencode($value); - } + /** + * Take value and turn it into a string suitable for inclusion in + * the path, by url-encoding. + * @param string $value a string which will be part of the path + * @return string the serialized object + */ + public static function toPathValue($value) { + return rawurlencode($value); + } - /** - * Take value and turn it into a string suitable for inclusion in - * the query, by imploding comma-separated if it's an object. - * If it's a string, pass through unchanged. It will be url-encoded - * later. - * @param object $object an object to be serialized to a string - * @return string the serialized object - */ - public static function toQueryValue($object) { + /** + * Take value and turn it into a string suitable for inclusion in + * the query, by imploding comma-separated if it's an object. + * If it's a string, pass through unchanged. It will be url-encoded + * later. + * @param object $object an object to be serialized to a string + * @return string the serialized object + */ + public static function toQueryValue($object) { if (is_array($object)) { return implode(',', $object); } else { return $object; } - } + } - /** - * Just pass through the header value for now. Placeholder in case we - * find out we need to do something with header values. - * @param string $value a string which will be part of the header - * @return string the header string - */ - public static function toHeaderValue($value) { - return $value; - } + /** + * Just pass through the header value for now. Placeholder in case we + * find out we need to do something with header values. + * @param string $value a string which will be part of the header + * @return string the header string + */ + public static function toHeaderValue($value) { + return $value; + } /** * Deserialize a JSON string into an object @@ -194,10 +193,19 @@ class APIClient { { if (null === $data) { $deserialized = null; - } else if (substr($class, 0, 6) == 'array[') { - $subClass = substr($class, 6, -1); + } elseif (substr($class, 0, 4) == 'map[') { + $inner = substr($class, 4, -1); $values = array(); - foreach ($data as $value) { + if(strrpos($inner, ",") !== false) { + $subClass = explode(',', $inner, 2)[1]; + foreach ($data as $key => $value) { + $values[] = array($key => self::deserialize($value, $subClass)); + } + } + $deserialized = $values; + } elseif (substr($class, 0, 6) == 'array[') { + $subClass = substr($class, 6, -1); + foreach ($data as $key => $value) { $values[] = self::deserialize($value, $subClass); } $deserialized = $values; diff --git a/src/test/scala/php/PhpModelTest.scala b/src/test/scala/php/PhpModelTest.scala index fc6f45b4193..723ec5b3aec 100644 --- a/src/test/scala/php/PhpModelTest.scala +++ b/src/test/scala/php/PhpModelTest.scala @@ -1,10 +1,12 @@ package php import com.wordnik.swagger.codegen.languages.PhpClientCodegen -import com.wordnik.swagger.util.{ Json, SwaggerLoader } +import com.wordnik.swagger.util.Json import com.wordnik.swagger.models._ import com.wordnik.swagger.models.properties._ +import io.swagger.parser.SwaggerParser + import org.junit.runner.RunWith import org.scalatest.junit.JUnitRunner import org.scalatest.FlatSpec @@ -121,9 +123,9 @@ class PhpModelTest extends FlatSpec with Matchers { val vars = cm.vars vars.get(0).baseName should be ("translations") - vars.get(0).datatype should be ("array[string]") + vars.get(0).datatype should be ("map[string,string]") vars.get(0).name should be ("translations") - vars.get(0).baseType should be ("array") + vars.get(0).baseType should be ("map") vars.get(0).containerType should be ("map") vars.get(0).required should equal (false) vars.get(0).isContainer should equal (true) @@ -151,7 +153,7 @@ class PhpModelTest extends FlatSpec with Matchers { 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") @@ -168,10 +170,10 @@ class PhpModelTest extends FlatSpec with Matchers { 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).complexType should be ("Children") + vars.get(0).datatype should be ("array[Children]") vars.get(0).name should be ("children") - vars.get(0).baseType should be ("NSArray") + vars.get(0).baseType should be ("array") vars.get(0).containerType should be ("array") vars.get(0).required should equal (false) vars.get(0).isContainer should equal (true) @@ -190,14 +192,14 @@ class PhpModelTest extends FlatSpec with Matchers { 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) + (cm.imports.asScala.toSet & Set("Children")).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).complexType should be ("Children") + vars.get(0).datatype should be ("map[string,Children]") vars.get(0).name should be ("children") - vars.get(0).baseType should be ("NSDictionary") + vars.get(0).baseType should be ("map") vars.get(0).containerType should be ("map") vars.get(0).required should equal (false) vars.get(0).isContainer should equal (true) @@ -215,9 +217,8 @@ class PhpModelTest extends FlatSpec with Matchers { 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) + cm.imports.size should be (1) + (cm.imports.asScala.toSet & Set("Children")).size should be (1) } it should "convert an map model" in { @@ -232,13 +233,13 @@ class PhpModelTest extends FlatSpec with Matchers { 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) + cm.imports.size should be (2) + (cm.imports.asScala.toSet & Set("Children")).size should be (1) } it should "create proper imports per #316" in { - val model = new SwaggerLoader().read("src/test/resources/postBodyTest.json") + val model = new SwaggerParser() + .read("src/test/resources/postBodyTest.json") val codegen = new PhpClientCodegen() val animalPaths = model.getPaths() @@ -246,14 +247,13 @@ class PhpModelTest extends FlatSpec with Matchers { 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) + animalCo.imports.contains("Animal") 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) + insectCo.imports.contains("Insect") should equal (true) } - */ } \ No newline at end of file