6

背景:WAMPスタック(Server 2008、Apache 2.4.2、MySQL 5.5.27、PHP 5.4.5)でのMediaWiki 1.19.1、Graphviz 2.28.0、Extension:GraphViz0.9の操作。MediaWikiのGraphViz拡張機能を使用してGraphvizダイアグラムからクリック可能な画像をレンダリングする基本機能については、すべてがうまく機能しており、期待どおりです。

問題:画像マップのリンクがMediaWikiページリンクテーブルに追加されていません。追加されない理由はわかりますが、「ここにリンクするもの」機能でリンクをたどる方法がない場合は問題になります。

望ましい解決策:GraphViz拡張機能の図の処理中に、生成された.mapファイルを使用して、ページに追加するwikilinkのリストを作成し、MediaWikiによって取得され、pagelinksテーブルに追加されます。

詳細:このGraphViz拡張コード:

<graphviz border='frame' format='png'>
digraph example1 {
  // define nodes
  nodeHello [
    label="I say Hello", 
    URL="Hello"
  ]
  nodeWorld [
    label="You say World!",
    URL="World"
  ]
  // link nodes
  nodeHello -> nodeWorld!
}
</graphviz>

この画像を生成します:

helloworldgraphviz図

そして、サーバー上の対応する.mapファイル内のこのイメージマップコード:

<map id="example1" name="example1">
<area shape="poly" id="node1" href="Hello" title="I say Hello" alt="" coords="164,29,161,22,151,15,137,10,118,7,97,5,77,7,58,10,43,15,34,22,31,29,34,37,43,43,58,49,77,52,97,53,118,52,137,49,151,43,161,37"/>
<area shape="poly" id="node2" href="World" title="You say World!" alt="" coords="190,125,186,118,172,111,152,106,126,103,97,101,69,103,43,106,22,111,9,118,5,125,9,133,22,139,43,145,69,148,97,149,126,148,152,145,172,139,186,133"/>
</map>

その画像マップファイルから、hrefとタイトルを抽出して次のようなwikiリンクを作成できるようにしたいと思います。

[[Hello|I say Hello]]
[[World|You say World!]]

その.mapファイルは本質的にXMLであるため、XPATHを使用してファイルを照会できると推測していますが、それは単なる推測です。PHPは私の最強の分野ではなく、XML / XPATHオプションを使用するための最善のアプローチ、またはそれがファイルからその情報を取得するための最善のアプローチであるかどうかもわかりません。

.mapファイルからwikilinkのコレクション/配列を取得したら、GraphViz.php拡張ファイルをハックしてページのコンテンツに追加し、pagelinksテーブルに追加できると確信しています。

進捗状況:質問を送信した直後に、ラバーダックの問題解決の瞬間が少しありました。画像マップにデータが適切に形成されているので、XPATHがおそらくその方法であることに気づきました。特に、マップファイルの内容がローカルの文字列変数に格納されたままであることがわかったため、必要なデータを取得できるようにするのは非常に簡単でした。

$xml = new SimpleXMLElement( $map );
foreach($xml->area as $item) {
  $links .= "[[" . $item->attributes()->href . "|" . $item->attributes()->title . "]]";
}

最終的な解決策:以下の私の受け入れられた答えを参照してください。ご覧いただきありがとうございます。私はあなたが提供できるどんな援助または指示にも感謝します。

4

1 に答える 1

4

