PageRenderTime 43ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/ext-libs/Protobuf-PHP/library/DrSlump/Protobuf/Compiler/Cli.php

https://gitlab.com/billyprice1/app-download.org
PHP | 260 lines | 198 code | 43 blank | 19 comment | 21 complexity | 31cc2e7d2bc7227a2cd9b6f0689382ea MD5 | raw file
  1. <?php
  2. namespace DrSlump\Protobuf\Compiler;
  3. require_once 'Console/CommandLine.php';
  4. use DrSlump\Protobuf;
  5. class Cli
  6. {
  7. public static function run($pluginExecutable)
  8. {
  9. $stdin = '';
  10. // PHP doesn't implement non-blocking stdin on Windows
  11. // https://bugs.php.net/bug.php?id=34972
  12. $isWin = 'WIN' === strtoupper(substr(PHP_OS, 0, 3));
  13. if (!$isWin) {
  14. // Open STDIN in non-blocking mode
  15. stream_set_blocking(STDIN, FALSE);
  16. // Loop until STDIN is closed or we've waited too long for data
  17. $cnt = 0;
  18. while (!feof(STDIN) && $cnt++ < 10) {
  19. // give protoc some time to feed the data
  20. usleep(10000);
  21. // read the bytes
  22. $bytes = fread(STDIN, 1024);
  23. if (strlen($bytes)) {
  24. $cnt = 0;
  25. $stdin .= $bytes;
  26. }
  27. }
  28. // If on windows and no arguments were given
  29. } else if ($_SERVER['argc'] < 2) {
  30. $stdin = fread(STDIN, 1024 * 1024);
  31. }
  32. // If no input was given we launch protoc from here
  33. if (0 === strlen($stdin)) {
  34. if ($isWin) {
  35. $pluginExecutable .= '.bat';
  36. }
  37. self::runProtoc($pluginExecutable);
  38. exit(0);
  39. }
  40. // We have data from stdin so compile it
  41. try {
  42. // Create a compiler interface
  43. $comp = new Protobuf\Compiler();
  44. echo $comp->compile($stdin);
  45. exit(0);
  46. } catch(\Exception $e) {
  47. fputs(STDERR, 'ERROR: ' . $e->getMessage());
  48. fputs(STDERR, $e->getTraceAsString());
  49. exit(255);
  50. }
  51. }
  52. public static function runProtoc($pluginExecutable)
  53. {
  54. $result = self::parseArguments();
  55. $protocBin = $result->options['protoc'];
  56. // Check if protoc is available
  57. exec("$protocBin --version", $output, $return);
  58. if (0 !== $return && 1 !== $return) {
  59. fputs(STDERR, "ERROR: Unable to find the protoc command.". PHP_EOL);
  60. fputs(STDERR, " Please make sure it's installed and available in the path." . PHP_EOL);
  61. exit(1);
  62. }
  63. if (!preg_match('/[0-9\.]+/', $output[0], $m)) {
  64. fputs(STDERR, "ERROR: Unable to get protoc command version.". PHP_EOL);
  65. fputs(STDERR, " Please make sure it's installed and available in the path." . PHP_EOL);
  66. exit(1);
  67. }
  68. if (version_compare($m[0], '2.3.0') < 0) {
  69. fputs(STDERR, "ERROR: The protoc command in your system is too old." . PHP_EOL);
  70. fputs(STDERR, " Minimum version required is 2.3.0 but found {$m[0]}." . PHP_EOL);
  71. exit(1);
  72. }
  73. $cmd[] = $protocBin;
  74. $cmd[] = '--plugin=protoc-gen-php=' . escapeshellarg($pluginExecutable);
  75. // Include paths
  76. $cmd[] = '--proto_path=' . escapeshellarg(__DIR__ . DIRECTORY_SEPARATOR . 'protos');
  77. if (!empty($result->options['include'])) {
  78. foreach($result->options['include'] as $include) {
  79. $include = realpath($include);
  80. $cmd[] = '--proto_path=' . escapeshellarg($include);
  81. }
  82. }
  83. // Convert proto files to absolute paths
  84. $protos = array();
  85. foreach ($result->args['protos'] as $proto) {
  86. $realpath = realpath($proto);
  87. if (FALSE === $realpath) {
  88. fputs(STDERR, "ERROR: File '$proto' does not exists");
  89. exit(1);
  90. }
  91. $protos[] = $realpath;
  92. }
  93. // Protoc will pass custom arguments to the plugin if they are given
  94. // before a colon character. ie: --php_out="foo=bar:/path/to/plugin"
  95. // We make use of it to pass arguments encoded as an URI query string
  96. $args = array();
  97. if ($result->options['comments']) {
  98. $args['comments'] = 1;
  99. // Protos are only needed for comments right now
  100. $args['protos'] = $protos;
  101. }
  102. if ($result->options['verbose']) {
  103. $args['verbose'] = 1;
  104. }
  105. if ($result->options['json']) {
  106. $args['json'] = 1;
  107. }
  108. if ($result->options['skipImported']) {
  109. $args['skip-imported'] = 1;
  110. }
  111. if ($result->options['define']) {
  112. $args['options'] = array();
  113. foreach($result->options['define'] as $define) {
  114. $parts = explode('=', $define);
  115. $parts = array_filter(array_map('trim', $parts));
  116. if (count($parts) === 1) {
  117. $parts[1] = 1;
  118. }
  119. $args['options'][$parts[0]] = $parts[1];
  120. }
  121. }
  122. if ($result->options['insertions']) {
  123. $args['options']['insertions'] = 1;
  124. }
  125. $cmd[] = '--php_out=' .
  126. escapeshellarg(
  127. http_build_query($args, '', '&') .
  128. ':' .
  129. $result->options['out']
  130. );
  131. // Add the chosen proto files to generate
  132. foreach ($protos as $proto) {
  133. $cmd[] = escapeshellarg($proto);
  134. }
  135. $cmdStr = implode(' ', $cmd);
  136. // Run command with stderr redirected to stdout
  137. passthru($cmdStr . ' 2>&1', $return);
  138. if ($return !== 0) {
  139. fputs(STDERR, PHP_EOL);
  140. fputs(STDERR, 'ERROR: protoc exited with an error (' . $return . ') when executed with: ' . PHP_EOL);
  141. fputs(STDERR, ' ' . implode(" \\\n ", $cmd) . PHP_EOL);
  142. exit($return);
  143. }
  144. }
  145. public static function parseArguments()
  146. {
  147. $main = new \Console_CommandLine();
  148. $main->addOption('out', array(
  149. 'short_name' => '-o',
  150. 'long_name' => '--out',
  151. 'action' => 'StoreString',
  152. 'description' => 'destination directory for generated files',
  153. 'default' => './',
  154. ));
  155. $main->addOption('include', array(
  156. 'short_name' => '-i',
  157. 'long_name' => '--include',
  158. 'action' => 'StoreArray',
  159. 'description' => 'define an include path (can be repeated)',
  160. 'multiple' => true,
  161. ));
  162. $main->addOption('json', array(
  163. 'short_name' => '-j',
  164. 'long_name' => '--json',
  165. 'action' => 'StoreTrue',
  166. 'description' => 'turn on ProtoJson Javascript file generation',
  167. ));
  168. $main->addOption('protoc', array(
  169. 'long_name' => '--protoc',
  170. 'action' => 'StoreString',
  171. 'default' => 'protoc',
  172. 'description' => 'protoc compiler executable path',
  173. ));
  174. $main->addOption('skipImported', array(
  175. 'long_name' => '--skip-imported',
  176. 'action' => 'StoreTrue',
  177. 'default' => false,
  178. 'description' => 'do not generate imported proto files',
  179. ));
  180. $main->addOption('comments', array(
  181. 'long_name' => '--comments',
  182. 'action' => 'StoreTrue',
  183. 'description' => 'port .proto comments to generated code',
  184. ));
  185. $main->addOption('insertions', array(
  186. 'long_name' => '--insertions',
  187. 'action' => 'StoreTrue',
  188. 'description' => 'generate @@protoc insertion points',
  189. ));
  190. $main->addOption('define', array(
  191. 'short_name' => '-D',
  192. 'long_name' => '--define',
  193. 'action' => 'StoreArray',
  194. 'multiple' => true,
  195. 'description' => 'define a generator option (ie: -Dmultifile -Dsuffix=pb.php)',
  196. ));
  197. $main->addOption('verbose', array(
  198. 'short_name' => '-v',
  199. 'long_name' => '--verbose',
  200. 'action' => 'StoreTrue',
  201. 'description' => 'turn on verbose output',
  202. ));
  203. $main->addArgument('protos', array(
  204. 'multiple' => true,
  205. 'description' => 'proto files',
  206. ));
  207. try {
  208. echo 'Protobuf-PHP ' . Protobuf::VERSION . ' by Ivan -DrSlump- Montes' . PHP_EOL . PHP_EOL;
  209. $result = $main->parse();
  210. return $result;
  211. } catch (\Exception $e) {
  212. $main->displayError($e->getMessage());
  213. exit(1);
  214. }
  215. }
  216. }