diff --git a/complete.php b/complete.php index e6fdee7..281c0b5 100644 --- a/complete.php +++ b/complete.php @@ -1,206 +1,432 @@ )|(?:>|::))?)$#i', $partial, $m ) ) { die( json_encode( false ) ); } + + $show_parameter = ( isset( $_POST['show_parameter'] ) && $_POST['show_parameter'] == 1 ) ? true : false; - $candidates = preg_grep( "/^{$m[1]}/", complete( $m[1] ) ); + $candidates = complete( $m[0], $show_parameter ); sort( $candidates ); - die( json_encode( ( array ) $candidates ) ); + die( json_encode( ( array )$candidates ) ); } else { error( 'Error initializing session.' ); } // returns array of possible matches -function complete( $string ) { - /** - * parse the line-buffer backwards to see if we have a - * - constant - * - function - * - variable - */ +function complete( $string, $show_parameter ) { + /** + * parse the line-buffer backwards to see if we have a + * - constant + * - function + * - variable + */ + + $m = array(); + + if ( preg_match( '#\$([A-Za-z0-9_]+)->#', $string, $a ) ) { + /* check for $o->... */ + $name = $a[1]; + + if ( isset( $GLOBALS[$name] ) && is_object( $GLOBALS[$name] ) ) { + $class_info = get_class_structure( $GLOBALS[$name] ); + + if ( isset( $class_info['methods'] ) && !empty( $class_info['methods'] ) ) { + foreach( $class_info['methods'] as $method_name => $method_info ) { + $m[] = class_method_info( $GLOBALS[$name], $method_name, $show_parameter ); + } + } - $m = array(); + if ( isset( $class_info['properties'] ) && !empty( $class_info['properties'] ) ) { + $m = array_merge( $m, class_property_info( $GLOBALS[$name] ) ); + } + // return the methods and properties of the object + return $m; + } + } else if ( preg_match( '#\$([A-Za-z0-9_]+)\[([^\]]+)\]->#', $string, $a ) ) { + /* check for $o[...]->... */ + $name = $a[1]; - if ( preg_match( '#\$([A-Za-z0-9_]+)->#', $string, $a ) ) { - /* check for $o->... */ - $name = $a[1]; + if ( isset( $GLOBALS[$name] ) && is_array( $GLOBALS[$name] ) && isset( $GLOBALS[$name][$a[2]] ) ) { + $class_info = get_class_structure( $GLOBALS[$name][$a[2]] ); - if ( isset( $GLOBALS[$name] ) && is_object( $GLOBALS[$name] ) ) { - $c = get_class_methods( $GLOBALS[$name] ); + if ( isset( $class_info['methods'] ) && !empty( $class_info['methods'] ) ) { + foreach( $class_info['methods'] as $method_name => $method_info ) { + $m[] = class_method_info( $GLOBALS[$name][$a[2]], $method_name, $show_parameter ); + } + } - foreach ( $c as $v ) { - $m[] = $v.'('; - } - $c = get_class_vars( get_class( $GLOBALS[$name] ) ); + if ( isset( $class_info['properties'] ) && !empty( $class_info['properties'] ) ) { + $m = array_merge( $m, class_property_info( $GLOBALS[$name][$a[2]] ) ); + } + // return the methods and properties of the object + return $m; + } + } else if ( preg_match( '#([A-Za-z0-9_]+)::#', $string, $a ) ) { + /* check for Class:: */ + $name = $a[1]; - foreach ( $c as $k => $v ) { - $m[] = $k; - } + if ( class_exists( $name, false ) ) { + $class_info = get_class_structure( $name ); - return $m; + if ( isset( $class_info['methods'] ) && !empty( $class_info['methods'] ) ) { + foreach( $class_info['methods'] as $method_name => $method_info ) { + $m[] = class_method_info( $name, $method_name, $show_parameter ); } - } else if ( preg_match( '#\$([A-Za-z0-9_]+)\[([^\]]+)\]->#', $string, $a ) ) { - /* check for $o[...]->... */ - $name = $a[1]; + } - if ( isset( $GLOBALS[$name] ) && - is_array( $GLOBALS[$name] ) && - isset( $GLOBALS[$name][$a[2]] ) ) { + if ( isset( $class_info['properties'] ) && !empty( $class_info['properties'] ) ) { - $c = get_class_methods( $GLOBALS[$name][$a[2]] ); + $m = array_merge( $m, class_property_info( $name ) ); + } + // return the methods and properties of the object + return $m; + } + } else if ( preg_match( '#\$([a-zA-Z]?[a-zA-Z0-9_]*)$#', $string, $g ) ) { + // loop through all the globals, only return those that match the search string + foreach( array_keys( $GLOBALS ) as $v ) { + if ( preg_match( "/^{$g[1]}/", $v ) ) { + $m[] = $v; + } + } + return $m; + } else if ( preg_match( '#new #', $string ) ) { + $c = get_declared_classes(); - foreach ( $c as $v ) { - $m[] = $v.'('; - } - $c = get_class_vars( get_class( $GLOBALS[$name][$a[2]] ) ); + foreach( $c as $name ) { + $class_info = get_class_structure( $name ); - foreach ( $c as $k => $v ) { - $m[] = $k; - } - return $m; + if ( isset( $class_info['methods'] ) && !empty( $class_info['methods'] ) ) { + foreach( $class_info['methods'] as $method_name => $method_info ) { + $m[] = class_method_info( $name, $method_name, $show_parameter ); } + } + } - } else if ( preg_match( '#([A-Za-z0-9_]+)::#', $string, $a ) ) { - /* check for Class:: */ - $name = $a[1]; + if ( isset( $class_info['properties'] ) && !empty( $class_info['properties'] ) ) { + $m = array_merge( $m, class_property_info( $name ) ); + } + // return the methods and properties of the class + return $m; + } else if ( preg_match( '#^:set #', $string ) ) { + foreach( PHP_Shell_Options::getInstance()->getOptions()as $v ) { + $m[] = $v; + } - if ( class_exists( $name, false ) ) { - $c = get_class_methods( $name ); + return $m; + } - foreach ( $c as $v ) { - $m[] = sprintf( '%s::%s(', $name, $v ); - } + $f = get_defined_functions(); + // loop through all the internal functions, only return those that match the search string + foreach( $f['internal'] as $v ) { + if ( preg_match( "/^{$string}/", $v ) ) { + $m[] = function_info( $v, $show_parameter ); + } + } + // loop through all the user functions, only return those that match the search string + foreach( $f['user'] as $v ) { + if ( preg_match( "/^{$string}/", $v ) ) { + $m[] = function_info( $v, $show_parameter ); + } + } - $cl = new ReflectionClass( $name ); - $c = $cl->getConstants(); + $c = get_declared_classes(); + // loop through all the declared classes only return those that match the search string + foreach( $c as $v ) { + if ( preg_match( "/^{$string}/", $v ) ) { + $m[] = $v.'::'; + } + } - foreach ( $c as $k => $v ) { - $m[] = sprintf( '%s::%s', $name, $k ); - } + $c = get_defined_constants(); + // loop through all the defined constants, only return those that match the search string + foreach( $c as $k => $v ) { + if ( preg_match( "/^{$string}/", $v ) ) { + $m[] = $v; + } + } - return $m; - } - } else if ( preg_match( '#\$([a-zA-Z]?[a-zA-Z0-9_]*)$#', $string ) ) { - $m = array_keys( $GLOBALS ); + /* taken from http://de3.php.net/manual/en/reserved.php */ + $reserved[] = 'abstract'; + $reserved[] = 'and'; + $reserved[] = ( $show_parameter ) ? 'array([ mixed $... ])' : 'array('; + $reserved[] = 'as'; + $reserved[] = 'break'; + $reserved[] = 'case'; + $reserved[] = 'catch'; + $reserved[] = 'class'; + $reserved[] = 'const'; + $reserved[] = 'continue'; + # $reserved[] = 'declare'; + $reserved[] = 'default'; + $reserved[] = ( $show_parameter ) ? 'die([$status])' : 'die('; + $reserved[] = 'do'; + $reserved[] = ( $show_parameter ) ? 'echo(string $arg1 [, string $... ])' : 'echo('; + $reserved[] = 'else'; + $reserved[] = 'elseif'; + $reserved[] = ( $show_parameter ) ? 'empty(mixed $var)' : 'empty('; + # $reserved[] = 'enddeclare'; + $reserved[] = ( $show_parameter ) ? 'eval(string $code_str)' : 'eval('; + $reserved[] = 'exception'; + $reserved[] = 'extends'; + $reserved[] = ( $show_parameter ) ? 'exit([$status])' : 'exit('; + $reserved[] = 'extends'; + $reserved[] = 'final'; + $reserved[] = ( $show_parameter ) ? 'for (expr1; expr2; expr3)' : 'for ('; + $reserved[] = ( $show_parameter ) ? 'foreach (array_expression as $key => $value | array_expression as $value)' : 'foreach ('; + $reserved[] = 'function'; + $reserved[] = 'global'; + $reserved[] = 'if'; + $reserved[] = 'implements'; + $reserved[] = 'include "'; + $reserved[] = 'include_once "'; + $reserved[] = 'interface'; + $reserved[] = ( $show_parameter ) ? 'isset(mixed $var [, mixed $var [, $... ]])' : 'isset('; + $reserved[] = ( $show_parameter ) ? 'list(mixed $varname [, mixed $... ])' : 'list('; + $reserved[] = 'new'; + $reserved[] = 'or'; + $reserved[] = ( $show_parameter ) ? 'print(string $arg)' : 'print('; + $reserved[] = 'private'; + $reserved[] = 'protected'; + $reserved[] = 'public'; + $reserved[] = 'require "'; + $reserved[] = 'require_once "'; + $reserved[] = 'return'; + $reserved[] = 'static'; + $reserved[] = ( $show_parameter ) ? 'switch (expr)' : 'switch ('; + $reserved[] = 'throw'; + $reserved[] = 'try'; + $reserved[] = ( $show_parameter ) ? 'unset(mixed $var [, mixed $var [, mixed $... ]])' : 'unset ('; + # $reserved[] = 'use'; + $reserved[] = 'var'; + $reserved[] = 'while'; + $reserved[] = 'xor'; + $reserved[] = '__FILE__'; + $reserved[] = '__FUNCTION__'; + $reserved[] = '__CLASS__'; + $reserved[] = '__LINE__'; + $reserved[] = '__METHOD__'; + + // loop through all the reserved keywords, only return those that match the search string + foreach( $reserved as $v ) { + if ( preg_match( "/^{$string}/", $v ) ) { + $m[] = $v; + } + } - return $m; - } else if ( preg_match( '#new #', $string ) ) { - $c = get_declared_classes(); + return $m; +} - foreach ( $c as $v ) { - $m[] = $v.'('; - } +/* +This function will return an array that describe the function +array( + 'name' => 'function_name', + 'parameters' => array( + '$parameter1' => array( + 'optional' => bool, + 'default_value' => '' + ),... + ) + ) + */ +function get_function_structure( $function_name ) { + // variable to store class information + $function_info; + + $reflected_function = new ReflectionFunction( $function_name ); + // function name + $function_info['name'] = $reflected_function->getName(); + + // loop through all the class method + foreach( $reflected_function->getParameters()as $function_parameter ) { + // method name, add &, if it is pass by reference + $parameter_name = ( $function_parameter->isPassedByReference() ) ? '&' : ''; + $parameter_name .= '$'.$function_parameter->getName(); + + $function_info['parameters'][$parameter_name] = array( 'optional' => $function_parameter->isOptional(), + // if the function is not defined by the user, the reflection class cannot determine the default value for it's parameters + 'default_value' => ( $function_parameter->isOptional() && + $reflected_function->isUserDefined() ) ? $function_parameter + ->getDefaultValue(): '' + ); + } + return $function_info; +} + +// This function will return a nicely formatted string describing the function +function function_info( $function_name, $show_parameter = true ) { + // load the function structure + $function_info = get_function_structure( $function_name ); + + $string = $function_info['name']; - return $m; - } else if ( preg_match( '#^:set #', $string ) ) { - foreach ( PHP_Shell_Options::getInstance()->getOptions() as $v ) { - $m[] = $v; + if ( $show_parameter ) { + $string .= '('; + + $params; + if ( isset( $function_info['parameters'] ) && !empty( $function_info['parameters'] ) ) { + foreach( $function_info['parameters'] as $parameter_name => $parameter_info ) { + if ( $parameter_info['optional'] ) { + $params[] = '['.$parameter_name.' = \''.$parameter_info['default_value'].'\']'; + } else { + $params[] = $parameter_name; } + } - return $m; + $string .= ( count( $params ) ) ? implode( ', ', $params ): ''; } - $f = get_defined_functions(); + $string .= ')'; + } else { + $string .= '('; + } + + return $string; +} - foreach ( $f['internal'] as $v ) { - $m[] = $v.'('; +/* + This function will return an array that describe the class structure + array( + 'name' => 'class_name', + 'parents' => array( + 'type',... + ), + 'properties' => array( + array( + 'property1' => array( + + ),... + ),... + } + , + 'methods' => array( + 'method1' => array( + 'modifiers' => array( + 'type',... + ), + 'parameters' => array( + '$parameter1' => array( + 'optional' => bool, + 'default_value' => '' + ),... + ) + ),... + ) +*/ +function get_class_structure( $class_name ) { + // variable to store class information + $class_info; + + $reflected_class = new ReflectionClass( $class_name ); + // class name + $class_info['name'] = $reflected_class->getName(); + + // loop through and store add parents + $reflected_parent_class = $reflected_class->getParentClass(); + if ( isset( $reflected_parent_class ) && !empty( $reflected_parent_class ) ) { + foreach( $reflected_parent_class as $class_parent ) { + $class_info['parents'][] = $class_parent; } + } + + foreach( $reflected_class->getProperties()as $property ) { + // property name and it's modifier + $class_info['properties'][$property->name]['modifiers'] = Reflection::getModifierNames( $property->getModifiers() ); + } - foreach ( $f['user'] as $v ) { - $m[] = $v.'('; + foreach( $reflected_class->getDefaultProperties()as $property_name => $default_value ) { + // property name and it's modifier + // property default value + $class_info['properties'][$property_name]['default_value'] = $default_value; + } + + // loop through all the class method + foreach( $reflected_class->getMethods()as $method ) { + // method name and it's modifier + $class_info['methods'][$method->name]['modifiers'] = Reflection::getModifierNames( $method->getModifiers() ); + + + // loop through each of the method parameter + foreach( $method->getParameters()as $method_parameter ) { + // parameter name, add &, if it is pass by reference + $parameter_name = ( $method_parameter->isPassedByReference() ) ? '&' : ''; + $parameter_name .= '$'.$method_parameter->getName(); + + $class_info['methods'][$method->name]['parameters'][$parameter_name] = array( 'optional' => $method_parameter->isOptional(), + // if the function is not defined by the user, the reflection class cannot determine the default value for it's parameters + 'default_value' => ( $method_parameter->isOptional() && $method + ->isUserDefined() ) ? $method_parameter->getDefaultValue(): '' + ); } + } + return $class_info; +} - $c = get_declared_classes(); +// return a nicely formatted string describing a particular class method +function class_method_info( $class_name, $method_name, $show_parameter ) { + // load the class structure + $class_info = get_class_structure( $class_name ); - foreach ( $c as $v ) { - $m[] = $v.'::'; - } - - $c = get_defined_constants(); - - foreach ( $c as $k => $v ) { - $m[] = $k; - } - - /* taken from http://de3.php.net/manual/en/reserved.php */ - $m[] = 'abstract'; - $m[] = 'and'; - $m[] = 'array('; - $m[] = 'as'; - $m[] = 'break'; - $m[] = 'case'; - $m[] = 'catch'; - $m[] = 'class'; - $m[] = 'const'; - $m[] = 'continue'; - # $m[] = 'declare'; - $m[] = 'default'; - $m[] = 'die('; - $m[] = 'do'; - $m[] = 'echo('; - $m[] = 'else'; - $m[] = 'elseif'; - $m[] = 'empty('; - # $m[] = 'enddeclare'; - $m[] = 'eval('; - $m[] = 'exception'; - $m[] = 'extends'; - $m[] = 'exit('; - $m[] = 'extends'; - $m[] = 'final'; - $m[] = 'for ('; - $m[] = 'foreach ('; - $m[] = 'function'; - $m[] = 'global'; - $m[] = 'if'; - $m[] = 'implements'; - $m[] = 'include "'; - $m[] = 'include_once "'; - $m[] = 'interface'; - $m[] = 'isset('; - $m[] = 'list('; - $m[] = 'new'; - $m[] = 'or'; - $m[] = 'print('; - $m[] = 'private'; - $m[] = 'protected'; - $m[] = 'public'; - $m[] = 'require "'; - $m[] = 'require_once "'; - $m[] = 'return'; - $m[] = 'static'; - $m[] = 'switch ('; - $m[] = 'throw'; - $m[] = 'try'; - $m[] = 'unset('; - # $m[] = 'use'; - $m[] = 'var'; - $m[] = 'while'; - $m[] = 'xor'; - $m[] = '__FILE__'; - $m[] = '__FUNCTION__'; - $m[] = '__CLASS__'; - $m[] = '__LINE__'; - $m[] = '__METHOD__'; + $string; - return $m; + if ( isset( $class_info['methods'] ) && !empty( $class_info['methods'] ) ) { + + $method_info = $class_info['methods'][$method_name]; + + $string = implode( ' ', $method_info['modifiers'] ).' '.$method_name.'('; + + if ( $show_parameter ) { + + // loop through all the method parameters + $params; + + if ( isset( $method_info['parameters'] ) && !empty( $method_info['parameters'] ) ) { + foreach( $method_info['parameters'] as $parameter_name => $parameter_info ) { + if ( $parameter_info['optional'] ) { + $params[] = '['.$parameter_name.' = \''.$parameter_info['default_value'].'\']'; + } else { + $params[] = $parameter_name; + } + } + $string .= ( count( $params ) ) ? implode( ', ', $params ): ''; + } + } + $string .= ')'; + } + return $string; +} + +// return a nicely formatted string describing a particular class methods and properties +function class_property_info( $class_name ) { + // load the class structure + $properties_info = get_class_structure( $class_name ); + + $a = array(); + + if ( isset( $properties_info['properties'] ) && !empty( $properties_info['properties'] ) ) { + foreach( $properties_info['properties'] as $property_name => $property_info ) { + $s = implode( ' ', $properties_info['properties'][$property_name]['modifiers'] ).' '.$property_name; + $s .= ( isset( $properties_info['properties'][$property_name]['default_value'] ) ) ? ' = \''.$properties_info['properties'][$property_name]['default_value'].'\'': ''; + $a[] = $s; + } + } + return $a; } -?> +?> \ No newline at end of file diff --git a/console.css b/console.css index 3bffe82..b525d4d 100644 --- a/console.css +++ b/console.css @@ -56,4 +56,14 @@ #wrapper #shell a:link, #wrapper #shell a:visited { color: #FFFFFF; +} +#wrapper #shell_control_panel { + font-family: Tahoma,Arial; + font-size: 10pt; + text-align:right; + color: #333; + background: none repeat scroll 0 0 #E6E8F2; + border-top: 1px solid #EEEFEE; + border-bottom: 1px solid #EEEFEE; + padding: 2px; } \ No newline at end of file diff --git a/console.js b/console.js index 12f89a8..d931498 100644 --- a/console.js +++ b/console.js @@ -86,10 +86,11 @@ } else if (j.length == 1) { input.val(j).focus(); } else { - // print 3-column listing of array values + // print 3-column listing of array values, 1-column is return full parameter buffer_to_longest(j); while (j.length > 0) { - var line = j.splice(0,3); + var column = (getCookie("wordpress_console_show_parameter") == 1) ? 1 : 3 ; + var line = j.splice(0,column); self.print(line.join(" ")); } self.doPrompt(); @@ -150,7 +151,9 @@ case "help": case "?": self.print("\nWhat's New:\n" + " Keyboard shortcuts: ctrl+l = clear, ctrl+a = goto start, ctrl+e = goto end\n" + - " Admin functions: add_user(), wp_delete_user(), and friends!\n" + + " Press Tab key for auto completion\n" + + " Admin functions: add_user(), wp_delete_user(), and friends, support native PHP as well!\n" + + " 'ClassName::' without the quotes + Tab Key will return result for the class\n" + "\n" + "Special Commands:\n" + " clear (c) = clears the console output\n" + @@ -216,7 +219,8 @@ type: "POST", dataType: "json", data: { - "root": self.root + "root": self.root, + 'show_parameter': getCookie("wordpress_console_show_parameter"), } }; var key = null; @@ -316,8 +320,58 @@ range.select(); } } - + $(function() { window.wpConsole = new $.wpConsole(); }); + + $(document).ready(function() { + $("#shell_show_parameter_chkbx").checked = getCookie("wordpress_console_show_parameter"); + + $("#shell_show_parameter_chkbx").click(function(){ + + if ($("#shell_show_parameter_chkbx").is(":checked")) { + setCookie("wordpress_console_show_parameter", 1, 360); + } + else { + setCookie("wordpress_console_show_parameter", 0, 360); + } + }); + }); + + function setCookie(c_name, value, expiredays) { + var exdate = new Date(); + exdate.setDate(exdate.getDate() + expiredays); + + document.cookie = c_name + "=" + escape(value) + ((expiredays==null) ? "" : ";expires=" + exdate.toGMTString()); + + c_name = null; + value = null; + expiredays = null; + exdate = null; + } + + function getCookie(c_name) { + var value = " "; + + if (document.cookie.length > 0) { + var c_start = document.cookie.indexOf(c_name + "="); + if (c_start != -1) { + c_start = c_start + c_name.length + 1; + var c_end = document.cookie.indexOf(";", c_start); + if (c_end == -1) { + c_end = document.cookie.length; + } + value = unescape(document.cookie.substring(c_start, c_end)); + c_end = null; + } + c_start = null; + } + + c_name = null; + + return value; + } + })(jQuery); + diff --git a/reload.php b/reload.php index 605e49d..2a07853 100644 --- a/reload.php +++ b/reload.php @@ -7,6 +7,8 @@ if (isset($_SESSION['partial'])) { unset($_SESSION['partial']); } - +if (isset($_SESSION['code'])) { + unset($_SESSION['code']); +} print json_encode(array('output' => "Success!")); ?> \ No newline at end of file diff --git a/wordpress-console.php b/wordpress-console.php index 8aca93c..a378a9f 100644 --- a/wordpress-console.php +++ b/wordpress-console.php @@ -62,6 +62,11 @@ function admin() { ?>

WordPress Console: "?" for help menu

+
+
+ +
+