MediaWiki + Graphviz +图像地图+页面链接

mat*_*321 5 php xpath mediawiki graphviz

背景:在WAMP堆栈上使用MediaWiki 1.19.1,Graphviz 2.28.0,扩展:GraphViz 0.9(Server 2008,Apache 2.4.2,MySQL 5.5.27,PHP 5.4.5).对于使用MediaWiki中的GraphViz扩展从Graphviz图表渲染可点击图像的基本功能,一切都非常有效.

问题:图像映射中的链接未添加到MediaWiki pagelinks表中.我明白为什么他们没有被添加但是如果没有办法通过"这里有什么链接"功能来关注链接就成了问题.

期望的解决方案:在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>
Run Code Online (Sandbox Code Playgroud)

生成此图片:

你好世界graphviz图

并且此图像映射代码位于服务器上相应的.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>
Run Code Online (Sandbox Code Playgroud)

从该图像映射文件,我希望能够提取href和标题来构建wikilinks,如下所示:

[[Hello|I say Hello]]
[[World|You say World!]]
Run Code Online (Sandbox Code Playgroud)

我猜测,因为.map文件本质上是XML,我可以使用XPATH来查询文件,但这只是猜测.PHP不是我最强大的领域,我不知道实现XML/XPATH选项的最佳方法,或者这甚至是从文件中提取信息的最佳方法.

一旦我从.map文件中获得了wikilinks的集合/数组,我确信我可以破解GraphViz.php扩展文件,将其添加到页面内容中,以将其添加到pagelinks表中.

进展:当我提交问题时,我有一点橡皮鸭解决问题的时刻.我意识到,由于我在图像映射中有很好的数据,因此XPATH可能就是这样.能够提取我需要的数据是非常微不足道的,特别是因为我发现地图文件内容是静止存储在本地字符串变量中的.

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

最终解决方案:请参阅下面的接受答案.谢谢参观.我感谢您提供的任何帮助或指导.

mat*_*321 4

我终于解决了所有问题,现在有了一个相当不错的解决方案来很好地渲染图表,提供链接列表,并在 wiki 上注册链接。我的解决方案并不完全支持当前 GraphViz 扩展的所有功能,因为它是因为存在我们不需要且我不想支持的功能而编写的。以下是该解决方案的假设/限制:

\n\n
    \n
  • 不支持MscGen:我们只需要Graphviz。
  • \n
  • 不支持 imageAttributes:我们想要控制格式和表示形式,但 imageAttributes 实现中似乎存在不一致,这会导致进一步的支持问题。
  • \n
  • 不支持 wiki 链接:虽然通过 wiki 和 Graphviz 扩展提供一致的链接使用会很好,但现实情况是 Graphviz 是一个完全不同的标记环境。虽然当前的扩展“支持”维基链接,但实现有点薄弱,并且留下了一些令人困惑的地方。示例:Wikilinks 支持为链接提供可选描述,但 Graphviz 已经使用节点标签作为描述。因此,您最终会忽略 wikilink 描述并告诉用户“是的,我们支持 wikilink,但不使用描述部分”。因此,由于我们并没有真正正确地使用 wikilink,因此只需实现常规链接实现即可尽量避免造成混乱。
  • \n
\n\n

输出如下所示:\nWiki Graphviz 增强功能

\n\n

以下是所做的更改

\n\n

注释掉这一行:

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

替换此代码块:

\n\n
// clean up map-name\n$map  = preg_replace( \'#<ma(.*)>#\', \' \', $map );\n$map  = str_replace( \'</map>\', \'\', $map );\nif ( $renderer == \'mscgen\' ) {\n    $mapbefore = $map;\n    $map = preg_replace( \'/(\\w+)\\s([_:%#/\\w]+)\\s(\\d+,\\d+)\\s(\\d+,\\d+)/\',\n   \'<area shape="$1" href="$2" title="$2" alt="$2" coords="$3,$4" />\',\n    $map );\n}\n\n/* Procduce html\n */\nif ( $wgGraphVizSettings->imageFormatting )\n{\n    $txt = imageAtrributes( $args, $storagename, $map, $outputType, $wgUploadPath ); // if we want borders/position/...\n} else {\n    $txt  = \'<map name="\' . $storagename . \'">\' . $map . \'</map>\' .\n         \'<img src="\' . $wgUploadPath . \'/graphviz/\' . $storagename . \'.\' . $outputType . \'"\' .\n                   \' usemap="#\' . $storagename . \'" />\';\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

有了这个代码:

