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";
 }
 ?>

Reply via email to