]> git.mxchange.org Git - quix0rs-gnu-social.git/commitdiff
console.php terminal script provides interactive PHP console in StatusNet environment...
authorBrion Vibber <brion@pobox.com>
Fri, 6 Nov 2009 13:31:39 +0000 (14:31 +0100)
committerBrion Vibber <brion@pobox.com>
Fri, 6 Nov 2009 15:17:31 +0000 (16:17 +0100)
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.

scripts/console.php [new file with mode: 0755]

diff --git a/scripts/console.php b/scripts/console.php
new file mode 100755 (executable)
index 0000000..e65529a
--- /dev/null
@@ -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);
+}