diff options
author | Brion Vibber <brion@pobox.com> | 2009-11-06 14:31:39 +0100 |
---|---|---|
committer | Brion Vibber <brion@pobox.com> | 2009-11-06 16:17:31 +0100 |
commit | 4b7a36ea1932cfd2245560fa9949dc32fe2d2fc7 (patch) | |
tree | 05a338590e0402dd6ef14ad5d49fff8a84906cb0 | |
parent | 6f7e3053baefce2a27fba376b020c2ed555821b7 (diff) |
console.php terminal script provides interactive PHP console in StatusNet environment, handy for testing!
Uses readline for line input editing if available; falls back to bash+readline if not native, and takes fgets() in worst case.
Currently a bit awkward in that each input line is parsed separately, so loops and function defs have to be squished to one line.
-rwxr-xr-x | scripts/console.php | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/scripts/console.php b/scripts/console.php new file mode 100755 index 000000000..e65529a8d --- /dev/null +++ b/scripts/console.php @@ -0,0 +1,153 @@ +#!/usr/bin/env php +<?php +/* + * StatusNet - the distributed open-source microblogging tool + * Copyright (C) 2009, StatusNet, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +# Abort if called from a web server + +define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); + +$helptext = <<<ENDOFHELP +console.php - provide an interactive PHP interpreter for testing + +ENDOFHELP; + +require_once INSTALLDIR.'/scripts/commandline.inc'; + +if (function_exists('posix_isatty')) { + define('CONSOLE_INTERACTIVE', posix_isatty(0)); +} else { + // Windows? Assume we're on a terminal. :P + define('CONSOLE_INTERACTIVE', false); +} +if (CONSOLE_INTERACTIVE) { + define('CONSOLE_READLINE', function_exists('readline')); +} + +if (CONSOLE_READLINE && CONSOLE_INTERACTIVE && file_exists(CONSOLE_HISTORY)) { + define(CONSOLE_HISTORY, getenv("HOME") . "/.statusnet_console_history"); + readline_read_history(CONSOLE_HISTORY); +} + +function read_input_line($prompt) +{ + if (CONSOLE_INTERACTIVE) { + if (CONSOLE_READLINE) { + $line = readline($prompt); + readline_add_history($line); + return $line; + } else { + return readline_emulation($prompt); + } + } else { + return fgets(STDIN); + } +} + +/** + * On Unix-like systems where PHP readline extension isn't present, + * -cough- Mac OS X -cough- we can shell out to bash to do it for us. + * This lets us at least handle things like arrow keys, but we don't + * get any entry history. :( + * + * Shamelessly ripped from when I wrote the same code for MediaWiki. :) + * @author Brion Vibber <brion@status.net> + * + * @param string $prompt + * @return mixed string on success, false on fail or EOF + */ +function readline_emulation($prompt) +{ + if(file_exists(trim(shell_exec('which bash')))) { + $encPrompt = escapeshellarg($prompt); + $command = "read -er -p $encPrompt && echo \"\$REPLY\""; + $encCommand = escapeshellarg($command); + $metaCommand = "bash -c $encCommand"; + + // passthru passes our STDIN and TTY to the child... + // We can pull the returned string via output buffering. + ob_start(); + $retval = false; + passthru($metaCommand, $retval); + $line = ob_get_contents(); + ob_end_clean(); + + if ($retval == 0) { + return $line; + } elseif ($retval == 127) { + // Couldn't execute bash even though we thought we saw it. + // Shell probably spit out an error message, sorry :( + // Fall through to fgets()... + } else { + // EOF/ctrl+D + return false; + } + } + + // Fallback... we'll have no editing controls, EWWW + if (feof(STDIN)) { + return false; + } + print $prompt; + return fgets(STDIN); +} + +function console_help() +{ + print "Welcome to StatusNet's interactive PHP console!\n"; + print "Type some PHP code and it'll run!\n"; + print "\n"; + print "Note that PHP is cranky and you can easily kill your session.\n"; +} + + +$prompt = common_config('site', 'name') . '> '; +while (!feof(STDIN)) { + $line = read_input_line($prompt); + if ($line === false) { + print "\n"; + break; + } elseif ($line !== '') { + try { + if ($line == 'exit') { + break; + } elseif ($line == 'help') { + console_help(); + continue; + } + + // Let's do this + $result = eval($line); + if ($result === false) { + // parse error + } elseif ($result === null) { + // no return + } else { + // return value from eval'd code + var_export($result); + } + } catch(Exception $e) { + print get_class($e) . ": " . $e->getMessage() . "\n"; + } + } + print "\n"; +} + +if (CONSOLE_READLINE && CONSOLE_INTERACTIVE) { + @readline_write_history(CONSOLE_HISTORY); +} |