getMessage() )); } $parsed = 0; $langs = []; $digests = []; printf("Removing asciidoc from %s/docs/examples\n", dirname(__DIR__)); removeAllFiles(dirname(__DIR__) . '/docs/examples/*.asciidoc'); printf("Output folder: %s/docs/examples\n\n", dirname(__DIR__)); foreach ($spec as $source) { if ($source['lang'] !== 'console') { continue; } // count the digests if (!isset($digests[$source['digest']])) { $digests[$source['digest']] = []; } $digests[$source['digest']][] = $source['source_location']['file']; // take stats about languages foreach ($source['found'] as $l) { if (!isset($langs[$l])) { $langs[$l] = 0; } $langs[$l]++; } if (!in_array($source['source_location']['file'], $fileToParse)) { continue; } printf("Reading source: %s\n", $source['source_location']['file']); $head = sprintf("// %s:%d\n", $source['source_location']['file'], $source['source_location']['line']); $head .= "\n[source, php]\n----\n"; $code = getClientSourceCode($source['parsed_source']); checkIfCodeHasValidSyntax($code); $exampleFile = sprintf("%s/docs/examples/%s.asciidoc", dirname(__DIR__), $source['digest']); file_put_contents($exampleFile, $head . $code . "----\n"); printf("File generated: %s.asciidoc\n", $source['digest']); $parsed++; } $end = microtime(true); // Count only the digests to prevent double count in code examples $tot = count($digests); printf("\nLanguage statistics:\n"); foreach ($langs as $lang => $num) { printf("%-8s: %4d (%.2f%% completed)\n", $lang, $num, (100/$tot)*$num); } printf("\n"); printf("Total source examples: %d\n", $tot); printf("Generated %d source examples in %.3f seconds\n", $parsed, $end - $start); // END /** * Generate the client source code from the parsed_source field */ function getClientSourceCode(array $parsedSource): string { $tab4 = str_repeat(' ', 4); $code = ''; foreach ($parsedSource as $source) { if (isset($source['params']) || isset($source['body'])) { $code .= '$params = [' . "\n"; $code .= prettyPrintArray($source['params'] ?? [], 4); if (isset($source['body'])) { $code .= sprintf("%s'body' => [\n", $tab4); $code .= prettyPrintArray($source['body'], 8); $code .= sprintf("%s],\n", $tab4); } $code .= "];\n"; } $code .= '$response = $client->' . normalizeApiName($source['api']); $code .= empty($source['params']) && empty($source['body']) ? '();' : '($params);'; $code .= "\n"; } return $code; } /** * Print an associative array as source code * Note: it removes the number keys in scalar array */ function prettyPrintArray(array $input, int $space): string { $output = ''; $tab = str_repeat(' ', $space); foreach ($input as $key => $value) { if (is_int($key)) { $output .= sprintf("%s", $tab); } else { $output .= sprintf("%s'%s' => ", $tab, $key); } if (is_array($value)) { $output .= "[\n"; $output .= prettyPrintArray($value, $space + 4); $output .= sprintf("%s],\n", $tab); } else { if (is_string($value)) { $value = "'" . str_replace("'", "\'", $value) . "'"; } if (is_bool($value)) { $value = $value ? 'true' : 'false'; } $output .= sprintf("%s,\n", $value); } } return $output; } /** * Normalize the api name for invoking the equivalent endpoint */ function normalizeApiName(string $api): string { $result = str_replace('_', '', lcfirst(ucwords($api, '_'))); return str_replace('.', '()->', $result); } /** * Check if the generated code has a valid PHP syntax using OpenSearch\Client */ function checkIfCodeHasValidSyntax(string $code): void { $script = sprintf("require_once '%s/vendor/autoload.php';\n", dirname(__DIR__)); $script .= '$client = OpenSearch\ClientBuilder::create()->build();' . "\n"; try { eval($script . $code); } catch (OpenSearchException $e) { } catch (Error $e) { throw new Exception(sprintf( "The generated code:\n%s\nhas the following parse error:\n%s", $code, $e->getMessage() )); } } /** * Remove all files in a folder */ function removeAllFiles(string $folder): void { $files = glob($folder); foreach ($files as $file) { if (is_file($file)) { unlink($file); } } } /** * Print the usage message in console */ function printUsageMsg(): void { printf("Usage: php %s \n", basename(__FILE__)); printf("where is the `alternatives_report.spec.json` path file\n"); }