私は最終的にすべての問題に取り組み、グラフを適切にレンダリングし、リンクのリストを提供し、リンクを wiki に登録するためのかなり適切なソリューションを手に入れました。私のソリューションは、現在の GraphViz 拡張機能のすべての機能を完全にサポートしているわけではありません。これは、必要のない機能があり、サポートしたくないためです。このソリューションの前提/制限は次のとおりです。

  • MscGen をサポートしていません: Graphviz のみが必要です。
  • imageAtrributes をサポートしていません: フォーマットとプレゼンテーションを制御したかったのですが、imageAttributes の実装に矛盾があり、サポートの問題がさらに発生するようでした。
  • ウィキリンクをサポートしていません: ウィキと Graphviz 拡張機能を介して一貫したリンクの使用を提供することは良いことですが、現実には、Graphviz はまったく異なるマークアップ環境です。現在の拡張機能はウィキリンクを「サポート」していますが、実装は少し弱く、混乱の余地があります。例: Wikilinks はリンクにオプションの説明を与えることをサポートしていますが、Graphviz は既に説明にノード ラベルを使用しています。そのため、ウィキリンクの説明を無視して、「はい、私たちはウィキリンクをサポートしていますが、説明部分は使用していません」とユーザーに伝えることになります.完全に混乱。

出力は次のようになります。 Wiki Graphviz の機能強化

行われた変更は次のとおりです

次の行をコメントアウトします。

// We don't want to support wikilinks so don't replace them
//$timelinesrc = rewriteWikiUrls( $timelinesrc ); // if we use wiki-links we transform them to real urls

次のコード ブロックを置き換えます。

// clean up map-name
$map  = preg_replace( '#<ma(.*)>#', ' ', $map );
$map  = str_replace( '</map>', '', $map );
if ( $renderer == 'mscgen' ) {
    $mapbefore = $map;
    $map = preg_replace( '/(\w+)\s([_:%#/\w]+)\s(\d+,\d+)\s(\d+,\d+)/',
   '<area shape="$1" href="$2" title="$2" alt="$2" coords="$3,$4" />',
    $map );
}

/* Procduce html
 */
if ( $wgGraphVizSettings->imageFormatting )
{
    $txt = imageAtrributes( $args, $storagename, $map, $outputType, $wgUploadPath ); // if we want borders/position/...
} else {
    $txt  = '<map name="' . $storagename . '">' . $map . '</map>' .
         '<img src="' . $wgUploadPath . '/graphviz/' . $storagename . '.' . $outputType . '"' .
                   ' usemap="#' . $storagename . '" />';
}

このコードで:

$intHtml = '';
$extHtml = '';
$badHtml = '';

// Wrap the map/area info with top level nodes and load into xml object
$xmlObj = new SimpleXMLElement( $map );

// What does map look like before we start working with it?
wfDebugLog( 'graphviz', 'map before: ' . $map . "\n" );

