sean Sun Feb 4 19:31:45 2007 UTC
Modified files:
/phpdoc/scripts functable.php
Log:
first stab at PECL support
http://cvs.php.net/viewvc.cgi/phpdoc/scripts/functable.php?r1=1.7&r2=1.8&diff_format=u
Index: phpdoc/scripts/functable.php
diff -u phpdoc/scripts/functable.php:1.7 phpdoc/scripts/functable.php:1.8
--- phpdoc/scripts/functable.php:1.7 Sat Feb 3 14:22:25 2007
+++ phpdoc/scripts/functable.php Sun Feb 4 19:31:45 2007
@@ -15,7 +15,7 @@
+----------------------------------------------------------------------+
| Authors: Sean Coates <[EMAIL PROTECTED]> |
+----------------------------------------------------------------------+
-$Id: functable.php,v 1.7 2007/02/03 14:22:25 sean Exp $
+$Id: functable.php,v 1.8 2007/02/04 19:31:45 sean Exp $
*/
// direct the output of this file into phpdoc/phpbook/phpbook-xsl/version.xml
@@ -23,12 +23,16 @@
// To do:
// - TEST, please
-// - PECL support
+// - someone should really make this code parse the source and not just look
+// at the protos
// You'll need to set up an SQLite DB (see PATH_DB, below) with the following:
// CREATE TABLE func_tag (func_name VARCHAR(50), tag_name VARCHAR(50),
// has_proto INT, is_alias INT, unicode_safe INT, source VARCHAR(255));
+// set $_ENV['DO_CVS'] to use php-src
+// set $_ENV['DO_PECL'] to use PECL
+
// set up config:
// set $_ENV['PATH_TMP'] to change the temporary directory
@@ -47,6 +51,9 @@
function rm_recursive($path)
{
+ if (!is_dir($path)) {
+ return;
+ }
$dir = new DirectoryIterator($path);
while($dir->valid()) {
if(!$dir->isDot()) {
@@ -61,7 +68,7 @@
rmdir($path);
}
-function get_release_tags()
+function get_php_release_tags()
{
rm_recursive(PATH_TMP);
mkdir(PATH_TMP);
@@ -96,6 +103,51 @@
return array_reverse($tags);
}
+function get_pecl_packages()
+{
+ $packages = array();
+ $XE = @new SimpleXMLElement('http://pecl.php.net/rest/p/packages.xml',
NULL, true); //@ sucks, but the XML doesn't like me
+ foreach ($XE as $Element) {
+ if ($Element->getName() == 'p') {
+ $packages[] = strtolower((string) $Element);
+ }
+ }
+ return $packages;
+}
+
+function get_pecl_releases($package)
+{
+ $releases = array();
+ try {
+ $XE = @new
SimpleXMLElement("http://pecl.php.net/rest/r/$package/allreleases.xml", NULL,
true); //@ sucks, but the XML doesn't like me
+ foreach ($XE as $Element) {
+ if ($Element->getName() == 'r') {
+ if (preg_match('/[0-9]+\.[0-9]+(\.[0-9]+)?$/i', (string)
$Element->v)) {
+ $releases[] = (string) $Element->v;
+ }
+ }
+ }
+ sort($releases);
+ return $releases;
+ } catch (Exception $e) {
+ fwrite(STDERR, " WARN: NO RELEASES\n");
+ return false;
+ }
+}
+
+function grab_pecl_release($package, $release)
+{
+ rm_recursive(PATH_TMP);
+ mkdir(PATH_TMP);
+ chdir(PATH_TMP);
+
+ $remoteTarball = 'http://pecl.php.net/get/'. urlencode($package) . '-' .
urlencode($release);
+ file_put_contents(PATH_TMP . '/pecl_tarball.tgz',
file_get_contents($remoteTarball));
+
+ // should probably do this as natively as possible.. @@@fixme
+ exec('/bin/tar zxf pecl_tarball.tgz');
+}
+
function checkout_tag($tag)
{
rm_recursive(PATH_TMP);
@@ -170,34 +222,34 @@
return $funcs;
}
-function convert_array_to_words($func)
+function convert_array_to_words($func, $tags4, $tags5, $tagsPECL)
{
- // globals suck )-:
- global $tags4, $tags5;
+ // this functions should be refactored
- static $regex = '/PHP_([45])_([0-9])_([0-9])/';
+ static $phpRegex = '/PHP_([45])_([0-9])_([0-9])/';
static $rep = '$1.$2.$3';
+ // function exists in PHP 4?
$text4 = '';
$ft4 = array();
foreach ($tags4 as $t) {
if (isset($func[$t])) {
$ft4[] = $t;
}
- }
-
+ }
if (!$ft4) {
$text4 = '';
} elseif ($ft4 == $tags4) {
$text4 = "PHP 4";
} else {
if ($ft4[0] == $tags4[0]) {
- $text4 = "PHP 4 <= " . preg_replace($regex, $rep, $ft4[count($ft4)
- 1]);
+ $text4 = "PHP 4 <= " . preg_replace($phpRegex, $rep,
$ft4[count($ft4) - 1]);
} else {
- $text4 = "PHP 4 >= " . preg_replace($regex, $rep, $ft4[0]);
+ $text4 = "PHP 4 >= " . preg_replace($phpRegex, $rep, $ft4[0]);
}
}
+ // function exists in PHP 5?
$text5 = '';
$ft5 = array();
foreach ($tags5 as $t) {
@@ -205,65 +257,157 @@
$ft5[] = $t;
}
}
-
if (!$ft5) {
$text5 = '';
} elseif ($ft5 == $tags5) {
$text5 = "PHP 5";
} else {
if ($ft5[0] == $tags5[0]) {
- $text5 = "PHP 5 <= " . preg_replace($regex, $rep, $ft5[count($ft5)
- 1]);
+ $text5 = "PHP 5 <= " . preg_replace($phpRegex, $rep,
$ft5[count($ft5) - 1]);
} else {
- $text5 = "PHP 5 >= " . preg_replace($regex, $rep, $ft5[0]);
+ $text5 = "PHP 5 >= " . preg_replace($phpRegex, $rep, $ft5[0]);
+ }
+ }
+
+ // function exists in PECL?
+ $textPECL = '';
+ if ($tagsPECL) {
+ $pkgPECL = array();
+ // determine pacakges
+ foreach ($tagsPECL as $tag) {
+ list($pkg, $ver) = explode('-', $tag);
+ if (isset($func[$tag])) {
+ if (!isset($pkgPECL[$pkg])) {
+ $pkgPECL[$pkg] = array();
+ }
+ $pkgPECL[$pkg][] = $ver;
+ }
+ }
+ foreach ($pkgPECL as $pkg => $vers) {
+ if ($textPECL) {
+ $textPECL .= ' '; // if there's something in the text,
prepend a space
+ }
+ $textPECL .= strtolower($pkg) .':'. $vers[0];
+ if (count($vers) > 1) {
+ $textPECL .= '-'. $vers[count($vers) - 1];
+ }
+ }
+ if ($textPECL) {
+ $textPECL = 'PECL ' . $textPECL; // prepend PECL
}
}
- if ($text4 && $text5) {
- return "$text4, $text5";
- } elseif ($text4) {
- return "$text4";
- } elseif ($text5) {
- return "$text5";
- } else {
- die("Error.");
+ // output
+ $texts = array_filter(array($text4, $text5, $textPECL)); // ignore empty
classes
+ return implode(', ', $texts);
+}
+
+function store_protos($tag, $protos, $source = 'php-src')
+{
+ $dbh = new PDO('sqlite:' . PATH_DB);
+
+ $s = $dbh->prepare('DELETE FROM func_tag WHERE tag_name = ?');
+ $s->bindParam(1, $tag);
+ $s->execute();
+
+ foreach ($protos as $p) {
+ $s = $dbh->prepare("INSERT INTO "
+ . "func_tag (func_name, tag_name, has_proto, unicode_safe,
source) "
+ . "VALUES (?, ?, 1, ?, ?)");
+ $s->bindParam(1, $p['func']);
+ $s->bindParam(2, $tag);
+ $s->bindParam(3, $p['unicode']);
+ $s->bindParam(4, $source);
+ $s->execute();
}
}
///////////////
///////////////
-if (getenv('SKIP_CVS')) {
+if (!getenv('DO_CVS')) {
fwrite(STDERR, "Skipping CVS\n");
} else {
- fwrite(STDERR, "Using CVS\n");
-
+ fwrite(STDERR, "Using CVS\n");
if (getenv('FUNCTABLE_TAGS')) {
$tags = explode(' ', getenv('FUNCTABLE_TAGS'));
} else {
- $tags = get_release_tags();
+ $tags = get_php_release_tags();
}
- fwrite(STDERR, "Tags: " . implode(' ', $tags) ."\n");
+ fwrite(STDERR, "PHP Tags: " . implode(' ', $tags) ."\n");
foreach ($tags as $tag) {
fwrite(STDERR, "Getting tag: $tag\n");
checkout_tag($tag);
+
$protos = parse_protos(PATH_TMP . DIRECTORY_SEPARATOR . 'php-src');
+ store_protos($tag, $protos);
+ }
+}
+
+if (getenv('DO_PECL')) {
+ fwrite(STDERR, "Skipping PECL\n");
+} else {
+ fwrite(STDERR, "Using PECL\n");
+ $releases = array();
+ if ($envReleases = getenv('PECL_RELEASES')) {
+ $envReleases = explode(' ', $envReleases);
+ sort($envReleases);
+ foreach ($envReleases as $envR) {
+ list($pkg, $ver) = explode('-', $envR);
+ if (isset($ver)) { // (allow for "runkit" instead of "runkit-0.8"
+ $vers = array($ver);
+ } else {
+ $vers = get_pecl_releases($pkg);
+ }
+ if ($vers) {
+ foreach ($vers as $ver) {
+ if (!isset($releases[$pkg])) {
+ $releases[$pkg] = array();
+ }
+ if (!in_array($ver, $releases[$pkg])) {
+ $releases[$pkg][] = $ver;
+ }
+ }
+ }
+ }
+ } else {
+ foreach (get_pecl_packages() as $pkg) {
+ fwrite(STDERR, "Fetching releases for: $pkg\n");
+ if ($peclReleases = get_pecl_releases($pkg)) {
+ foreach ($peclReleases as $ver) {
+ if (!isset($releases[$pkg])) {
+ $releases[$pkg] = array();
+ }
+ $releases[$pkg][] = $ver;
+ }
+ }
+ }
+ }
- $dbh = new PDO('sqlite:' . PATH_DB);
-
- $s = $dbh->prepare('DELETE FROM func_tag WHERE tag_name = ?');
- $s->bindParam(1, $tag);
- $s->execute();
-
- foreach ($protos as $p) {
- $s = $dbh->prepare("INSERT INTO "
- . "func_tag (func_name, tag_name, has_proto,
unicode_safe, source) "
- . "VALUES (?, ?, 1, ?, 'php-src')");
- $s->bindParam(1, $p['func']);
- $s->bindParam(2, $tag);
- $s->bindParam(3, $p['unicode']);
- $s->execute();
+ foreach ($releases as $pkg => $versions) {
+ foreach ($versions as $ver) {
+ $pkgName = $pkg . '-' . $ver;
+ fwrite(STDERR, "Grabbing PECL Release: " . $pkgName ."\n");
+ grab_pecl_release($pkg, $ver);
+ fwrite(STDERR, "Parsing protos ...\n");
+ // sometimes PECL package name case is broken:
+ $dirName = false;
+ if (is_dir(PATH_TMP . DIRECTORY_SEPARATOR . $pkgName)) {
+ $dirName = PATH_TMP . DIRECTORY_SEPARATOR . $pkgName;
+ } elseif (is_dir(PATH_TMP . DIRECTORY_SEPARATOR .
strtolower($pkgName))) {
+ $dirName = PATH_TMP . DIRECTORY_SEPARATOR .
strtolower($pkgName);
+ } elseif (is_dir(PATH_TMP . DIRECTORY_SEPARATOR .
strtoupper($pkgName))) {
+ $dirName = PATH_TMP . DIRECTORY_SEPARATOR .
strtoupper($pkgName);
+ } else {
+ fwrite(STDERR, "ERROR: unable to determine package
directory.\n");
+ }
+ if ($dirName) {
+ $protos = parse_protos($dirName);
+ fwrite(STDERR, "Storing protos ...\n");
+ store_protos($pkgName, $protos, 'PECL');
+ }
}
}
}
@@ -301,27 +445,36 @@
func_tag
WHERE
UPPER(tag_name) = ?
+ AND
+ source = ?
ORDER BY
tag_name
");
$tq = $dbh->query("
SELECT
- DISTINCT UPPER(tag_name) AS tag_name
+ DISTINCT UPPER(tag_name) AS tag_name,
+ source
FROM
func_tag
WHERE
- tag_name LIKE 'PHP\\__\\__\\__' ESCAPE '\\'
+ (
+ tag_name LIKE 'PHP\\__\\__\\__' ESCAPE '\\'
+ AND
+ source = 'php-src'
+ )
+ OR
+ source = 'PECL'
ORDER BY
UPPER(tag_name)
");
foreach ($tq as $tr) {
$tags[] = $tr['tag_name'];
- if ($s->execute(array($tr['tag_name']))) {
+ if ($s->execute(array($tr['tag_name'], $tr['source']))) {
while ($fr = $s->fetch()) {
if ($fr['func_name']) {
- $funcs[$fr['func_name']][$tr['tag_name']] = 1;
+ $funcs[$fr['func_name']][$tr['tag_name']] = 1;
}
}
}
@@ -330,18 +483,19 @@
$tags4 = array();
$tags5 = array();
+$tagsPECL = array();
foreach ($tags as $t) {
if (substr($t,0,5) == 'PHP_4') {
$tags4[] = $t;
} elseif (substr($t,0,5) == 'PHP_5') {
$tags5[] = $t;
- } else {
- die('ERROR: '. $t);
+ } else { // must be PECL
+ $tagsPECL[] = $t;
}
}
foreach ($funcs as $funcname => $func) {
- $text = htmlspecialchars(convert_array_to_words($func));
+ $text = htmlspecialchars(convert_array_to_words($func, $tags4, $tags5,
$tagsPECL));
echo " <function name='{$funcname}' from='{$text}'/>\n";
}
?>