|
@@ -0,0 +1,897 @@
|
|
|
+<?php
|
|
|
+
|
|
|
+ * PHP-GTK Stub generator
|
|
|
+ *
|
|
|
+ * This program can be run on any system with PHP-GTK installed.
|
|
|
+ * It generates a skeleton file containing all classes present
|
|
|
+ * in the currently active PHP-GTK extension, with their
|
|
|
+ * constants, methods, and signatures thereof.
|
|
|
+ *
|
|
|
+ * This file can be installed on various IDEs to enable code
|
|
|
+ * completion when the IDE does not use the PHP-GTK interpreter
|
|
|
+ * itself.
|
|
|
+ *
|
|
|
+ * Installation on Eclipse PDT
|
|
|
+ * To enable code completion for PHP-GTK on Eclipse PDT:
|
|
|
+ * 1. create a "PHP-GTK Lookup" PHP project
|
|
|
+ * 2. run this file and save its output as a PHP file, like "php-reference.php"
|
|
|
+ * 3. place the generated file in a directory of its own, within the "PHP Lookup" project
|
|
|
+ * 4. When creating a new PHP Project, add the "PHP Lookup" project in the list of includes
|
|
|
+ *
|
|
|
+ * Similar steps should work in other IDEs
|
|
|
+ *
|
|
|
+ * Do NOT include/require it in your actual PHP source code:
|
|
|
+ * it would clash with the actual PHP-GTK symbols.
|
|
|
+ *
|
|
|
+ * This version has been tested on the following standard PGP-GTK2 builds:
|
|
|
+ * - 2.0.0-dev "leap day special"
|
|
|
+ * - 2.0.1 "you knew this was coming"
|
|
|
+ *
|
|
|
+ * @copyright Frederic G. MARAND
|
|
|
+ * @license CeCILL Version 2.0
|
|
|
+ * @link http:
|
|
|
+ * @version $Id: Gtk_Dumper.php,v 1.1 2008-05-24 06:40:51 cvs Exp $
|
|
|
+ */
|
|
|
+
|
|
|
+error_reporting(E_ALL | E_STRICT);
|
|
|
+
|
|
|
+define('GTK_DUMPER_VERSION', '$Id: Gtk_Dumper.php,v 1.1 2008-05-24 06:40:51 cvs Exp $');
|
|
|
+
|
|
|
+
|
|
|
+ * Obtain the reflection info about the PHP-GTK extension
|
|
|
+ * @return string
|
|
|
+ */
|
|
|
+function getExtensionInfo()
|
|
|
+ {
|
|
|
+ $arExtensions = get_loaded_extensions();
|
|
|
+ if (!in_array('php-gtk', $arExtensions))
|
|
|
+ {
|
|
|
+ die('PHP-GTK not loaded');
|
|
|
+ }
|
|
|
+ $ret = "/**\n"
|
|
|
+ . " * PHP-GTK skeletons, generated from the extension using: \n"
|
|
|
+ . " * " . GTK_DUMPER_VERSION . PHP_EOL
|
|
|
+ . " * \n";
|
|
|
+
|
|
|
+ $ext = new ReflectionExtension('php-gtk');
|
|
|
+ $version = $ext->getVersion()
|
|
|
+ ? $ext->getVersion()
|
|
|
+ : 'No version info';
|
|
|
+ $ret .= sprintf
|
|
|
+ (
|
|
|
+ " * Name : %s\n" .
|
|
|
+ " * Version : %s\n" .
|
|
|
+ " * INI entries : %d\n",
|
|
|
+ $ext->getName(),
|
|
|
+ $version,
|
|
|
+ count($ext->getINIEntries())
|
|
|
+ );
|
|
|
+ foreach ($ext->getINIEntries() as $entry => $value)
|
|
|
+ {
|
|
|
+ $ret .= ' * - ' . $entry . ' = ' . $value . PHP_EOL;
|
|
|
+ }
|
|
|
+ $ret .= " */\n";
|
|
|
+ return $ret;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * internal use class to return the origin of a class, interface, method, object, or function
|
|
|
+ */
|
|
|
+class GtkOriginator
|
|
|
+ {
|
|
|
+
|
|
|
+ * @param ReflectionFunctionAbstract $x
|
|
|
+ */
|
|
|
+ public function __construct($x)
|
|
|
+ {
|
|
|
+ $arMethodNames = get_class_methods($x);
|
|
|
+ if (!in_array('isInternal', $arMethodNames) or !in_array('isUserDefined', $arMethodNames))
|
|
|
+ {
|
|
|
+ throw new ReflectionException('GtkOriginator() takes classes implementing isInternal()/isUserDefined(). '
|
|
|
+ . get_class($x)
|
|
|
+ . print_r($arMethodNames, true));
|
|
|
+ }
|
|
|
+ $this->x = $x;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * A consistency-checked readable form of the origin modifier
|
|
|
+ *
|
|
|
+ * @return string
|
|
|
+ */
|
|
|
+ public function getOrigin()
|
|
|
+ {
|
|
|
+ $mask = $this->x->isInternal() << 1 | $this->x->isUserDefined();
|
|
|
+ switch ($mask)
|
|
|
+ {
|
|
|
+ case 0: $ret = 'unknown_origin'; break;
|
|
|
+ case 1: $ret = 'user-defined' ; break;
|
|
|
+ case 2: $ret = 'internal' ; break;
|
|
|
+ case 3:
|
|
|
+ throw new ReflectionException("Inconsistent origin for $this->x->name().");
|
|
|
+ break;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ return $ret;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * The PHP-GTK 2.0 extension has some specific quirks:
|
|
|
+ * - only a limited subset of parameter attributes is used
|
|
|
+ * - optional parameters are visible, but not their default values
|
|
|
+ * - some parameters have invalid names: the first parameter in
|
|
|
+ * GtkColorMap::alloc_color is "$color OR red"
|
|
|
+ * - some parameters are named as $... to denote extended parameter lists
|
|
|
+ *
|
|
|
+ * Number of parameters with given attribute combinations in version 2.0.0.0 of php_gtk.dll:
|
|
|
+ * - none: 21098
|
|
|
+ * - allowsNull: 2 (GtkIconView::set_drag_dest_item($pos) and Gdk::event_request_motions($event))
|
|
|
+ * - isOptional: 2412
|
|
|
+ * - valid class name: 132
|
|
|
+ * - valid class name + allowsNull: 5888
|
|
|
+ * - valid class name + isOptional: 1 (GtkIconView::__construct(GtkTreeModel $model))
|
|
|
+ * - valid class name + isOptional + allowsNull: 76
|
|
|
+ */
|
|
|
+class GtkReflectionParameter extends ReflectionParameter
|
|
|
+ {
|
|
|
+
|
|
|
+ * Format the parameter as a valid PHP declaration.
|
|
|
+ * The means the information is not necessarily complete
|
|
|
+ * in comparison with the one available from __toString()
|
|
|
+ *
|
|
|
+ * The return value is an assoc array with two keys:
|
|
|
+ * - valid: if true, this is a valid PHP parameter declaration; otherwise it is a PHP comment containing a declaration
|
|
|
+ * - string: the actual result
|
|
|
+ *
|
|
|
+ * "Invalid" results typically happen when a parameter is optional, but
|
|
|
+ * without a default value. In that case, the comment contains the
|
|
|
+ * parameter declaration within a comment, meaning it cannot be inserted
|
|
|
+ * as such in a PHP function declaration.
|
|
|
+ *
|
|
|
+ * @return array
|
|
|
+ */
|
|
|
+ public function asPhp()
|
|
|
+ {
|
|
|
+ $ret = '';
|
|
|
+
|
|
|
+ $bitDA = $this->isDefaultValueAvailable() ? 1 : 0;
|
|
|
+ $bitAN = $this->allowsNull() ? 1 : 0;
|
|
|
+ $bitOP = $this->isOptional() ? 1 : 0;
|
|
|
+
|
|
|
+ * An exception can occur on getClass():
|
|
|
+ * GtkIconView::set_drag_dest_item($pos)
|
|
|
+ * getting its class throws a ReflectionException:
|
|
|
+ * "Class GtkIconViewDropPosition does not exist"
|
|
|
+ * so we ignore it.
|
|
|
+ */
|
|
|
+ try
|
|
|
+ {
|
|
|
+ $typeName = $this->getClass();
|
|
|
+ }
|
|
|
+ catch (ReflectionException $e)
|
|
|
+ {
|
|
|
+ $typeName = NULL;
|
|
|
+ }
|
|
|
+ $bitCN = empty($typeName) ? 0 : 1;
|
|
|
+ $bitAR = $this->isArray() ? 1 : 0;
|
|
|
+ $bitDN = $bitDA
|
|
|
+ ? (($this->getDefaultValue() === NULL) ? 1: 0)
|
|
|
+ : 0;
|
|
|
+ $mask= $bitDA + ($bitAN << 1) + ($bitOP << 2) + ($bitCN << 3) + ($bitAR << 4) + ($bitDN << 5);
|
|
|
+
|
|
|
+
|
|
|
+ * @todo sanitize name
|
|
|
+ */
|
|
|
+ $name = $this->name;
|
|
|
+ $name = str_replace(' ', '_', $name);
|
|
|
+
|
|
|
+
|
|
|
+ $ret = array('valid' => TRUE);
|
|
|
+ switch ($mask)
|
|
|
+ {
|
|
|
+ case 0:
|
|
|
+ $ret['string'] = '$' . $name;
|
|
|
+ break;
|
|
|
+ case 2:
|
|
|
+ try
|
|
|
+ {
|
|
|
+ $def = var_export($this->getDefaultValue(), TRUE);
|
|
|
+ }
|
|
|
+ catch (ReflectionException $e)
|
|
|
+ {
|
|
|
+ $def = 'NULL /* Exception: ' . $e->getMessage() . ' */';
|
|
|
+ }
|
|
|
+ $ret['string'] = "\$$name = " . $def;
|
|
|
+ break;
|
|
|
+ case 4:
|
|
|
+ $ret['string'] = "/* \$$name */";
|
|
|
+ $ret['valid'] = FALSE;
|
|
|
+ break;
|
|
|
+ case 8:
|
|
|
+ $ret['string'] = $this->getClass()->name . ' $' . $name;
|
|
|
+ break;
|
|
|
+ case 10:
|
|
|
+ $ret['string'] = $this->getClass()->name . ' $' . $name . " /* or NULL */";
|
|
|
+ break;
|
|
|
+ case 12:
|
|
|
+ $ret['string'] = '/* ' . $this->getClass()->name . ' $' . $name . ' */';
|
|
|
+ $ret['valid'] = FALSE;
|
|
|
+ case 14:
|
|
|
+ $ret['string'] = $this->getClass()->name . ' $' . $name . ' = NULL';
|
|
|
+ break;
|
|
|
+ case 16:
|
|
|
+ $ret['string'] = 'array $' . $name;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ throw new ReflectionException("Unhandled combination of attributes " . sprintf('0x%02X', $mask) . " for parameter $name.");
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ return $ret;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * Extends the ReflectionMethod to enable generation of PHP source code
|
|
|
+ * instead of pseudo-readable code as in __toString
|
|
|
+ *
|
|
|
+ */
|
|
|
+class GtkReflectionMethod extends ReflectionMethod
|
|
|
+ {
|
|
|
+
|
|
|
+ * PHP-GTK2 includes some problematic method names, which clash
|
|
|
+ * with reserver words in PHP (foreach, unset)
|
|
|
+ *
|
|
|
+ * @param string $name
|
|
|
+ * @return string
|
|
|
+ */
|
|
|
+ protected function fixName($name)
|
|
|
+ {
|
|
|
+
|
|
|
+ * Fix PHP-GTK 2.0.0.0 special names
|
|
|
+ */
|
|
|
+ switch ($name)
|
|
|
+ {
|
|
|
+ case 'foreach':
|
|
|
+ $ret = 'foreach_method';
|
|
|
+ break;
|
|
|
+ case 'unset':
|
|
|
+ $ret = 'unset_method';
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ $ret = $name;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ return $ret;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * Some stats from PHP-GTK 2.0.0.0:
|
|
|
+ *
|
|
|
+ * - 0x0100 plain: 29443
|
|
|
+ * - 0x0101 static: 2539
|
|
|
+ * - 0x0104 public final: 24
|
|
|
+ * - 0x0108 public | undocumented 0x0008: 479
|
|
|
+ * - 0x2100 public | undocumented 0x2000: 243 (all of them constructors)
|
|
|
+ * - 0x2400 private | undocumented 0x2000: 2 (both of them constructors)
|
|
|
+ * - 0x8404 private final | undocumented 0x8000: 4 (PhpGtk*Exception::__clone())
|
|
|
+ *
|
|
|
+ * @return string
|
|
|
+ */
|
|
|
+ public function asPhp()
|
|
|
+ {
|
|
|
+ $ret = ' ';
|
|
|
+
|
|
|
+
|
|
|
+ * built a more complete attribute list tant getModifiers()
|
|
|
+ */
|
|
|
+ $bitST = $this->isStatic() ? ReflectionMethod::IS_STATIC : 0;
|
|
|
+ $bitAB = $this->isAbstract() ? ReflectionMethod::IS_ABSTRACT : 0;
|
|
|
+ $bitFI = $this->isFinal() ? ReflectionMethod::IS_FINAL : 0;
|
|
|
+ $bitPU = $this->isPublic() ? ReflectionMethod::IS_PUBLIC : 0;
|
|
|
+ $bitPO = $this->isProtected() ? ReflectionMethod::IS_PROTECTED: 0;
|
|
|
+ $bitPV = $this->isPrivate() ? ReflectionMethod::IS_PRIVATE : 0;
|
|
|
+ $bitCO = $this->isConstructor() ? 0x00004000 : 0;
|
|
|
+ $bitDE = $this->isDeprecated() ? ReflectionFunction::IS_DEPRECATED: 0;
|
|
|
+ $bitDS = $this->isDestructor() ? 0x10000000 : 0;
|
|
|
+
|
|
|
+ * PHP-GTK2 does not fill in these elements, so we do not use them:
|
|
|
+ *
|
|
|
+ 'file ' . $this->getFileName()
|
|
|
+ 'startLine ' . $this->getStartLine()
|
|
|
+ 'endLine ' . $this->getEndLine()
|
|
|
+ 'docComment ' . $this->getDocComment()
|
|
|
+ 'static Vars ' . implode(', ', $this->getStaticVariables())
|
|
|
+ */
|
|
|
+
|
|
|
+ $mask = $bitST | $bitAB | $bitFI | $bitPU | $bitPO | $bitPV | $bitCO | $bitDE | $bitDS
|
|
|
+ | $this->getModifiers();
|
|
|
+
|
|
|
+ if ($bitCO and $this->name != '__construct')
|
|
|
+ {
|
|
|
+ throw ReflectionException("Incorrectly named constructor $this->name.");
|
|
|
+ }
|
|
|
+ if ($bitDS and $this->name != '__destruct')
|
|
|
+ {
|
|
|
+ throw ReflectionException("Incorrectly named destructor $this->name.");
|
|
|
+ }
|
|
|
+
|
|
|
+ $name = $this->fixName($this->name);
|
|
|
+ $isInterface = $this->getDeclaringClass()->isInterface();
|
|
|
+ if ($isInterface)
|
|
|
+ {
|
|
|
+ if (!($mask & self::IS_ABSTRACT))
|
|
|
+ {
|
|
|
+ throw("Non-abstract method $name in interface declaration.");
|
|
|
+ }
|
|
|
+ $mask &= !(self::IS_ABSTRACT
|
|
|
+ | self::IS_PUBLIC
|
|
|
+ | self::IS_PROTECTED
|
|
|
+ | self::IS_PRIVATE
|
|
|
+ );
|
|
|
+ }
|
|
|
+ $origin = new GtkOriginator($this);
|
|
|
+ $origin = $origin->getOrigin();
|
|
|
+
|
|
|
+ switch ($mask)
|
|
|
+ {
|
|
|
+ case 0x0000:
|
|
|
+ $ret .= "/* $origin */ function ";
|
|
|
+ break;
|
|
|
+ case 0x0100:
|
|
|
+ $ret .= "public /* $origin */ function ";
|
|
|
+ break;
|
|
|
+ case 0x0101:
|
|
|
+ $ret .= "static public /* $origin */ function ";
|
|
|
+ break;
|
|
|
+ case 0x0102:
|
|
|
+ $ret .= "abstract public /* $origin */ function ";
|
|
|
+ break;
|
|
|
+ case 0x0103:
|
|
|
+ $ret .= "static abstract public /* $origin */ function ";
|
|
|
+ break;
|
|
|
+ case 0x0104:
|
|
|
+ $ret .= "final public /* $origin */ function ";
|
|
|
+ break;
|
|
|
+ case 0x0108:
|
|
|
+ $ret .= "public /* 0x0008 $origin */ function ";
|
|
|
+ break;
|
|
|
+ case 0x2102:
|
|
|
+ $ret .= "public /* 0x2000 $origin */ function ";
|
|
|
+ break;
|
|
|
+ case 0x6100:
|
|
|
+ $ret .= "public /* 0x6000 $origin */ function ";
|
|
|
+ break;
|
|
|
+ case 0x6400:
|
|
|
+ $ret .= "private /* 0x6000 $origin */ function ";
|
|
|
+ break;
|
|
|
+ case 0x8404:
|
|
|
+ $ret .= "final private /* 0x8000 $origin */ function ";
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ throw new ReflectionException("Unhandled method attribute set " . sprintf('0x%08x', $mask)
|
|
|
+ . " for " . $this->getDeclaringClass()->name . '::' . $this->name . '().');
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ * Not used in PHP-GTK 2.0.0.0
|
|
|
+ */
|
|
|
+ if ($this->returnsReference())
|
|
|
+ {
|
|
|
+ $ret .= '&';
|
|
|
+ }
|
|
|
+
|
|
|
+ $ret .= $name . " // "
|
|
|
+ . $this->getNumberOfParameters() . ' parameters, '
|
|
|
+ . $this->getNumberOfRequiredParameters() . " required."
|
|
|
+ . "\n (\n ";
|
|
|
+
|
|
|
+ $arParamStrings = array();
|
|
|
+ $arParamComments = array();
|
|
|
+ foreach ($this->getParameters() as $param)
|
|
|
+ {
|
|
|
+ $paramVector = $param->asPhp();
|
|
|
+ if ($paramVector['valid'])
|
|
|
+ {
|
|
|
+ $arParamStrings[] = $paramVector['string'];
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ $arParamComments[] = $paramVector['string'];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ $paramString = implode(",\n ", $arParamStrings);
|
|
|
+ if (count($arParamComments))
|
|
|
+ {
|
|
|
+ $paramString .= "\n " . implode("\n ", $arParamComments);
|
|
|
+ }
|
|
|
+ $ret .= $paramString
|
|
|
+ . "\n )";
|
|
|
+
|
|
|
+ $ret .= $isInterface ? ";\n\n" : " {}\n\n";
|
|
|
+ return $ret;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * Convert the ReflectionParameter array to a GtkReflectionParameter array
|
|
|
+ *
|
|
|
+ * @return GtkReflectionParameter[]
|
|
|
+ */
|
|
|
+ function getParameters()
|
|
|
+ {
|
|
|
+ $arParams1 = parent::getParameters();
|
|
|
+ $arParams2 = array();
|
|
|
+ foreach($arParams1 as $param)
|
|
|
+ {
|
|
|
+ $pos = $param->getPosition();
|
|
|
+ $arParams2[] = new GtkReflectionParameter(array($this->class, $this->name), $pos);
|
|
|
+ }
|
|
|
+ unset($arParams1);
|
|
|
+ return $arParams2;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * An extension to the ReflectionClass, able to output
|
|
|
+ * reflection information about an interface either as
|
|
|
+ * structured content or PHP source code
|
|
|
+ */
|
|
|
+class GtkReflectionInterface extends GtkReflectionClass
|
|
|
+ {
|
|
|
+
|
|
|
+ * Make sure the class/interface information matches
|
|
|
+ * the actual class
|
|
|
+ * @throws ReflectionException
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ protected function getHeader()
|
|
|
+ {
|
|
|
+
|
|
|
+ * Consistency check
|
|
|
+ */
|
|
|
+ if (!$this->isInterface())
|
|
|
+ {
|
|
|
+ throw new ReflectionException("Interface $this->name is listed as being a plain class.");
|
|
|
+ }
|
|
|
+
|
|
|
+ $ret = $this->getModifiersString()
|
|
|
+ . " interface $this->name";
|
|
|
+ return $ret;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * Extend the ReflectionClass to support PHP rendering
|
|
|
+ * There are no doccomments in PHP-GTK classes, so no
|
|
|
+ * method around $this->getDocComment()
|
|
|
+ * Same for interface $this->getProperties()
|
|
|
+ */
|
|
|
+class GtkReflectionClass extends ReflectionClass
|
|
|
+ {
|
|
|
+
|
|
|
+ * @return string
|
|
|
+ */
|
|
|
+ protected function getModifiersString()
|
|
|
+ {
|
|
|
+ $ret = array();
|
|
|
+ $mask = $this->getModifiers();
|
|
|
+ if ($mask & self::IS_EXPLICIT_ABSTRACT) { $ret[] = 'abstract'; }
|
|
|
+ if ($mask & self::IS_FINAL) { $ret[] = 'final'; }
|
|
|
+ if ($mask & self::IS_IMPLICIT_ABSTRACT) { $ret[] = '/* abstract */'; }
|
|
|
+ if ($this->isInstantiable()) { $ret[] = '/* instantiable */'; }
|
|
|
+ if ($this->isIterateable()) { $ret[] = '/* iterateable */'; }
|
|
|
+
|
|
|
+ $origin = new GtkOriginator($this);
|
|
|
+ $origin = $origin->getOrigin();
|
|
|
+ $ret[] = "/* $origin */";
|
|
|
+
|
|
|
+ $ret = implode(' ', $ret);
|
|
|
+ $ret = str_replace(' */ /* ', ' ', $ret);
|
|
|
+ return $ret;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * Make sure the class/interface information matches
|
|
|
+ * the actual class
|
|
|
+ * @throws ReflectionException
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ protected function getHeader()
|
|
|
+ {
|
|
|
+
|
|
|
+ * Consistency check
|
|
|
+ */
|
|
|
+ if ($this->isInterface())
|
|
|
+ {
|
|
|
+ throw new ReflectionException("Class $this->name is listed as being an interface.");
|
|
|
+ }
|
|
|
+
|
|
|
+ $ret = $this->getModifiersString()
|
|
|
+ . " class $this->name";
|
|
|
+ return $ret;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * return the inherited constants
|
|
|
+ */
|
|
|
+ protected function getInheritedConstants()
|
|
|
+ {
|
|
|
+ $ret = array();
|
|
|
+ $arAncestry = Gtk_Dumper::getClassAncestry($this->name);
|
|
|
+ array_pop($arAncestry);
|
|
|
+ foreach($arAncestry as $ancestorName)
|
|
|
+ {
|
|
|
+ $rAncestor = new ReflectionClass($ancestorName);
|
|
|
+ $arAncestorConstants = $rAncestor->getConstants();
|
|
|
+ $ret = array_merge($ret, $arAncestorConstants);
|
|
|
+ unset($rAncestor);
|
|
|
+ }
|
|
|
+ return $ret;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * return the "constant" clauses
|
|
|
+ * @return string
|
|
|
+ */
|
|
|
+ protected function getConstantsString()
|
|
|
+ {
|
|
|
+ $arConstants = $this->getConstants();
|
|
|
+ $ret = '';
|
|
|
+
|
|
|
+ $arInheritedConstants = $this->getInheritedConstants();
|
|
|
+ foreach ($arConstants as $name => $value)
|
|
|
+ {
|
|
|
+ if (array_key_exists($name, $arInheritedConstants) and ($arInheritedConstants[$name] == $value))
|
|
|
+ {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ * These reserved words are used for Gdk blit modes
|
|
|
+ */
|
|
|
+ if (in_array($name, array('XOR', 'OR', 'AND')))
|
|
|
+ {
|
|
|
+ $comment = "// Actual name is $name, which is reserved in PHP";
|
|
|
+ $name = "${name}_BLIT";
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ $comment = NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (is_string($value))
|
|
|
+ {
|
|
|
+ $value = "'$value'";
|
|
|
+ }
|
|
|
+ $ret .= " const $name = $value"
|
|
|
+ . (empty($comment) ? ";\n" : "; $comment\n");
|
|
|
+ }
|
|
|
+ $ret = (empty($ret) and !$this->isInterface())
|
|
|
+ ? " // No constants\n"
|
|
|
+ : $ret;
|
|
|
+ return $ret;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ * Format the class as a valid PHP declaration.
|
|
|
+ * The means the information is not necessarily complete
|
|
|
+ * in comparison with the one available from __toString()
|
|
|
+ *
|
|
|
+ * @todo tidy up vertical spacing
|
|
|
+ * @return string
|
|
|
+ */
|
|
|
+ public function asPhp()
|
|
|
+ {
|
|
|
+
|
|
|
+ $ret = $this->getHeader() ;
|
|
|
+
|
|
|
+
|
|
|
+ $parent = $this->getParentClass();
|
|
|
+ if ($parent)
|
|
|
+ {
|
|
|
+ $ret .= " extends " . $parent->name;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ $arInterfaceNames1 = $this->getInterfaceNames();
|
|
|
+ $arInterfaceNames2 = array();
|
|
|
+ foreach ($arInterfaceNames1 as $interface)
|
|
|
+ {
|
|
|
+
|
|
|
+ if ($interface == 'Traversable')
|
|
|
+ {
|
|
|
+ $ret .= " // Traversable cannot be implement in userland PHP\n"
|
|
|
+ . " // see http://www.php.net/~helly/php/ext/spl/interfaceTraversable.html\n";
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ $arInterfaceNames2[] = $interface;
|
|
|
+ }
|
|
|
+
|
|
|
+ $ret .= empty($arInterfaceNames2)
|
|
|
+ ? NULL
|
|
|
+ : "\n implements "
|
|
|
+ . implode(', ', $arInterfaceNames2);
|
|
|
+ $ret .= "\n {\n";
|
|
|
+
|
|
|
+
|
|
|
+ $constantStrings = $this->getConstantsString();
|
|
|
+ if (!empty($constantStrings))
|
|
|
+ {
|
|
|
+ $ret .= $constantStrings . PHP_EOL;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ foreach ($this->getMethods() as $method)
|
|
|
+ {
|
|
|
+ if ($method->getDeclaringClass()->name == $this->name)
|
|
|
+ {
|
|
|
+ $ret .= $method->asPhp();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ $ret .= " }\n";
|
|
|
+
|
|
|
+ return $ret;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * Convert the ReflectionMethod array to a GtkReflectionMethod array
|
|
|
+ *
|
|
|
+ * @return GtkReflectionMethod[]
|
|
|
+ */
|
|
|
+ function getMethods($filter = NULL)
|
|
|
+ {
|
|
|
+ $arMethods1 = parent::getMethods();
|
|
|
+ $arMethods2 = array();
|
|
|
+ foreach($arMethods1 as $method)
|
|
|
+ {
|
|
|
+ $arMethods2[] = new GtkReflectionMethod($this->name, $method->name);
|
|
|
+ }
|
|
|
+ unset($arMethods1);
|
|
|
+ return $arMethods2;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * Static methods allow lists of classes and interfaces
|
|
|
+ * to be obtained, from which an exhaustive dump of the
|
|
|
+ * classes and interfaces in an extension can be obtained
|
|
|
+ * using the normal methods of the class.
|
|
|
+ */
|
|
|
+class Gtk_Dumper
|
|
|
+ {
|
|
|
+
|
|
|
+ * The Reflection class for the class under examination
|
|
|
+ * @var ReflectionClass
|
|
|
+ */
|
|
|
+ protected $class;
|
|
|
+
|
|
|
+
|
|
|
+ * The name of the class under examination
|
|
|
+ * This is a shortcut to avoid constant reuse
|
|
|
+ * of ReflectionClass::getName()
|
|
|
+ * @var string
|
|
|
+ */
|
|
|
+ protected $name;
|
|
|
+
|
|
|
+
|
|
|
+ * @param string $name
|
|
|
+ */
|
|
|
+ public function __construct($name)
|
|
|
+ {
|
|
|
+ $this->name = $name;
|
|
|
+ $this->class = new ReflectionClass($name);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * Return the hierarchy of parents to a class as an array starting
|
|
|
+ * at the root class
|
|
|
+ *
|
|
|
+ * @param string $className
|
|
|
+ * @return array
|
|
|
+ */
|
|
|
+ static public function getClassAncestry($className)
|
|
|
+ {
|
|
|
+ $ret = array();
|
|
|
+ $class = new ReflectionClass($className);
|
|
|
+ do
|
|
|
+ {
|
|
|
+ array_unshift($ret, $class->getName());
|
|
|
+ $class = $class->getParentClass();
|
|
|
+ } while($class);
|
|
|
+ return $ret;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * List the classes in PHP-GTK
|
|
|
+ *
|
|
|
+ * Regrettably, the Reflection information on PHP-GTK2 classes
|
|
|
+ * is incomplete: it does not return the extension information on
|
|
|
+ * ReflectionClass::getExtension() and ReflectionClass::getExtensionName()
|
|
|
+ * so we have to use hard-coded information
|
|
|
+ *
|
|
|
+ * @return array
|
|
|
+ */
|
|
|
+ static public function getPhpGtkClassNames()
|
|
|
+ {
|
|
|
+ static $phpGtkRoots = array
|
|
|
+ (
|
|
|
+
|
|
|
+ * These are the PHP-GTK 2 root classes
|
|
|
+ */
|
|
|
+ 'Atk',
|
|
|
+ 'GBoxed',
|
|
|
+ 'Gdk',
|
|
|
+ 'GdkAtom',
|
|
|
+ 'Glade',
|
|
|
+ 'GObject',
|
|
|
+ 'GParamSpec',
|
|
|
+ 'GPointer',
|
|
|
+ 'GType',
|
|
|
+ 'Gtk',
|
|
|
+ 'GtkAccessible',
|
|
|
+ 'GtkAtom',
|
|
|
+ 'GtkTreeModelRow',
|
|
|
+ 'GtkTreeModelRowIterator',
|
|
|
+ 'Pango',
|
|
|
+
|
|
|
+
|
|
|
+ * This one has an ancestor outside the extension
|
|
|
+ */
|
|
|
+ 'PhpGtkException',
|
|
|
+ );
|
|
|
+
|
|
|
+ $arClassNames = get_declared_classes();
|
|
|
+ $ret = array();
|
|
|
+ foreach ($arClassNames as $className)
|
|
|
+ {
|
|
|
+ $rclass = new ReflectionClass($className);
|
|
|
+ $extName = $rclass->getExtensionName();
|
|
|
+
|
|
|
+ * The PHP-GTK extension does not define a value for getExtensionName()
|
|
|
+ * so we can save time, ignore classes known to come from other extensions
|
|
|
+ */
|
|
|
+ if (!empty($extName))
|
|
|
+ {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * we only want non-interface classes in this list
|
|
|
+ */
|
|
|
+ if ($rclass->isInterface())
|
|
|
+ {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * We can't just use ancestry roots, because PhpGtkException is not a root,
|
|
|
+ * and other similar cases might arise in later versions.
|
|
|
+ */
|
|
|
+ if (count(array_intersect(self::getClassAncestry($className), $phpGtkRoots)))
|
|
|
+ {
|
|
|
+ $ret[] = $className;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return $ret;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * List the interfaces in PHP-GTK
|
|
|
+ *
|
|
|
+ * Regrettably, the Reflection information on PHP-GTK2 classes
|
|
|
+ * is incomplete: it does not return the extension information on
|
|
|
+ * ReflectionClass::getExtension() and ReflectionClass::getExtensionName()
|
|
|
+ * so we have to use hard-coded information
|
|
|
+ *
|
|
|
+ * @return array
|
|
|
+ */
|
|
|
+ static public function getPhpGtkInterfaceNames()
|
|
|
+ {
|
|
|
+ $arInterfaceNames = get_declared_interfaces();
|
|
|
+ $ret = array();
|
|
|
+ foreach($arInterfaceNames as $name)
|
|
|
+ {
|
|
|
+ if (strpos($name, 'Gtk') === 0)
|
|
|
+ {
|
|
|
+ $ret[] = $name;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return $ret;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * return the methods clause
|
|
|
+ *
|
|
|
+ * if name is not set, return all the methods, otherwise
|
|
|
+ * just return the info for the designated method
|
|
|
+ *
|
|
|
+ * @param string $name
|
|
|
+ * @return string
|
|
|
+ */
|
|
|
+ function getClassMethods($name = NULL)
|
|
|
+ {
|
|
|
+ $ret = '';
|
|
|
+ $arMethods = empty($name)
|
|
|
+ ? $this->class->getMethods()
|
|
|
+ : array('name' => $name);
|
|
|
+
|
|
|
+ foreach ($arMethods as $oMethod)
|
|
|
+ {
|
|
|
+ $method = $this->class->getMethod($oMethod->name);
|
|
|
+ $modifiers = Reflection::getModifierNames($method->getModifiers());
|
|
|
+ $dc = $method->getDeclaringClass();
|
|
|
+ if ($dc->name != $this->name)
|
|
|
+ {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ $modifiers = implode (' ', $modifiers) . ' ';
|
|
|
+
|
|
|
+ $arParams = $method->getParameters();
|
|
|
+ $arParamStrings = array();
|
|
|
+ foreach ($arParams as $oParam)
|
|
|
+ {
|
|
|
+ if ($oParam->isOptional())
|
|
|
+ continue;
|
|
|
+
|
|
|
+ $name = str_replace(' ', '_', $oParam->name);
|
|
|
+
|
|
|
+ $isArray = $oParam->isArray();
|
|
|
+ $allowsNull = $oParam->allowsNull();
|
|
|
+ $isRef = $oParam->isPassedByReference();
|
|
|
+ $isOptional = $oParam->isOptional();
|
|
|
+ $hasDefault = $oParam->isDefaultValueAvailable();
|
|
|
+ $default = $hasDefault ? $oParam->getDefaultValue() : NULL;
|
|
|
+ $s = $isArray ? 'array ' : NULL ;
|
|
|
+ $s .= $isRef ? '&' : '';
|
|
|
+ $s .= "$$name";
|
|
|
+ $s .= $isOptional ? '/* optional */' : '';
|
|
|
+ $s .= $hasDefault ? ' = ' . $default : NULL;
|
|
|
+ $arParamStrings[] = $s;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ switch ($oMethod->name)
|
|
|
+ {
|
|
|
+ case 'foreach':
|
|
|
+ $methodName = 'foreach_method';
|
|
|
+ break;
|
|
|
+ case 'unset':
|
|
|
+ $methodName = 'unset_method';
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ $methodName = $oMethod->name;
|
|
|
+ }
|
|
|
+ $params = '(' . (count($arParamStrings) ? implode(', ', $arParamStrings) : NULL) . ')';
|
|
|
+ $ret .= ' ' . $modifiers . 'function ' . $methodName . $params . " {}\n";
|
|
|
+ }
|
|
|
+ return $ret;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * Global code
|
|
|
+ */
|
|
|
+function main()
|
|
|
+ {
|
|
|
+ echo "<?php\n";
|
|
|
+ echo getExtensionInfo();
|
|
|
+
|
|
|
+ foreach (Gtk_Dumper::getPhpGtkInterfaceNames() as $interfaceName)
|
|
|
+ {
|
|
|
+ $interface = new GtkReflectionInterface($interfaceName);
|
|
|
+ echo $interface->asPhp();
|
|
|
+ }
|
|
|
+
|
|
|
+ foreach (Gtk_Dumper::getPhpGtkClassNames() as $className)
|
|
|
+ {
|
|
|
+ $class = new GtkReflectionClass($className);
|
|
|
+ echo $class->asPhp();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+main();
|