console.php 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. #!/usr/bin/env php
  2. <?php
  3. /*
  4. * StatusNet - the distributed open-source microblogging tool
  5. * Copyright (C) 2009, StatusNet, Inc.
  6. *
  7. * This program is free software: you can redistribute it and/or modify
  8. * it under the terms of the GNU Affero General Public License as published by
  9. * the Free Software Foundation, either version 3 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU Affero General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Affero General Public License
  18. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20. // Abort if called from a web server
  21. define('INSTALLDIR', realpath(dirname(__FILE__) . '/..'));
  22. $helptext = <<<ENDOFHELP
  23. console.php - provide an interactive PHP interpreter for testing
  24. ENDOFHELP;
  25. require_once INSTALLDIR.'/scripts/commandline.inc';
  26. // Assume we're on a terminal if on Windows, otherwise posix_isatty tells us.
  27. define('CONSOLE_INTERACTIVE', !function_exists('posix_isatty') || posix_isatty(0));
  28. define('CONSOLE_READLINE', CONSOLE_INTERACTIVE && function_exists('readline'));
  29. if (CONSOLE_READLINE && CONSOLE_INTERACTIVE) {
  30. define('CONSOLE_HISTORY', getenv("HOME") . "/.statusnet_console_history");
  31. if (file_exists(CONSOLE_HISTORY)) {
  32. readline_read_history(CONSOLE_HISTORY);
  33. }
  34. }
  35. function read_input_line($prompt)
  36. {
  37. if (CONSOLE_INTERACTIVE) {
  38. if (CONSOLE_READLINE) {
  39. $line = readline($prompt);
  40. if (trim($line) != '') {
  41. readline_add_history($line);
  42. if (defined('CONSOLE_HISTORY')) {
  43. // Save often; it's easy to hit fatal errors.
  44. readline_write_history(CONSOLE_HISTORY);
  45. }
  46. }
  47. return $line;
  48. } else {
  49. return readline_emulation($prompt);
  50. }
  51. } else {
  52. return fgets(STDIN);
  53. }
  54. }
  55. /**
  56. * On Unix-like systems where PHP readline extension isn't present,
  57. * -cough- Mac OS X -cough- we can shell out to bash to do it for us.
  58. * This lets us at least handle things like arrow keys, but we don't
  59. * get any entry history. :(
  60. *
  61. * Shamelessly ripped from when I wrote the same code for MediaWiki. :)
  62. * @author Brion Vibber <brion@status.net>
  63. *
  64. * @param string $prompt
  65. * @return mixed string on success, false on fail or EOF
  66. */
  67. function readline_emulation($prompt)
  68. {
  69. if(CONSOLE_INTERACTIVE && file_exists(trim(shell_exec('which bash')))) {
  70. $encPrompt = escapeshellarg($prompt);
  71. $command = "read -er -p $encPrompt && echo \"\$REPLY\"";
  72. $encCommand = escapeshellarg($command);
  73. $metaCommand = "bash -c $encCommand";
  74. // passthru passes our STDIN and TTY to the child...
  75. // We can pull the returned string via output buffering.
  76. ob_start();
  77. $retval = false;
  78. passthru($metaCommand, $retval);
  79. $line = ob_get_contents();
  80. ob_end_clean();
  81. if ($retval == 0) {
  82. return $line;
  83. } elseif ($retval == 127) {
  84. // Couldn't execute bash even though we thought we saw it.
  85. // Shell probably spit out an error message, sorry :(
  86. // Fall through to fgets()...
  87. } else {
  88. // EOF/ctrl+D
  89. return false;
  90. }
  91. }
  92. // Fallback... we'll have no editing controls, EWWW
  93. if (feof(STDIN)) {
  94. return false;
  95. }
  96. if (CONSOLE_INTERACTIVE) {
  97. print $prompt;
  98. }
  99. return fgets(STDIN);
  100. }
  101. function console_help()
  102. {
  103. print "Welcome to StatusNet's interactive PHP console!\n";
  104. print "Type some PHP code and it'll execute...\n";
  105. print "\n";
  106. print "Hint: return a value of any type to output it via var_export():\n";
  107. print " \$profile = new Profile();\n";
  108. print " \$profile->find();\n";
  109. print " \$profile->fetch();\n";
  110. print " return \$profile;\n";
  111. print "\n";
  112. print "Note that PHP is cranky and you can easily kill your session by mistyping.\n";
  113. print "\n";
  114. print "Type ctrl+D or enter 'exit' to exit.\n";
  115. }
  116. if (CONSOLE_INTERACTIVE) {
  117. print "StatusNet interactive PHP console... type ctrl+D or enter 'exit' to exit.\n";
  118. $prompt = common_config('site', 'name') . '> ';
  119. } else {
  120. $prompt = '';
  121. }
  122. while (!feof(STDIN)) {
  123. $line = read_input_line($prompt);
  124. if ($line === false) {
  125. if (CONSOLE_INTERACTIVE) {
  126. print "\n";
  127. }
  128. break;
  129. } elseif ($line !== '') {
  130. try {
  131. if (trim($line) == 'exit') {
  132. break;
  133. } elseif (trim($line) == 'help') {
  134. console_help();
  135. continue;
  136. }
  137. // Let's do this!
  138. $result = eval($line);
  139. if ($result === false) {
  140. // parse error
  141. } elseif ($result === null) {
  142. // no return
  143. } else {
  144. // return value from eval'd code
  145. var_export($result);
  146. }
  147. } catch(Exception $e) {
  148. print get_class($e) . ": " . $e->getMessage() . "\n";
  149. }
  150. }
  151. if (CONSOLE_INTERACTIVE) {
  152. print "\n";
  153. }
  154. }