#!/usr/bin/php
<?php

print "\n";
print "------------------------------------------------------------------\n";
print "Gathering hook information from the source code ...\n";

// Find files that might contain documentation for hooks.
chdir(dirname(__FILE__) . "/../../..");
$files = `find . -type f -name '*.php' -exec grep -l "\[hook\]" {} \;`;

// Storage for gathering the documentation.
$hookdocs = array();

// Process all files.
foreach ( explode("\n", $files) as $file) {
    if ($file == '') continue;

    print "> $file\n";

    $fp = fopen($file, 'r');
    if (!$fp) die("Reading file $file failed!\n");

    $hook    = NULL;
    $doc     = NULL;
    $section = NULL;
    while ($line = fgets($fp))
    {
        if (preg_match('/^\s*\*\//', $line)) {
            if ($hook !== NULL)
            {
                if ($doc['category'] === NULL) {
                    die("$file: no category defined for hook $hook\n");
                }
                if (empty($hookdocs[$doc['category']])) {
                    $hookdocs[$doc['category']] = array();
                }
                $hookdocs[$doc['category']][$doc['hook']] = $doc;
                $hook = NULL;
            }
            continue;
        }

        if ($hook === NULL) {
            if (preg_match('/^\s*\*\s*\[hook\]/', $line)) {
                $line = fgets($fp);
                if (preg_match('/^\s*\*\s*(\S+)/', $line, $m)) {
                    print "  > hook " . $m[1] . "\n";
                    $hook = $m[1];
                    $doc  = array(
                        "hook"        => $m[1],
                        "availability"=> '',
                        "category"    => NULL,
                        "description" => NULL,
                        "when"        => NULL,
                        "input"       => NULL,
                        "output"      => NULL,
                    );
                    $section = NULL;
                }
            }
        } else {
            if (preg_match('/^\s*\*\s*\[(description|availability|category|when|input|output|example)\]\s*(.*)\s*$/', $line, $m)) {
                $section = $m[1];
                $doc[$section] .= $m[2] . "\n";
            } elseif ($section !== NULL){
                if ($section == 'example') {
                    $doc[$section] .= preg_replace('/^\s*\*/', '', $line);
                } else {
                    $doc[$section] .= preg_replace('/^\s*\*\s*/', '', $line);
                }
            }
        }
    }
}

print "------------------------------------------------------------------\n";
print "Generating documentation ...\n";

$output = dirname(__FILE__) . "/part_hooks_generated.xml";
$fp = fopen($output, "w");
if (!$fp) die("Writing to $output failed.\n");

fputs($fp, "
<!-- Warning: this part was generated by docs/docbook/developer/mkhookdocs -->
<!-- Warning: do not do manual changes to this file. -->

");

function format_part($part)
{
    // First pass: see how much space we can remove from the start of
    // the lines in the example.
    $min_space = NULL;
    foreach (explode("\n", $part) as $line) {
        if (!preg_match('/^(\s+)\S/', $line, $m)) continue;
        $space = strlen($m[1]);
        if ($min_space === NULL || $min_space > $space) $min_space = $space;
    }
    // Second pass: remove the whitespace.
    if ($min_space !== NULL) {
        $newpart = '';
        foreach (explode("\n", $part) as $line) {
            $line = substr($line, $min_space);
            $newpart .= "$line\n";
        }
        $part = $newpart;
    }

    // Replace some HTML-like shortcuts for docbook code.
    $part = str_replace(array(
        '<ul>',
        '<li>',
        '</li>',
        '</ul>',
        '<b>',
        '</b>',
        '<br>',
        '<br/>',
        '<hookcode>',
        '</hookcode>'
    ), array(
        '<itemizedlist>',
        '<listitem>',
        '</listitem>',
        '</itemizedlist>',
        '<emphasis role="bold">',
        '</emphasis>',
        '<sbr/>',
        '<sbr/>',
        '<programlisting><![CDATA[',
        ']]></programlisting>'
    ), $part);

    // Some special entries for easy referencing.
    $part = preg_replace('!<hook>([\w_]+)</hook>!', '<xref endterm="$1" linkend="hook.$1"/>', $part);
    $part = preg_replace('!<phpfunc>([\w_]+)</phpfunc>!i', '<ulink url="http://www.php.net/$1">$1</ulink>()', $part);

    return $part;
}

foreach ($hookdocs as $category => $hooks)
{
    $catid = strtolower(preg_replace('/\W/', '', $category));
    $category = htmlspecialchars(trim($category));

    fputs($fp, "  <section id=\"hooks.category.$catid\">\n");
    fputs($fp, "    <title>$category</title>\n");

    foreach ($hooks as $name => $hook)
    {
        $name = htmlspecialchars(trim($name));

        fputs($fp, "    <section id=\"hook.$name\" xreflabel=\"$name\">\n");
        fputs($fp, "      <title>$name</title>\n");
        $hook['availability'] = preg_replace('/^\s+|\s+$/', '', $hook['availability']);
        if (!empty($hook['availability'])) {
            fputs($fp, "      <para>\n");
            fputs($fp, "        ({$hook['availability']})\n");
            fputs($fp, "      </para>\n");
        }
        fputs($fp, "      <para>\n");
        fputs($fp, format_part($hook['description']));
        fputs($fp, "      </para>\n");
        fputs($fp, "      <para>\n");
        fputs($fp, "        <emphasis role=\"bold\">\n");
        fputs($fp, "          Call time:\n");
        fputs($fp, "        </emphasis>\n");
        fputs($fp, "      </para>\n");
        fputs($fp, "      <para>\n");
        fputs($fp, format_part($hook['when']));
        fputs($fp, "      </para>\n");
        fputs($fp, "      <para>\n");
        fputs($fp, "        <emphasis role=\"bold\">\n");
        fputs($fp, "          Hook input:\n");
        fputs($fp, "        </emphasis>\n");
        fputs($fp, "      </para>\n");
        fputs($fp, "      <para>\n");
        fputs($fp, format_part($hook['input']));
        fputs($fp, "      </para>\n");
        fputs($fp, "      <para>\n");
        fputs($fp, "        <emphasis role=\"bold\">\n");
        fputs($fp, "          Hook output:\n");
        fputs($fp, "        </emphasis>\n");
        fputs($fp, "      </para>\n");
        fputs($fp, "      <para>\n");
        fputs($fp, format_part($hook['output']));
        fputs($fp, "      </para>\n");
        if (!empty($hook['example'])) {
            fputs($fp, "      <para>\n");
            fputs($fp, "        <emphasis role=\"bold\">\n");
            fputs($fp, "          Example code:\n");
            fputs($fp, "        </emphasis>\n");
            fputs($fp, "      </para>\n");
            fputs($fp, "      <para>\n");
            fputs($fp, format_part($hook['example']));
            fputs($fp, "      </para>\n");
        }
        fputs($fp, "    </section>\n");
    }

    fputs($fp, "  </section>\n");
}

?>