\n\n
$intHtml = \'\';\n$extHtml = \'\';\n$badHtml = \'\';\n\n// Wrap the map/area info with top level nodes and load into xml object\n$xmlObj = new SimpleXMLElement( $map );\n\n// What does map look like before we start working with it?\nwfDebugLog( \'graphviz\', \'map before: \' . $map . "\\n" );\n\n// loop through each of the <area> nodes\nforeach($xmlObj->area as $areaNode) {\n\n    wfDebugLog( \'graphviz\', "areaNode: " . $areaNode->asXML() . "\\n" );\n\n    // Get the data from the XML attributes\n    $hrefValue = (string)$areaNode->attributes()->href;\n    $textValue = (string)$areaNode->attributes()->title;\n\n    wfDebugLog( \'graphviz\', \'$hrefValue before: \' . $hrefValue . "\\n" );\n    wfDebugLog( \'graphviz\', \'$textValue before: \' . $textValue . "\\n" );\n\n    // For the text fields, multiple spaces ("   ") in the Graphviz source (label)\n    // turns into a regular space followed by encoded representations of\n    // non-breaking spaces (" &#xA0;&#xA0;") in the .map file which then turns\n    // into the following in the local variables: (" \xc3\x82\xc2\xa0\xc3\x82\xc2\xa0").\n    // The following two options appear to convert/decode the characters\n    // appropriately. Leaving the lines commented out for now, as we have\n    // not seen a graph in the wild with multiple spaces in the label -\n    // just happened to stumble on the scenario.\n    // See http://www.php.net/manual/en/simplexmlelement.asxml.php\n    // and http://stackoverflow.com/questions/2050723/how-can-i-preg-replace-special-character-like-pret-a-porter\n    //$textValue = iconv("UTF-8", "ASCII//TRANSLIT", $textValue);\n    //$textValue = html_entity_decode($textValue, ENT_NOQUOTES, \'UTF-8\');\n\n    // Now we need to deal with the whitespace characters like tabs and newlines\n    // and also deal with them correctly to replace multiple occurences.\n    // Unfortunately, the \\n and \\t values in the variable aren\'t actually\n    // tab or newline characters but literal characters \'\\\' + \'t\' or \'\\\' + \'n\'.\n    // So the normally recommended regex \'/\\s+/u\' to replace the whitespace \n    // characters does not work.\n    // See http://stackoverflow.com/questions/6579636/preg-replace-n-in-string\n    $hrefValue = preg_replace("/( |\\\\\\\\n|\\\\\\\\t)+/", \' \', $hrefValue);\n    $textValue = preg_replace("/( |\\\\\\\\n|\\\\\\\\t)+/", \' \', $textValue);\n\n    // check to see if the url matches any of the\n    // allowed protocols for external links\n    if ( preg_match( \'/^(?:\' . wfUrlProtocols() . \')/\', $hrefValue ) ) {\n        // external link\n        $parser->mOutput->addExternalLink( $hrefValue );\n        $extHtml .= Linker::makeExternalLink( $hrefValue, $textValue ) . \', \';\n    }\n    else {\n        $first = substr( $hrefValue, 0, 1 );\n        if ( $first == \'\\\\\' || $first == \'[\' || $first == \'/\' ) {\n            // potential UNC path, wikilink, absolute or relative path\n            $hrefValue = \'#InvalidLink\';\n            $badHtml .= Linker::makeExternalLink( $hrefValue, $textValue ) . \', \';\n            $textValue = \'Invalid link. Check Graphviz source.\';\n        }\n        else {\n            $title = Title::newFromText( $hrefValue );\n            if ( is_null( $title ) ) {\n                // invalid link\n                $hrefValue = \'#InvalidLink\';\n                $badHtml .= Linker::makeExternalLink( $hrefValue, $textValue ) . \', \';\n                $textValue = \'Invalid link. Check Graphviz source.\';\n            }\n            else {\n                // internal link\n                $parser->mOutput->addLink( $title );\n                $intHtml .= Linker::link( $title, $textValue ) . \', \';\n                $hrefValue = $title->getFullURL();\n            }\n        }\n    }\n\n    $areaNode->attributes()->href = $hrefValue;\n    $areaNode->attributes()->title = $textValue;\n\n}\n\n$map = $xmlObj->asXML();\n\n// The contents of $map, which is now XML, gets embedded\n// in the HTML sent to the browser so we need to strip\n// the XML version tag and we also strip the <map> because\n// it will get replaced with a new one with the correct name.\n$map = str_replace( \'<?xml version="1.0"?>\', \'\', $map );\n$map = preg_replace( \'#<ma(.*)>#\', \' \', $map );\n$map = str_replace( \'</map>\', \'\', $map );\n\n// Let\'s see what it looks like now that we are done with it.\nwfDebugLog( \'graphviz\', \'map after: \' . $map . "\\n" );\n\n$txt = \'\' .\n    \'<table style="background-color:#f9f9f9;border:1px solid #ddd;">\' .\n        \'<tr>\' .\n            \'<td style="border:1px solid #ddd;text-align:center;">\' .\n                \'<map name="\' . $storagename . \'">\' . $map . \'</map>\' .\n                \'<img src="\' . $wgUploadPath . \'/graphviz/\' . $storagename . \'.\' . $outputType . \'"\' . \' usemap="#\' . $storagename . \'" />\' .\n            \'</td>\' .\n        \'</tr>\' .\n        \'<tr>\' .\n            \'<td style="font:10px verdana;">\' .\n                \'This Graphviz diagram links to the following pages:\' .\n                \'<br /><strong>Internal</strong>: \' . ( $intHtml != \'\' ?  rtrim( $intHtml, \' ,\' ) : \'<em>none</em>\' ) .\n                \'<br /><strong>External</strong>: \' . ( $extHtml != \'\' ?  rtrim( $extHtml, \' ,\' ) : \'<em>none</em>\' ) .\n                ( $badHtml != \'\' ? \'<br /><strong>Invalid</strong>: \' . rtrim($badHtml, \' ,\') .\n                \'<br /><em>Tip: Do not use wikilinks ([]), UNC paths (\\\\) or relative links (/) when creating links in Graphviz diagrams.</em>\' : \'\' ) .\n            \'</td>\' .\n        \'</tr>\' .\n    \'</table>\';\n
Run Code Online (Sandbox Code Playgroud)\n\n

可能的增强功能:

\n\n
    \n
  • 如果图表下方的链接列表能够进行排序和重复数据删除,那就太好了。
  • \n
\n