Index: extensions/SemanticMediaWiki/includes/SMW_ParserExtensions.php =================================================================== --- extensions/SemanticMediaWiki/includes/SMW_ParserExtensions.php (revision 0) +++ extensions/SemanticMediaWiki/includes/SMW_ParserExtensions.php (revision 0) @@ -49,7 +49,11 @@ SMWParserExtensions::$mTempParser = $parser; // In the regexp matches below, leading ':' escapes the markup, as known for Categories. - // Parse links to extract semantic properties. + // Parse links to extract semantic properties. + global $smwgRecursivePropertyValues; + if ( $smwgRecursivePropertyValues ) { + self::parsePropertiesRecursive( $parser, $text ); + } else if ( $smwgLinksInValues ) { // More complex regexp -- lib PCRE may cause segfaults if text is long :-( $semanticLinkPattern = '/\[\[ # Beginning of the link (?:([^:][^]]*):[=:])+ # Property name (or a list of those) @@ -60,7 +64,7 @@ )*) # all this zero or more times (?:\|([^]]*))? # Display text (like "text" in [[link|text]]), optional \]\] # End of link - /xu'; + /xu'; $text = preg_replace_callback( $semanticLinkPattern, array( 'SMWParserExtensions', 'parsePropertiesCallback' ), $text ); } else { // Simpler regexps -- no segfaults found for those, but no links in values. $semanticLinkPattern = '/\[\[ # Beginning of the link @@ -160,13 +164,13 @@ // Extract annotations and create tooltip. $properties = preg_split( '/:[=:]/u', $property ); - - foreach ( $properties as $singleprop ) { - $dv = SMWParseData::addProperty( $singleprop, $value, $valueCaption, SMWParserExtensions::$mTempParser, $smwgStoreAnnotations && SMWParserExtensions::$mTempStoreAnnotations ); + + foreach ( $properties as $singleprop ) { + $dv = SMWParseData::addProperty( $singleprop, $value, $valueCaption, SMWParserExtensions::$mTempParser, $smwgStoreAnnotations && SMWParserExtensions::$mTempStoreAnnotations ); } $result = $dv->getShortWikitext( true ); - + if ( ( $smwgInlineErrors && $smwgStoreAnnotations && SMWParserExtensions::$mTempStoreAnnotations ) && ( !$dv->isValid() ) ) { $result .= $dv->getErrorText(); } @@ -175,5 +179,161 @@ return $result; } - + + + static private function parseProperties( $text, &$result = array(), &$start = 0, $inprop = false ) { + while( preg_match( '/\[\[([^:[][^]]*?):[=:]|(\[\[[^][]*?\]\])|(\]\])/xu', $text, $m, PREG_OFFSET_CAPTURE, $start ) ) { + $offset = $m[0][1]; + if( isset($m[3]) && $inprop ) { + // end of property + $result[] = substr($text, $start, $offset - $start); + $start = $offset + 2; + return true; + } + if( isset($m[2]) ) { + // common link + $result[] = substr($text, $start, $offset - $start); + // special case, common link in 1-sized array + $result[] = array( $m[0][0] ); + $offset += strlen($m[0][0]); + $start = $offset; + continue; + } + + // property declaration + if( count( SMWPropertyValue::makeUserProperty( $m[1][0] )->getErrors() ) > 0 ) { + $offset += 2; + $result[] = substr($text, $start, $offset - $start); + $start = $offset; + continue; + } + + $result[] = substr($text, $start, $offset - $start); + $start = $offset; + + $start2 = $start + strlen($m[0][0]); + $props = array(); + $props[] = $m[1][0]; + while( preg_match( '/([^:[][^]]*?):[=:]/xu', $text, $m, PREG_OFFSET_CAPTURE, $start2 ) ) { + $offset = $m[0][1]; + if( $offset != $start2 ) break; + if( count( SMWPropertyValue::makeUserProperty( $m[1][0] )->getErrors() ) > 0 ) break; + + $props[] = $m[1][0]; + $start2 = $offset + strlen($m[0][0]); + } + $propprefix = substr($text, $start, $start2 - $start); + $pval = array(); + if( self::parseProperties( $text, $pval, $start2, true ) ) { + $i = count($props) - 1; + $pval = array( 'name' => $props[$i], 'val' => $pval ); + while( $i > 0 ) { + --$i; + $pval = array( 'name' => $props[$i], 'val' => array( $pval ) ); + } + $result[] = $pval; + } else { + $result[] = $propprefix; + foreach($pval as $item) { + $result[] = $item; + } + } + $start = $start2; + } + $result[] = substr($text, $start); + + return false; + } + static private function renderProperties( &$parser, $prop ) { + $property = $prop['name']; + $pval = $prop['val']; + + $value = ''; + $caption = false; + + foreach($pval as $item) { + if(is_array($item)) { + if(count($item) == 1) { + // link + $t = $item[0]; + } else { + // property + $t = self::renderProperties($parser, $item); + } + if($caption === false) { + $value .= $t; + } else { + $caption .= $t; + } + } else { + if($caption === false) { + if(($idx = strpos($item, '|')) !== false) { + $value .= substr($item, 0, $idx); + $caption = substr($item, $idx + 1); + } else { + $value .= $item; + } + } else { + $caption .= $item; + } + } + } + + if ( $value == '' ) { // silently ignore empty values + return ''; + } + if ( $property == 'SMW' ) { + switch ( $value ) { + case 'on': + SMWParserExtensions::$mTempStoreAnnotations = true; + break; + case 'off': + SMWParserExtensions::$mTempStoreAnnotations = false; + break; + } + return ''; + } + + global $smwgInlineErrors, $smwgStoreAnnotations; + + // FIXME: not fully tested yet + // The following checks for markers generated by MediaWiki to handle special content, + // e.g. math. In general, SMW is not prepared to handle such content properly. + // Note: \x07 was used in MediaWiki 1.11.0, \x7f is used now + if ( ( strpos( $value, "\x7f" ) === false ) && ( strpos( $value, "\x07" ) === false ) ) { + $dv = SMWParseData::addProperty( $property, $value, $caption, SMWParserExtensions::$mTempParser, $smwgStoreAnnotations && SMWParserExtensions::$mTempStoreAnnotations ); + $result = $dv->getShortWikitext( true ); + if ( ( $smwgInlineErrors && $smwgStoreAnnotations && SMWParserExtensions::$mTempStoreAnnotations ) && ( !$dv->isValid() ) ) { + $result .= $dv->getErrorText(); + } + } else { + $unstrippedValue = $parser->mStripState->unstripBoth($value); + $dv = SMWParseData::addProperty( $property, $unstrippedValue, $caption, SMWParserExtensions::$mTempParser, $smwgStoreAnnotations && SMWParserExtensions::$mTempStoreAnnotations ); + // for text only, no check for now + $result = $caption ? $caption : $value; + if ( ( $smwgInlineErrors && $smwgStoreAnnotations && SMWParserExtensions::$mTempStoreAnnotations ) && ( !$dv->isValid() ) ) { + $result .= $dv->getErrorText(); + } + } + return $result; + } + static public function parsePropertiesRecursive( &$parser, &$text ) { + wfProfileIn( 'parsePropertiesRecursive (SMW)' ); + + self::parseProperties( $text, $doc ); + $text = ''; + foreach($doc as $item) { + if(!is_array($item)) { + // plain text + $text .= $item; + } elseif(count($item) == 1) { + // link + $text .= $item[0]; + } else { + $text .= self::renderProperties( $parser, $item); + } + } + + wfProfileOut( 'parsePropertiesRecursive (SMW)' ); + } }