From 01d29ee023b12a35ae718385e89af97c4853618b Mon Sep 17 00:00:00 2001 From: Anthony Axenov Date: Sun, 17 Sep 2023 23:59:37 +0800 Subject: [PATCH] Initial and very naive conversion v2.0 => v2.1 (#10) --- composer.json | 3 +- src/Collection.php | 1 + src/Converters/ConvertFormat.php | 2 + .../Postman20/Postman20Converter.php | 7 +- .../Postman21/Postman21Converter.php | 164 ++++++++++++++++++ src/Environment.php | 10 +- src/Processor.php | 14 +- 7 files changed, 190 insertions(+), 11 deletions(-) create mode 100644 src/Converters/Postman21/Postman21Converter.php diff --git a/composer.json b/composer.json index 8c5cf7c..fe966c0 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,8 @@ "keywords": ["postman", "collection", "converter", "http", "wget", "curl", "api", "convert"], "require": { "php": "^8.1", - "ext-json": "*" + "ext-json": "*", + "ext-mbstring": "*" }, "bin": ["pm-convert"], "autoload": { diff --git a/src/Collection.php b/src/Collection.php index 4a032aa..891419b 100644 --- a/src/Collection.php +++ b/src/Collection.php @@ -12,6 +12,7 @@ use Stringable; * * @property array|object $item * @property object $info + * @property object|null $variable */ class Collection implements Stringable { diff --git a/src/Converters/ConvertFormat.php b/src/Converters/ConvertFormat.php index 9aa6c0a..3bebb54 100644 --- a/src/Converters/ConvertFormat.php +++ b/src/Converters/ConvertFormat.php @@ -9,6 +9,7 @@ use PmConverter\Converters\{ Curl\CurlConverter, Http\HttpConverter, Postman20\Postman20Converter, + Postman21\Postman21Converter, Wget\WgetConverter}; enum ConvertFormat: string @@ -17,4 +18,5 @@ enum ConvertFormat: string case Curl = CurlConverter::class; case Wget = WgetConverter::class; case Postman20 = Postman20Converter::class; + case Postman21 = Postman21Converter::class; } diff --git a/src/Converters/Postman20/Postman20Converter.php b/src/Converters/Postman20/Postman20Converter.php index 370044f..2730d7f 100644 --- a/src/Converters/Postman20/Postman20Converter.php +++ b/src/Converters/Postman20/Postman20Converter.php @@ -19,7 +19,7 @@ class Postman20Converter extends AbstractConverter implements ConverterContract { protected const FILE_EXT = 'v20.postman_collection.json'; - protected const OUTPUT_DIR = 'v2.0'; + protected const OUTPUT_DIR = 'pm-v2.0'; /** * Converts collection requests @@ -93,7 +93,7 @@ class Postman20Converter extends AbstractConverter implements ConverterContract return; } $type = $request->auth->type; - if ($type !== 'noauth' && is_array($request->auth->$type)) { // bearer + if ($type !== 'noauth' && is_array($request->auth->$type)) { $auth = []; foreach ($request->auth->$type as $param) { $auth[$param->key] = $param->value; @@ -125,8 +125,7 @@ class Postman20Converter extends AbstractConverter implements ConverterContract { foreach ($responses as $response) { if (is_object($response->originalRequest->url)) { - $raw = $response->originalRequest->url->raw; - $response->originalRequest->url = $raw; + $response->originalRequest->url = $response->originalRequest->url->raw; } } } diff --git a/src/Converters/Postman21/Postman21Converter.php b/src/Converters/Postman21/Postman21Converter.php new file mode 100644 index 0000000..317812a --- /dev/null +++ b/src/Converters/Postman21/Postman21Converter.php @@ -0,0 +1,164 @@ +collection = $collection; + $this->collection->info->schema = str_replace('/v2.0.', '/v2.1.', $this->collection->info->schema); + $this->prepareOutputDir($outputPath); + $this->convertAuth($this->collection->raw()); + foreach ($this->collection->item as $item) { + $this->convertItem($item); + } + $this->writeCollection(); + } + + /** + * Writes converted collection into file + * + * @return bool + * @throws CannotCreateDirectoryException + * @throws DirectoryIsNotWriteableException + */ + protected function writeCollection(): bool + { + $filedir = FileSystem::makeDir($this->outputPath); + $filepath = sprintf('%s%s%s.%s', $filedir, DIRECTORY_SEPARATOR, $this->collection->name(), static::FILE_EXT); + return file_put_contents($filepath, $this->collection) > 0; + } + + /** + * Changes some requests fields in place + * + * @param mixed $item + * @return void + */ + protected function convertItem(mixed $item): void + { + if ($this->isItemFolder($item)) { + foreach ($item->item as $subitem) { + if ($this->isItemFolder($subitem)) { + $this->convertItem($subitem); + } else { + $this->convertAuth($subitem->request); + $this->convertRequestUrl($subitem->request); + $this->convertResponseUrls($subitem->response); + } + } + } else { + $this->convertAuth($item->request); + $this->convertRequestUrl($item->request); + $this->convertResponseUrls($item->response); + } + } + + /** + * Converts auth object from v2.0 to v2.1 + * + * @param object $request + * @return void + */ + protected function convertAuth(object $request): void + { + if (empty($request->auth)) { + return; + } + $type = $request->auth->type; + if ($type !== 'noauth' && isset($request->auth->$type)) { + $auth = []; + foreach ($request->auth->$type as $key => $value) { + $auth[] = (object)[ + 'key' => $key, + 'value' => $value, + 'type' => 'string', + ]; + } + $request->auth->$type = $auth; + } + } + + /** + * Converts requests URLs from string v2.0 to object v2.1 + * + * @param object $request + * @return void + */ + protected function convertRequestUrl(object $request): void + { + if (is_string($request->url) && mb_strlen($request->url) > 0) { + $data = array_values(array_filter(explode('/', $request->url))); //TODO URL parsing + if (count($data) === 1) { + $url = [ + 'raw' => $request->url, + 'host' => [$data[0] ?? $request->url], + ]; + } else { + $url = [ + 'raw' => $request->url, + 'protocol' => str_replace(':', '', $data[0]), + 'host' => [$data[1] ?? $request->url], + 'path' => array_slice($data, 2), + ]; + } + $request->url = (object)$url; + } + } + + /** + * Converts URLs response examples from string v2.0 to object v2.1 + * + * @param array $responses + * @return void + */ + protected function convertResponseUrls(array $responses): void + { + foreach ($responses as $response) { + if (is_string($response->originalRequest->url)) { + $data = array_values(array_filter(explode('/', $response->originalRequest->url))); //TODO URL parsing + if (count($data) === 1) { + $url = [ + 'raw' => $response->originalRequest->url, + 'host' => [$data[0] ?? $response->originalRequest->url], + ]; + } else { + $url = [ + 'raw' => $response->originalRequest->url, + 'protocol' => str_replace(':', '', $data[0]), + 'host' => [$data[1] ?? $response->originalRequest->url], + 'path' => array_slice($data, 2), + ]; + } + $response->originalRequest->url = (object)$url; + } + } + } +} diff --git a/src/Environment.php b/src/Environment.php index b0d1164..ab3bcaf 100644 --- a/src/Environment.php +++ b/src/Environment.php @@ -12,12 +12,14 @@ class Environment implements \ArrayAccess protected array $vars = []; /** - * @param object $env + * @param object|null $env */ - public function __construct(protected object $env) + public function __construct(protected ?object $env) { - foreach ($env->values as $var) { - $this->vars[static::formatKey($var->key)] = $var->value; + if (!empty($env->values)) { + foreach ($env->values as $var) { + $this->vars[static::formatKey($var->key)] = $var->value; + } } } diff --git a/src/Processor.php b/src/Processor.php index 05e3137..4ddaa2f 100644 --- a/src/Processor.php +++ b/src/Processor.php @@ -54,7 +54,7 @@ class Processor protected array $converters = []; /** - * @var object[] Collections that will be converted into choosen formats + * @var Collection[] Collections that will be converted into choosen formats */ protected array $collections = []; @@ -93,6 +93,7 @@ class Processor * Parses an array of arguments came from cli * * @return void + * @throws JsonException */ protected function parseArgs(): void { @@ -160,6 +161,10 @@ class Processor $this->formats[ConvertFormat::Postman20->name] = ConvertFormat::Postman20; break; + case '--v2.1': + $this->formats[ConvertFormat::Postman21->name] = ConvertFormat::Postman21; + break; + case '--var': [$var, $value] = explode('=', trim($this->argv[$idx + 1])); $this->vars[$var] = $value; @@ -297,8 +302,13 @@ class Processor protected function printStats(int $success, int $count): void { $time = (hrtime(true) - $this->initTime) / 1_000_000; + $timeFmt = 'ms'; + if ($time > 1000) { + $time /= 1000; + $timeFmt = 'sec'; + } $ram = (memory_get_peak_usage(true) - $this->initRam) / 1024 / 1024; - printf('Converted %d of %d in %.3f ms using up to %.3f MiB RAM%s', $success, $count, $time, $ram, PHP_EOL); + printf("Converted %d/%d in %.2f $timeFmt using up to %.2f MiB RAM%s", $success, $count, $time, $ram, PHP_EOL); } /**