// loop through each of the <area> nodes
foreach($xmlObj->area as $areaNode) {

    wfDebugLog( 'graphviz', "areaNode: " . $areaNode->asXML() . "\n" );

    // Get the data from the XML attributes
    $hrefValue = (string)$areaNode->attributes()->href;
    $textValue = (string)$areaNode->attributes()->title;

    wfDebugLog( 'graphviz', '$hrefValue before: ' . $hrefValue . "\n" );
    wfDebugLog( 'graphviz', '$textValue before: ' . $textValue . "\n" );

    // For the text fields, multiple spaces ("   ") in the Graphviz source (label)
    // turns into a regular space followed by encoded representations of
    // non-breaking spaces (" &#xA0;&#xA0;") in the .map file which then turns
    // into the following in the local variables: ("   ").
    // The following two options appear to convert/decode the characters
    // appropriately. Leaving the lines commented out for now, as we have
    // not seen a graph in the wild with multiple spaces in the label -
    // just happened to stumble on the scenario.
    // See http://www.php.net/manual/en/simplexmlelement.asxml.php
    // and http://stackoverflow.com/questions/2050723/how-can-i-preg-replace-special-character-like-pret-a-porter
    //$textValue = iconv("UTF-8", "ASCII//TRANSLIT", $textValue);
    //$textValue = html_entity_decode($textValue, ENT_NOQUOTES, 'UTF-8');

    // Now we need to deal with the whitespace characters like tabs and newlines
    // and also deal with them correctly to replace multiple occurences.
    // Unfortunately, the \n and \t values in the variable aren't actually
    // tab or newline characters but literal characters '\' + 't' or '\' + 'n'.
    // So the normally recommended regex '/\s+/u' to replace the whitespace 
    // characters does not work.
    // See http://stackoverflow.com/questions/6579636/preg-replace-n-in-string
    $hrefValue = preg_replace("/( |\\\\n|\\\\t)+/", ' ', $hrefValue);
    $textValue = preg_replace("/( |\\\\n|\\\\t)+/", ' ', $textValue);

    // check to see if the url matches any of the
    // allowed protocols for external links
    if ( preg_match( '/^(?:' . wfUrlProtocols() . ')/', $hrefValue ) ) {
        // external link
        $parser->mOutput->addExternalLink( $hrefValue );
        $extHtml .= Linker::makeExternalLink( $hrefValue, $textValue ) . ', ';
    }
    else {
        $first = substr( $hrefValue, 0, 1 );
        if ( $first == '\\' || $first == '[' || $first == '/' ) {
            // potential UNC path, wikilink, absolute or relative path
            $hrefValue = '#InvalidLink';
            $badHtml .= Linker::makeExternalLink( $hrefValue, $textValue ) . ', ';
            $textValue = 'Invalid link. Check Graphviz source.';
        }
        else {
            $title = Title::newFromText( $hrefValue );
            if ( is_null( $title ) ) {
                // invalid link
                $hrefValue = '#InvalidLink';
                $badHtml .= Linker::makeExternalLink( $hrefValue, $textValue ) . ', ';
                $textValue = 'Invalid link. Check Graphviz source.';
            }
            else {
                // internal link
                $parser->mOutput->addLink( $title );
                $intHtml .= Linker::link( $title, $textValue ) . ', ';
                $hrefValue = $title->getFullURL();
            }
        }
    }

    $areaNode->attributes()->href = $hrefValue;
    $areaNode->attributes()->title = $textValue;

}

$map = $xmlObj->asXML();

// The contents of $map, which is now XML, gets embedded
// in the HTML sent to the browser so we need to strip
// the XML version tag and we also strip the <map> because
// it will get replaced with a new one with the correct name.
$map = str_replace( '<?xml version="1.0"?>', '', $map );
$map = preg_replace( '#<ma(.*)>#', ' ', $map );
$map = str_replace( '</map>', '', $map );

// Let's see what it looks like now that we are done with it.
wfDebugLog( 'graphviz', 'map after: ' . $map . "\n" );

$txt = '' .
    '<table style="background-color:#f9f9f9;border:1px solid #ddd;">' .
        '<tr>' .
            '<td style="border:1px solid #ddd;text-align:center;">' .
                '<map name="' . $storagename . '">' . $map . '</map>' .
                '<img src="' . $wgUploadPath . '/graphviz/' . $storagename . '.' . $outputType . '"' . ' usemap="#' . $storagename . '" />' .
            '</td>' .
        '</tr>' .
        '<tr>' .
            '<td style="font:10px verdana;">' .
                'This Graphviz diagram links to the following pages:' .
                '<br /><strong>Internal</strong>: ' . ( $intHtml != '' ?  rtrim( $intHtml, ' ,' ) : '<em>none</em>' ) .
                '<br /><strong>External</strong>: ' . ( $extHtml != '' ?  rtrim( $extHtml, ' ,' ) : '<em>none</em>' ) .
                ( $badHtml != '' ? '<br /><strong>Invalid</strong>: ' . rtrim($badHtml, ' ,') .
                '<br /><em>Tip: Do not use wikilinks ([]), UNC paths (\\) or relative links (/) when creating links in Graphviz diagrams.</em>' : '' ) .
            '</td>' .
        '</tr>' .
    '</table>';

可能な拡張:

  • グラフの下にあるリンクのリストがソートされ、重複が排除されているとよいでしょう。
于 2012-08-31T14:04:19.927 に答える