Php MediaWiki+;Graphviz+;图像地图+;页面链接
背景:使用MediaWiki 1.19.1、Graphviz 2.28.0、扩展:WAMP堆栈上的Graphviz 0.9(Server 2008、Apache 2.4.2、MySQL 5.5.27、PHP 5.4.5)。使用MediaWiki中的Graphviz扩展从Graphviz图中呈现可点击图像的基本功能,一切都很正常 问题:图像映射中的链接未添加到MediaWiki页面链接表中。我明白为什么没有添加这些链接,但是如果没有办法使用“What links here”功能来跟踪链接,这就成了一个问题 所需解决方案:在处理GraphViz扩展名中的图表时,我想使用生成的.map文件创建一个Wiki链接列表,添加到页面上,以便MediaWiki获取并添加到pagelinks表中 详细信息: 此GraphViz扩展代码:Php MediaWiki+;Graphviz+;图像地图+;页面链接,php,xpath,mediawiki,graphviz,Php,Xpath,Mediawiki,Graphviz,背景:使用MediaWiki 1.19.1、Graphviz 2.28.0、扩展:WAMP堆栈上的Graphviz 0.9(Server 2008、Apache 2.4.2、MySQL 5.5.27、PHP 5.4.5)。使用MediaWiki中的Graphviz扩展从Graphviz图中呈现可点击图像的基本功能,一切都很正常 问题:图像映射中的链接未添加到MediaWiki页面链接表中。我明白为什么没有添加这些链接,但是如果没有办法使用“What links here”功能来跟踪链接,这就成了
<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>
我猜,因为.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 . "]]";
}
最终解决方案:见下面我接受的答案。
谢谢你看。我感谢您提供的任何帮助或指导。我终于解决了所有问题,现在有了一个相当不错的解决方案,可以很好地呈现图表,提供链接列表,并在wiki上注册链接。我的解决方案不完全支持当前GraphViz扩展的所有功能,因为它是编写的,因为有些功能我们不需要,我也不想支持。以下是此解决方案的假设/限制:
- 不支持MscGen:我们只需要Graphviz
- 不支持imageAttributes:我们想要控制格式和表示,imageAttributes实现中似乎存在不一致,这将导致进一步的支持问题
- 不支持wikilinks:虽然通过wiki和Graphviz扩展提供一致的链接使用会很好,但事实是Graphviz是一个完全不同的标记环境。虽然当前的扩展“支持”维基链接,但实现有点弱,留下了混乱的地方。示例:Wikilinks支持为链接提供可选描述,但Graphviz已经使用节点标签进行描述。因此,你最终会忽略wikilink的描述,并告诉用户“是的,我们支持wikilinks,但不使用描述部分”,因此,由于我们没有真正正确地使用wikilinks,所以只需实现常规链接实现,并尝试完全避免混淆
// 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 . '" />';
}
//清除映射名称
$map=preg#u replace(“##,”,“$map);
$map=str_替换(“”,,$map);
如果($renderer=='mscgen'){
$mapbefore=$map;
$map=preg_replace('/(\w+)\s([\:%\w]+)\s(\d+,\d+)\s(\d+,\d+)/”,
'',
$map);
}
/*过程html
*/
如果($wgGraphVizSettings->imageFormatting)
{
$txt=ImageAtributes($args、$storagename、$map、$outputType、$wgUploadPath);//如果需要边框/位置/。。。
}否则{
$txt='.$map'.'。
'';
}
使用此代码:
$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 ("   ") 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>';
$intHtml='';
$extHtml='';
$badHtml='';
//用顶级节点包装地图/区域信息并加载到xml对象中
$xmlObj=新的simplexmlement($map);
//在我们开始使用地图之前,它是什么样子的?
wfDebugLog('graphviz','map before:'.$map.\n');
//循环遍历每个节点
foreach($xmlObj->area作为$areaNode){
wfDebugLog('graphviz','areaNode:.$areaNode->asXML().“\n”);
//从XML属性获取数据
$hrefValue=(字符串)$areaNode->attributes()->href;
$textValue=(字符串)$areaNode->attributes()->title;
wfDebugLog('graphviz','hrefValue before:'.$hrefValue.\n');
wfDebugLog('graphviz','$textValue之前:'.$textValue.\n');
//对于文本字段,Graphviz源(标签)中有多个空格(“”)
//转换为规则空间,后跟的是
//.map文件中的非中断空格( ; ;”),然后将
//在局部变量中插入以下内容:(“the”)。
//以下两个选项用于转换/解码字符
//适当的。现在把这些行注释掉,就像我们已经做的那样
//未在野外看到标签中有多个空格的图形-
//只是碰巧发现了这个场景。
//看http://www.php.net/manual/en/simplexmlelement.asxml.php
//及http://stackoverflow.com/questions/2050723/how-can-i-preg-replace-special-character-like-pret-a-porter
//$textValue=iconv(“UTF-8”、“ASCII//translat”、$textValue);
//$textValue=html_entity_decode($textValue,ENT_NOQUOTES,'UTF-8');
//现在我们需要处理空白字符,比如制表符和换行符
//并对其进行正确处理,以避免多次发生。
//不幸的是,变量中的\n和\t值实际上不是
//制表符或换行符
// 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 ("   ") 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>';