summaryrefslogtreecommitdiff
path: root/includes/parser/Parser_LinkHooks.php
diff options
context:
space:
mode:
Diffstat (limited to 'includes/parser/Parser_LinkHooks.php')
-rw-r--r--includes/parser/Parser_LinkHooks.php326
1 files changed, 0 insertions, 326 deletions
diff --git a/includes/parser/Parser_LinkHooks.php b/includes/parser/Parser_LinkHooks.php
deleted file mode 100644
index b2cdc41a..00000000
--- a/includes/parser/Parser_LinkHooks.php
+++ /dev/null
@@ -1,326 +0,0 @@
-<?php
-/**
- * Modified version of the PHP parser with hooks for wiki links; experimental
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup Parser
- */
-
-/**
- * Parser with LinkHooks experiment
- * @ingroup Parser
- */
-class Parser_LinkHooks extends Parser {
- /**
- * Update this version number when the ParserOutput format
- * changes in an incompatible way, so the parser cache
- * can automatically discard old data.
- */
- const VERSION = '1.6.4';
-
- # Flags for Parser::setLinkHook
- # Also available as global constants from Defines.php
- const SLH_PATTERN = 1;
-
- # Constants needed for external link processing
- # Everything except bracket, space, or control characters
- const EXT_LINK_URL_CLASS = '[^][<>"\\x00-\\x20\\x7F]';
- const EXT_IMAGE_REGEX = '/^(http:\/\/|https:\/\/)([^][<>"\\x00-\\x20\\x7F]+)
- \\/([A-Za-z0-9_.,~%\\-+&;#*?!=()@\\x80-\\xFF]+)\\.((?i)gif|png|jpg|jpeg)$/Sx';
-
- /**#@+
- * @private
- */
- # Persistent:
- var $mLinkHooks;
-
- /**#@-*/
-
- /**
- * Constructor
- */
- public function __construct( $conf = array() ) {
- parent::__construct( $conf );
- $this->mLinkHooks = array();
- }
-
- /**
- * Do various kinds of initialisation on the first call of the parser
- */
- function firstCallInit() {
- parent::__construct();
- if ( !$this->mFirstCall ) {
- return;
- }
- $this->mFirstCall = false;
-
- wfProfileIn( __METHOD__ );
-
- $this->setHook( 'pre', array( $this, 'renderPreTag' ) );
- CoreParserFunctions::register( $this );
- CoreLinkFunctions::register( $this );
- $this->initialiseVariables();
-
- wfRunHooks( 'ParserFirstCallInit', array( &$this ) );
- wfProfileOut( __METHOD__ );
- }
-
- /**
- * Create a link hook, e.g. [[Namepsace:...|display}}
- * The callback function should have the form:
- * function myLinkCallback( $parser, $holders, $markers,
- * Title $title, $titleText, &$sortText = null, &$leadingColon = false ) { ... }
- *
- * Or with SLH_PATTERN:
- * function myLinkCallback( $parser, $holders, $markers, )
- * &$titleText, &$sortText = null, &$leadingColon = false ) { ... }
- *
- * The callback may either return a number of different possible values:
- * String) Text result of the link
- * True) (Treat as link) Parse the link according to normal link rules
- * False) (Bad link) Just output the raw wikitext (You may modify the text first)
- *
- * @param $ns Integer or String: the Namespace ID or regex pattern if SLH_PATTERN is set
- * @param $callback Mixed: the callback function (and object) to use
- * @param $flags Integer: a combination of the following flags:
- * SLH_PATTERN Use a regex link pattern rather than a namespace
- *
- * @throws MWException
- * @return callback|null The old callback function for this name, if any
- */
- public function setLinkHook( $ns, $callback, $flags = 0 ) {
- if( $flags & SLH_PATTERN && !is_string($ns) )
- throw new MWException( __METHOD__ . '() expecting a regex string pattern.' );
- elseif( $flags | ~SLH_PATTERN && !is_int( $ns ) )
- throw new MWException( __METHOD__ . '() expecting a namespace index.' );
- $oldVal = isset( $this->mLinkHooks[$ns] ) ? $this->mLinkHooks[$ns][0] : null;
- $this->mLinkHooks[$ns] = array( $callback, $flags );
- return $oldVal;
- }
-
- /**
- * Get all registered link hook identifiers
- *
- * @return array
- */
- function getLinkHooks() {
- return array_keys( $this->mLinkHooks );
- }
-
- /**
- * Process [[ ]] wikilinks
- * @param $s
- * @throws MWException
- * @return LinkHolderArray
- *
- * @private
- */
- function replaceInternalLinks2( &$s ) {
- wfProfileIn( __METHOD__ );
-
- wfProfileIn( __METHOD__ . '-setup' );
- static $tc = false, $titleRegex; //$e1, $e1_img;
- if( !$tc ) {
- # the % is needed to support urlencoded titles as well
- $tc = Title::legalChars() . '#%';
- # Match a link having the form [[namespace:link|alternate]]trail
- //$e1 = "/^([{$tc}]+)(?:\\|(.+?))?]](.*)\$/sD";
- # Match cases where there is no "]]", which might still be images
- //$e1_img = "/^([{$tc}]+)\\|(.*)\$/sD";
- # Match a valid plain title
- $titleRegex = "/^([{$tc}]+)$/sD";
- }
-
- $holders = new LinkHolderArray( $this );
-
- if( is_null( $this->mTitle ) ) {
- wfProfileOut( __METHOD__ . '-setup' );
- wfProfileOut( __METHOD__ );
- throw new MWException( __METHOD__ . ": \$this->mTitle is null\n" );
- }
-
- wfProfileOut( __METHOD__ . '-setup' );
-
- $offset = 0;
- $offsetStack = array();
- $markers = new LinkMarkerReplacer( $this, $holders, array( &$this, 'replaceInternalLinksCallback' ) );
- while( true ) {
- $startBracketOffset = strpos( $s, '[[', $offset );
- $endBracketOffset = strpos( $s, ']]', $offset );
- # Finish when there are no more brackets
- if( $startBracketOffset === false && $endBracketOffset === false ) break;
- # Determine if the bracket is a starting or ending bracket
- # When we find both, use the first one
- elseif( $startBracketOffset !== false && $endBracketOffset !== false )
- $isStart = $startBracketOffset <= $endBracketOffset;
- # When we only found one, check which it is
- else $isStart = $startBracketOffset !== false;
- $bracketOffset = $isStart ? $startBracketOffset : $endBracketOffset;
- if( $isStart ) {
- /** Opening bracket **/
- # Just push our current offset in the string onto the stack
- $offsetStack[] = $startBracketOffset;
- } else {
- /** Closing bracket **/
- # Pop the start pos for our current link zone off the stack
- $startBracketOffset = array_pop( $offsetStack );
- # Just to clean up the code, lets place offsets on the outer ends
- $endBracketOffset += 2;
-
- # Only do logic if we actually have a opening bracket for this
- if( isset( $startBracketOffset ) ) {
- # Extract text inside the link
- @list( $titleText, $paramText ) = explode( '|',
- substr( $s, $startBracketOffset + 2, $endBracketOffset - $startBracketOffset - 4 ), 2 );
- # Create markers only for valid links
- if( preg_match( $titleRegex, $titleText ) ) {
- # Store the text for the marker
- $marker = $markers->addMarker( $titleText, $paramText );
- # Replace the current link with the marker
- $s = substr( $s, 0, $startBracketOffset ) .
- $marker .
- substr( $s, $endBracketOffset );
- # We have modified $s, because of this we need to set the
- # offset manually since the end position is different now
- $offset = $startBracketOffset+strlen( $marker );
- continue;
- }
- # ToDo: Some LinkHooks may allow recursive links inside of
- # the link text, create a regex that also matches our
- # <!-- LINKMARKER ### --> sequence in titles
- # ToDO: Some LinkHooks use patterns rather than namespaces
- # these need to be tested at this point here
- }
- }
- # Bump our offset to after our current bracket
- $offset = $bracketOffset+2;
- }
-
- # Now expand our tree
- wfProfileIn( __METHOD__ . '-expand' );
- $s = $markers->expand( $s );
- wfProfileOut( __METHOD__ . '-expand' );
-
- wfProfileOut( __METHOD__ );
- return $holders;
- }
-
- function replaceInternalLinksCallback( $parser, $holders, $markers, $titleText, $paramText ) {
- wfProfileIn( __METHOD__ );
- $wt = isset( $paramText ) ? "[[$titleText|$paramText]]" : "[[$titleText]]";
- wfProfileIn( __METHOD__ . "-misc" );
-
- # Don't allow internal links to pages containing
- # PROTO: where PROTO is a valid URL protocol; these
- # should be external links.
- if( preg_match( '/^\b(?i:' . wfUrlProtocols() . ')/', $titleText ) ) {
- wfProfileOut( __METHOD__ . "-misc" );
- wfProfileOut( __METHOD__ );
- return $wt;
- }
-
- # Make subpage if necessary
- if( $this->areSubpagesAllowed() ) {
- $titleText = $this->maybeDoSubpageLink( $titleText, $paramText );
- }
-
- # Check for a leading colon and strip it if it is there
- $leadingColon = $titleText[0] == ':';
- if( $leadingColon ) $titleText = substr( $titleText, 1 );
-
- wfProfileOut( __METHOD__ . "-misc" );
- # Make title object
- wfProfileIn( __METHOD__ . "-title" );
- $title = Title::newFromText( $this->mStripState->unstripNoWiki( $titleText ) );
- if( !$title ) {
- wfProfileOut( __METHOD__ . "-title" );
- wfProfileOut( __METHOD__ );
- return $wt;
- }
- $ns = $title->getNamespace();
- wfProfileOut( __METHOD__ . "-title" );
-
- # Default for Namespaces is a default link
- # ToDo: Default for patterns is plain wikitext
- $return = true;
- if( isset( $this->mLinkHooks[$ns] ) ) {
- list( $callback, $flags ) = $this->mLinkHooks[$ns];
- if( $flags & SLH_PATTERN ) {
- $args = array( $parser, $holders, $markers, $titleText, &$paramText, &$leadingColon );
- } else {
- $args = array( $parser, $holders, $markers, $title, $titleText, &$paramText, &$leadingColon );
- }
- # Workaround for PHP bug 35229 and similar
- if ( !is_callable( $callback ) ) {
- throw new MWException( "Tag hook for namespace $ns is not callable\n" );
- }
- $return = call_user_func_array( $callback, $args );
- }
- if( $return === true ) {
- # True (treat as plain link) was returned, call the defaultLinkHook
- $return = CoreLinkFunctions::defaultLinkHook( $parser, $holders, $markers, $title,
- $titleText, $paramText, $leadingColon );
- }
- if( $return === false ) {
- # False (no link) was returned, output plain wikitext
- # Build it again as the hook is allowed to modify $paramText
- $return = isset( $paramText ) ? "[[$titleText|$paramText]]" : "[[$titleText]]";
- }
- # Content was returned, return it
- wfProfileOut( __METHOD__ );
- return $return;
- }
-
-}
-
-class LinkMarkerReplacer {
-
- protected $markers, $nextId, $parser, $holders, $callback;
-
- function __construct( $parser, $holders, $callback ) {
- $this->nextId = 0;
- $this->markers = array();
- $this->parser = $parser;
- $this->holders = $holders;
- $this->callback = $callback;
- }
-
- function addMarker( $titleText, $paramText ) {
- $id = $this->nextId++;
- $this->markers[$id] = array( $titleText, $paramText );
- return "<!-- LINKMARKER $id -->";
- }
-
- function findMarker( $string ) {
- return (bool) preg_match( '/<!-- LINKMARKER [0-9]+ -->/', $string );
- }
-
- function expand( $string ) {
- return StringUtils::delimiterReplaceCallback( "<!-- LINKMARKER ", " -->", array( &$this, 'callback' ), $string );
- }
-
- function callback( $m ) {
- $id = intval( $m[1] );
- if( !array_key_exists( $id, $this->markers ) ) return $m[0];
- $args = $this->markers[$id];
- array_unshift( $args, $this );
- array_unshift( $args, $this->holders );
- array_unshift( $args, $this->parser );
- return call_user_func_array( $this->callback, $args );
- }
-}