Extension:AutoLink

From MediaWiki.org

Jump to: navigation, search

       

Manual on MediaWiki Extensions
List of MediaWiki Extensions
Crystal Clear app error.png
AutoLink

Release status: unstable

Implementation  Extended syntax
Description Used to make auto links in a page during page view.
Author(s)  Sanjeev / Samuel Gelineau / Dirk Kreisel / Hyunsik Kim
Last Version  1.3 / 2.4 / 3.7
License No license specified
Download AutoLink

check usage (experimental)

Contents

[edit] What can this extension do?

When a new page is created, or an existing page is saved, Some of the specific words in the page content will automatically become links to other pages. Such Extension was very much required for my application so i thought of placing it here so that others if interested can use it.

[edit] Usage

[edit] Version 1.x

Once this extension is installed, just edit a page, add some content to it and save the page. The words in the page content which are present in the page AutoLinkPages will become links to respective page. So AutoLinkPages acts as a dictionary for the Auto Link words.

[edit] Version 2.x

Words in a page's content that match any other Page Title will be displayed as links to that page. (It is no longer necessary to create an AutoLinkPage page.)

[edit] Version 3.7

Feature : Attach a Link which matches other Page Titles in a page's content.

Mode selection : Autolink during save page, Autolink during page views

Caution : This version has to list all Page Titles, so it may takes much CPU and resources when using some BIG wiki.

If v3.7 works as Autolink during page views mode, it never change its original content in the DB.

[edit] Installation

  • (1.x only)Create a page with name AutoLinkPages. This page will contain : separated pagenames which have to be auto linked. For example AutoLinkPages.
  • Just copy the extension directy from AutoLink.
  • Save it as AutoLink.php in extensions directory.

[edit] Changes to LocalSettings.php

Include this extension in LocalSettings.php as follows:-

require_once("$IP/extensions/AutoLink.php");

[edit] Code

Note : Latest version at bottom.

[edit] version with restricted wordlist

<?php
/**
 * AutoLink extension
 * Adds Auto Links in A page.
 * Reads page 'AutoLinkPages', which works as Dictonary.
 *
 * @author Sanjeev
 * @version 1.2
 * @url http://www.mediawiki.org/wiki/Extension:AutoLink
 */
 
if ( ! defined( 'MEDIAWIKI' ) )
        die();
 
$wgExtensionCredits['other'][] = array(
    'name' => 'AutoLink',
    'version' => '1.2',
    'author' => '[http://www.mediawiki.org/wiki/User:Sanjualone Sanjeev]',
    'url' => 'http://www.mediawiki.org/wiki/Extension:AutoLink',
);
 
$wgHooks['ArticleSave'][] = 'wfAddAutoLinks';
 
#Event handler for ArticleSave event.
function wfAddAutoLinks(&$article, &$user, &$text) {
        $content = $text;
        $pages = array();
        #This should not work for the Page AutoLinkPages.

        if($article->mTitle->mTextform != 'AutoLinkPages') {
                $pages = getPages();
                $textlines = array();
                $textlines = explode('\n',$content);
                $newlines = array();
                foreach($textlines as $line) {
                        $textword = array();
                        $textword = explode(' ',$line);
                        $newwords = array();
                        foreach($textword as $word) {
                                if(strpos($word,'[') == false &&
                                   strpos($word,']') == false &&
                                   strpos($word,'<') == false &&
                                   strpos($word,'>') == false) {
                                      if(strstr($word,'.') == false || strstr($word,'.')== '.') {
                                        foreach($pages as $page) {
                                                if(strstr($word,$page))
                                                 $word=str_replace($page,"[[".$page."]]",$word);
                                        }
                                      }
                                }
                                $newwords[] = $word;
                        }
 
                        $newlines[] = implode(' ',$newwords);
                }
                $content = implode('\n',$newlines);
                $text = $content;
        }
        return true;
}
 
#Function to return page names from AutoLinkPages as an array()
function getPages() {
        $title = Title::newFromURL('AutoLinkPages');
        $article = new Article($title);
        $pagenames = $article->getContent();
        $pages = explode(':',$pagenames);
        return $pages;
}

[edit] new version with restricted wordlist also working for longer matches

<?php
/**
 * AutoLink extension
 * Adds Auto Links in A page.
 * Reads page 'AutoLinkPages', which works as Dictonary. Please seperate the restricted words with |
 *
 * @author Sanjeev, Samuel Gelineau, Dirk Kreisel
 * @version 1.3
 * @url http://www.mediawiki.org/wiki/Extension:AutoLink
 */
define('AUTOLINK_REPLACE_FIRST_ONLY', false);
define('AUTOLINK_EXCLUDED_PAGES', 'AutoLinkPages|Welcome to ASK');
define('AUTOLINK_LINK_DELIMITER', '|');
 
if (!defined('MEDIAWIKI' )) { die(); }    				
 
$wgExtensionCredits['other'][] = array(					
    'name' => 'AutoLink',
    'version' => '1.3',
    'author' => array('Sanjeev', 'Samuel Gelineau', '[mailto://dirk.kreisel@gmx.net Dirk Kreisel]'),
    'url' => 'http://www.mediawiki.org/wiki/Extension:AutoLink'
);
 
$wgHooks['ArticleSave'][] = 'wfAddAutoLinks';				
 
#Event handler for ArticleSave event.
function wfAddAutoLinks(&$article, &$user, &$text) {											
		#file_put_contents('c:\test.txt', $text);
        $content = $text;
        $pages = array();									
        #This should not work for the Page AutoLinkPages.
		
		$excludedPages = explode('|', AUTOLINK_EXCLUDED_PAGES);		
		foreach ($excludedPages as $excludedPage) {
	        if ($article->mTitle->mTextform == $excludedPage) {		
				return true;										
			}									
		}
 
		$pages = getPages();										
 
		foreach ($pages as $page) {									
			$pos = 0; $offset = 0;									
			while ($pos !== false) {
				if ($pos != 0) {
					$pos += strlen($page) + $offset;			
				}
 
				$pos = strpos($content, $page, $pos);				
				$offset = 0;
 
				if ($pos === false) {
					continue;										
				}
 
				if (preg_match('/[a-zA-Z0-9\[\<]/', $content[$pos-1]) == 0 &&
                                    preg_match('/[a-zA-Z0-9\]\>]/', $content[$pos+strlen($page)]) == 0) {				
 
					$content = substr($content, 0, $pos) . 
							   '[[' . substr($content, $pos, strlen($page)) . ']]' .	
							   substr($content, $pos + strlen($page));
					$offset = 4;																		
					if (AUTOLINK_REPLACE_FIRST_ONLY === true) {
						$pos = false;													
					}
				}
 
				if (AUTOLINK_REPLACE_FIRST_ONLY === true &&
	                            preg_match('/[\[]/', $content[$pos-1]) != 0 &&
	                            preg_match('/[\]]/', $content[$pos+strlen($page)]) != 0) {			
				$pos = false;
				}
			}
		}
 
		$text = $content;
		return true;
}
 
#Function to return page names from AutoLinkPages as an array()
function getPages() {
        $title = Title::newFromURL('AutoLinkPages');
        $article = new Article($title);
        $pagenames = $article->getContent();
        $pages = explode(AUTOLINK_LINK_DELIMITER, $pagenames);
        return $pages;
}

[edit] version which matches all pages

<?php
/**
 * AutoLink extension
 * Turn ordinary words into page links, if the name matches. to match plurals and variations,
 * write lots and lots of redirection pages.
 * The original version, by [http://www.mediawiki.org/wiki/User:Sanjualone Sanjeev], required
 * users to manually enter all the page names they wanted to match.
 * [http://www.mediawiki.org/wiki/User:Gelisam] completely rewrote the script (minus the
 * boilerplate) to match any page.
 *
 * @author Samuel Gelineau
 * @version 2.2
 * @url http://www.mediawiki.org/wiki/Extension:AutoLink
 */
if ( ! defined( 'MEDIAWIKI' ) )
        die();
 
$wgExtensionCredits['other'][] = array(
    'name' => 'AutoLink',
    'version' => '2.2',
    'author' => 'Samuel Gelineau',
    'url' => 'http://www.mediawiki.org/wiki/Extension:AutoLink'
);
 
$wgHooks['ArticleSave'][] = 'wfAddAutoLinks';
 
#Event Handler for ArticleSave Event.
function wfAddAutoLinks(&$article, &$user, &$text) {
        global $autolink__current_page;
        $autolink__current_page = str_replace(' ', '_', $article->mTitle->mTextform);
 
        $text = mapIgnoringBlocks(
                array(
                        "<createbox>", "</createbox>",
                        "<categorytree>", "</categorytree>",
                        "<DPL>", "</DPL>",
                        "[[", "]]",
                        "[", "]",
                        "{{", "}}",
                        "<nowiki>", "</nowiki>"
                ),
                $text,
                'autoLinkWords'
        );
        return true;
}
 
function mapIgnoringBlocks($delimiters, $text, $map) {
        if (count($delimiters) == 0) return $map($text);
 
        $block_start = array_shift($delimiters);
        $block_end = array_shift($delimiters);
 
        $result = "";
        $post_headers = explode($block_start, $text);
 
        $first_inter_block = array_shift($post_headers);
        $result = $result . mapIgnoringBlocks($delimiters, $first_inter_block, $map);
 
        foreach($post_headers as $post_header) {
                $block_and_inter_block = explode($block_end, $post_header, 2);
 
                $block = array_shift($block_and_inter_block);
                $result = $result . $block_start . $block . $block_end;
 
                $inter_block = array_shift($block_and_inter_block);
                $result = $result . mapIgnoringBlocks($delimiters, $inter_block, $map);
        }
 
        return $result;
}
 
function autoLinkWords($text) {
        global $autolink__current_page;
 
        $patterns = array();
        $replacements = array();
        foreach(getPages() as $page) {
                if ($page != $autolink__current_page) {
                        $pattern = str_replace('_', '[_ ]', preg_quote($page, '/'));
                        $pattern = '/\b((?<!\[)(?<!\/\/)' . $pattern . '(?!\]))\b/i';
 
                        $patterns[] = $pattern;
                        $replacements[] = '[[' . $page . '|\1]]';
                }
        }
        return preg_replace($patterns, $replacements, $text);
}
 
#Function to return page names from AutoLinkPages as an array()
function getPages() {
        $dbr = &wfGetDB(DB_SLAVE);
        $result_set = $dbr->select('page', array('page_title'), array('page_namespace' => 0));
        $titles = array();
        while (
                ($row = $dbr->fetchObject($result_set))
        ) {
                $titles[] = $row->page_title;
        }
        $dbr->freeResult($result_set);
        return $titles;
}

[edit] version which matches all pages giving preference to longer matches

<?php
/**
 * AutoLink extension
 * Turn ordinary words into page links, if the name matches. to match plurals and variations,
 * write lots and lots of redirection pages.
 * The original version, by [http://www.mediawiki.org/wiki/User:Sanjualone Sanjeev], required
 * users to manually enter all the page names they wanted to match.
 * [http://www.mediawiki.org/wiki/User:Gelisam] completely rewrote the script (minus the
 * boilerplate) to match any page.
 *
 * On 08/24/2007, a new version was created by [http://www.mediawiki.org/wiki/User:Vjg] which
 * gives preference to longer page names. It switches the order of processing, handling the
 * article for each page, but only building the page array once. The previous version handled
 * the article once, but built the page array on each pass. I haven't fully explored all the
 * performance implications. This was for use on a relatively small site.
 *
 * @author Virgil Green
 * @version 2.3
 * @url http://www.mediawiki.org/wiki/Extension:AutoLink
 */
 
if ( ! defined( 'MEDIAWIKI' ) )
        die();
 
$wgExtensionCredits['other'][] = array(
    'name' => 'AutoLink',
    'version' => '2.3',
    'author' => 'Virgil Green',
    'url' => 'http://www.mediawiki.org/wiki/Extension:AutoLink',
);
 
$wgHooks['ArticleSave'][] = 'wfAddAutoLinks';
 
#Event Handler for ArticleSave Event.
function wfAddAutoLinks(&$article, &$user, &$text) {
        global $autolink__current_page;
        $autolink__current_page = str_replace(' ', '_', $article->mTitle->mTextform);
 
        $text = autoLinkWords(
                array(
                        "<createbox>", "</createbox>",
                        "<categorytree>", "</categorytree>",
                        "<DPL>", "</DPL>",
                        "[[", "]]",
                        "[", "]",
                        "{{", "}}",
                        "<nowiki>", "</nowiki>"
                ),
                $text
        );
        return true;
}
 
function mapIgnoringBlocks($delimiters, $text, $pattern, $replacement) {
        if (count($delimiters) == 0) {
                return preg_replace($pattern, $replacement, $text);
        }
 
        $block_start = array_shift($delimiters);
        $block_end = array_shift($delimiters);
 
        $result = "";
        $post_headers = explode($block_start, $text);
 
        $first_inter_block = array_shift($post_headers);
        $result = $result . mapIgnoringBlocks($delimiters, $first_inter_block, $pattern, $replacement);
 
        foreach($post_headers as $post_header) {
                $block_and_inter_block = explode($block_end, $post_header, 2);
 
                $block = array_shift($block_and_inter_block);
                $result = $result . $block_start . $block . $block_end;
 
                $inter_block = array_shift($block_and_inter_block);
                $result = $result . mapIgnoringBlocks($delimiters, $inter_block, $pattern, $replacement);
        }
 
        return $result;
}
 
function autoLinkWords($delimiters, $text) {
        global $autolink__current_page;
 
        $patternMap = array();
        foreach(getPages() as $page) {
                if ($page != $autolink__current_page) {
                        $pattern = str_replace('_', '[_ ]', preg_quote($page, '/'));
                        $pattern = '/\b((?<!\[)(?<!\/\/)' . $pattern . '(?!\]))\b/i';
 
                        $patternMap[$pattern] = '[[' . $page . '|\1]]';
                }
        }
        foreach($patternMap as $pattern=>$replacement) {
                $text = mapIgnoringBlocks($delimiters, $text, $pattern, $replacement);
        }
        return $text;
}
 
#Function to return page names from AutoLinkPages as an array()
function getPages() {
        $dbr = &wfGetDB(DB_SLAVE);
        $result_set = $dbr->select('page', array('page_title'), array('page_namespace' => 0), __METHOD__, array('ORDER BY' =>'page_title desc'));
        $titles = array();
        while (
                ($row = $dbr->fetchObject($result_set))
        ) {
                $titles[] = $row->page_title;
        }
        $dbr->freeResult($result_set);
        return $titles;
}

[edit] version which matches all pages preferring longer page names and provides shorter, easier to read links, add magic words

<?php
/**
 * AutoLink extension
 * Turn ordinary words into page links, if the name matches. to match plurals and variations,
 * write lots and lots of redirection pages.
 * The original version, by [http://www.mediawiki.org/wiki/User:Sanjualone Sanjeev], required
 * users to manually enter all the page names they wanted to match.
 * [http://www.mediawiki.org/wiki/User:Gelisam] completely rewrote the script (minus the
 * boilerplate) to match any page.
 *
 * On 08/24/2007, a new version was created by [http://www.mediawiki.org/wiki/User:Vjg] which
 * gives preference to longer page names. It switches the order of processing, handling the
 * article for each page, but only building the page array once. The previous version handled
 * the article once, but built the page array on each pass. I haven't fully explored all the
 * performance implications. This was for use on a relatively small site.
 *
 * on 09/10/2008, a new version was created by Krishna Maheshwari
 * which doesn't add a pipe & link if the page name matches the text (longest matches first).  It also strips all links 
 * prior to regenerating them, ensuring if changes or other articles are created with longer names
 * that match, than they are used.  Ie: This Text could be transformed to This [[Text]] than on a
 * subsequent edit become [[This Text]]. In addition, it only allows the first occurance of a page
 * to be linked instead of each occurance. This extension is used on Hindupedia (www.hindupedia.com)
 * New Tags: __NOAUTOLINK__ => this extension doesn't try to generate any links for page
 *           __NOREGENERATELINKS__ => don't try to regenerate links
 *           <noautolink> ... </noautolink> => don't generate links on content inside these tags
 * @author Krishna Maheshwari
 * @version 2.4
 * @url http://www.mediawiki.org/wiki/Extension:AutoLink
 */
 
if ( ! defined( 'MEDIAWIKI' ) )
        die();
 
$wgExtensionCredits['other'][] = array(
    'name' => 'AutoLink',
    'version' => '2.4',
    'author' => 'Krishna Maheshwari',
    'url' => 'http://www.mediawiki.org/wiki/Extension:AutoLink',
);
 
$wgHooks['ArticleSave'][] = 'wfAddAutoLinks';
$wgHooks['MagicWordMagicWords'][] = 'AutolinkMagicWordMagicWords';
$wgHooks['MagicWordwgVariableIDs'][] = 'AutolinkMagicWordwgVariableIDs';
$wgHooks['LanguageGetMagic'][] = 'AutolinkLanguageGetMagic';
$wgHooks['ParserBeforeInternalParse'][] = 'AutolinkParserBeforeInternalParse';
 
#ideally, this would work here so that the article isn't changed, only the display is.
#however, this will also increase the load on the wiki (does not work right now)
#$wgHooks['InternalParseBeforeLinks'][] = 'wfAddAutoLinks';
 
#Event Handler for ArticleSave Event.
function wfAddAutoLinks(&$article, &$user, &$text) {
        global $autolink__current_page;
        $autolink__current_page = str_replace(' ', '_', $article->mTitle->mTextform);
 
        #potential bug: sometimes doesn't parse pages > 32k.  if confirmed, remove comment below
        #               to prevent parsing of large pages
        #if (mb_strlen($text, 'latin1') > 32768) { return true; }

        #if we specificy no autolink, than don't autolink
        if (preg_match('/__NOAUTOLINK__/', $text)) { return true; } 
 
        #as long as we are allowed to regenerate links...
        if (!preg_match('/__NOREGENERATELINKS__/', $text)) {
          #strip links so that all links are regenerated except those that are custom links
          #ie have a '|' or ')' or '(' in them
          $text = preg_replace('/\[\[([^|:\(\)\]]*)\]\]/','\1',$text);
        }
 
        $text = autoLinkWords(
                array(
                        "<noautolink>","</noautolink>", #add tag that prevents autolinking in parts of article
                        "<createbox>", "</createbox>",
                        "<categorytree", "</categorytree>",
                        "<DPL>", "</DPL>",
                        "[[", "]]",
                        "[", "]",
                        "{{", "}}",
                        "<nowiki>", "</nowiki>"
                ),
                $text
        );
 
        return true;
}
 
function mapIgnoringBlocks($delimiters, $text, $pattern, $replacement, &$phrasecount) {
        if (count($delimiters) == 0) {
           if ($phrasecount < 2) {
                #make sure that we don't change the capitaliation of the string we are replacing
                $replaceResult = preg_replace($pattern, '[[' . '\1' . ']]', $text, 1);
 
                if ($replaceResult != $text) { $phrasecount++; }
                return $replaceResult;
           }
           else {
                return $text;
           }
        }
 
        $block_start = array_shift($delimiters);
        $block_end = array_shift($delimiters);
 
        $result = "";
        $post_headers = explode($block_start, $text);
 
        $first_inter_block = array_shift($post_headers);
        $result = $result . mapIgnoringBlocks($delimiters, $first_inter_block, $pattern, $replacement, $phrasecount);
 
        foreach($post_headers as $post_header) {
                $block_and_inter_block = explode($block_end, $post_header, 2);
 
                $block = array_shift($block_and_inter_block);
                $result = $result . $block_start . $block . $block_end;
 
                $inter_block = array_shift($block_and_inter_block);
                $result = $result . mapIgnoringBlocks($delimiters, $inter_block, $pattern, $replacement, $phrasecount);
        }
 
        return $result;
}
 
function autoLinkWords($delimiters, $text) {
        global $autolink__current_page;
 
        foreach(getPages() as $page) {
                if ($page != $autolink__current_page) {
                        $pattern = str_replace('_', '[_ ]', preg_quote($page, '/'));
                        $pattern = '/\b((?<!\[)(?<!\/\/)' . $pattern . '(?!\]))\b/i';
 
                        $match = '\1';
                        if ($match = $page) {
                              $matchMap[$match] = 0;
                              $match = str_replace('_',' ', $match);
                              $patternMap[$pattern] = '[[' . $match . ']]';
                        }
                }
        }
        foreach($patternMap as $pattern=>$replacement) {
                $tmpstr = str_replace(' ','_', $replacement);
                $index = substr($tmpstr,2,-2);
                $matchCount = $matchMap[$index];
                $text = mapIgnoringBlocks($delimiters, $text, $pattern, $replacement, $matchCount);
                $matchMap[$index] = $matchCount;
        }
 
        return $text;
}
 
#Function to return page names from AutoLinkPages as an array()
function getPages() {
        $dbr = &wfGetDB(DB_SLAVE);
        $result_set = $dbr->select('page', array('page_title'), array('page_namespace' => 0), __METHOD__, array('ORDER BY' =>'page_title desc'));
        $titles = array();
        while (($row = $dbr->fetchObject($result_set))) {
                $titles[] = $row->page_title;
        }
        $dbr->freeResult($result_set);
        uasort($titles,"Ascii_sort"); //Longest page titles first
        return $titles;
}
 
function Ascii_sort($val_1, $val_2)
{
        // initialize the return value to zero
        $retVal = 0;
 
        // compare lengths
        $firstVal = strlen($val_1);
        $secondVal = strlen($val_2);
 
        if($firstVal > $secondVal) {
                $retVal = -1;
        }
        else if($firstVal < $secondVal) {
                $retVal = 1;
        }
        return $retVal;
}
 
//////////// Magic Word Functions //////////// 
 
function AutolinkMagicWordMagicWords(&$magicWords)
{
        $magicWords[] = 'MAG_NOAUTOLINK';
        $magicWords[] = 'MAG_NOREGENERATELINKS';
        return true;
}
 
function AutolinkMagicWordwgVariableIDs(&$wgVariableIDs)
{
        $wgVariableIDs[] = MAG_NOAUTOLINK;
        $wgVariableIDs[] = MAG_NOREGENERATELINKS;
        return true;
}
 
function AutolinkLanguageGetMagic(&$magicWords, $langCode)
{
        $magicWords[MAG_NOAUTOLINK] = array( 0, '__NOAUTOLINK__');
        $magicWords[MAG_NOREGENERATELINKS] = array( 0, '__NOREGENERATELINKS__' );
        return true;
}
 
function AutolinkParserBeforeInternalParse($parser, $text, $stripState)
{
        if (MagicWord::get( MAG_NOAUTOLINK )->matchAndRemove( $text ) )
        {
                $parser->mOptions->mNumberHeadings = (TRUE);
        }
        if (MagicWord::get( MAG_NOREGENERATELINKS)->matchAndRemove( $text ) )
        {
                $parser->mOptions->mNumberHeadings = (TRUE);
        }
        return true;
}

[edit] Added Feature Autolink during page views

<?php
/**
 * AutoLink extension
 * Turn ordinary words into page links, if the name matches. to match plurals and variations,
 * write lots and lots of redirection pages.
 * The original version, by [http://www.mediawiki.org/wiki/User:Sanjualone Sanjeev], required
 * users to manually enter all the page names they wanted to match.
 * [http://www.mediawiki.org/wiki/User:Gelisam] completely rewrote the script (minus the
 * boilerplate) to match any page.
 *
 * On 08/24/2007, a new version was created by [http://www.mediawiki.org/wiki/User:Vjg] which
 * gives preference to longer page names. It switches the order of processing, handling the
 * article for each page, but only building the page array once. The previous version handled
 * the article once, but built the page array on each pass. I haven't fully explored all the
 * performance implications. This was for use on a relatively small site.
 *
 * on 09/10/2008, a new version was created by Krishna Maheshwari
 * which doesn't add a pipe & link if the page name matches the text (longest matches first).  It also strips all links 
 * prior to regenerating them, ensuring if changes or other articles are created with longer names
 * that match, than they are used.  Ie: This Text could be transformed to This [[Text]] than on a
 * subsequent edit become [[This Text]]. In addition, it only allows the first occurance of a page
 * to be linked instead of each occurance. This extension is used on Hindupedia (www.hindupedia.com)
 * New Tags: __NOAUTOLINK__ => this extension doesn't try to generate any links for page
 *           __NOREGENERATELINKS__ => don't try to regenerate links
 *           <noautolink> ... </noautolink> => don't generate links on content inside these tags
 *
 * On 12/25/2008, a new version was created by Hyunsik Kim
 * completly rewritten version. Main function refer to the version 2.4
 * magic word function has been removed because I don't know what it is.
 * reduce regex functions and replace faster one, improve getting title function.
 * consider nested tag structure.
 * longest match uses first.
 *    -- v3.2 : Bug fix - MakeRegion
 *    -- v3.3 : Improve Regioning function - Increase speed.
 *    -- v3.5 : Feature added Autolink execute when view page.
 *    -- 12/26/2008, v3.6 : Increse Parse speed.
 *    -- 12/27/2008, v3.7 : Bug fix - Prevent link strip at protected block.
 *
 * @author Hyunsik Kim (E-mail:weatherbless.story@gmail.com)
 * @version 3.7
 * @url http://www.mediawiki.org/wiki/Extension:AutoLink
 */
 
if (!defined('MEDIAWIKI')) die();
 
$wgExtensionCredits['other'][] = array(
    'name' => 'AutoLink',
    'version' => '3.7',
    'author' => 'Hyunsik Kim',
    'url' => 'http://www.mediawiki.org/wiki/Extension:AutoLink',
);
 
########################## Enable Autolink ###########################
# We don't recommend both options has been enabled at the same time. #

# To activate Autolink after edit page, uncomment this:
#$wgHooks['ArticleSave'][] = 'wfAutoLink_ArticleSave';

# To activate Autolink during page view, uncomment this:
$wgHooks['ArticleAfterFetchContent'][] = 'wfAutoLink_ArticleAfterFetchContent';
 
# Event Handler for ArticleAfterFetchContent Event.
function wfAutoLink_ArticleAfterFetchContent(&$article, &$text)
{
	global $action;
	$currentPage = $article->mTitle->mTextform;
 
	# Actions : view, watch, unwatch, delete, revert, rollback, protect, unprotect,
	#           info, markpatrolled, render, deletetrackback, purge, print, dublincore,
	#           creativecommons, credits, submit, edit, editredlink, history, raw, ajax
	# Refer to [http://www.mediawiki.org/wiki/Manual:Page_action#Actions]
	switch( $action )
	{
		case '':
		case 'view':
		case 'render':
		case 'purge':
		case 'print':
			AutoLink_Parse($currentPage, $text);
			break;
		case 'edit':
		case 'editredlink':
			break;
		default:
			break;
	}
 
	return true;
}
 
# Event Handler for ArticleSave Event.
function wfAutoLink_ArticleSave(&$article, &$user, &$text)
{
	return AutoLink_Parse($article->mTitle->mTextform, &$text);
}
 
function AutoLink_Parse($title, &$text)
{
	# Set ignoring blocks. It must include "[[" and "]]"
	# Otherwise, It may cause endless recursion.
	$ignoreBlocks = array(
		array("[[", "]]"),
		array("[", "]"),
		array("{{", "}}"),
		array("<pre", "</pre>"),
		array("<nowiki>", "</nowiki>"),
		array("<noautolink>","</noautolink>"),
		array("<createbox>", "</createbox>"),
		array("<categorytree>", "</categorytree>"),
		array("<DPL>", "</DPL>"),
		array("#REDIRECT", "]]"),
		);
 
	$currentPage = str_replace(" ", "_", $title);
 
	# If we specificy no autolink, than don't autolink
	if (stripos($text, '__NOAUTOLINK__') !== false) { return true; } 
 
	# As long as we are allowed to regenerate links...
	if (stripos($text, '__NOREGENERATELINKS__') === false)
	{
		# Strip links so that all links are regenerated except those that are custom links
		# ie have a '|' or ')' or '(' in them
		# It only work for odd number region(Protected area).
		$region = AutoLink_MakeRegion($text, $ignoreBlocks);
 
		for ( $i = 1; $i < count($region); $i += 2)
		{
			$region[$i] = preg_replace('/^\[\[([^|:\(\)\]]*)\]\]$/','\1',$region[$i]);
		}
 
		# Merge regions so that all stripped links are unprotected.
		$text = implode($region);
	}
 
	$titles = AutoLink_GetTitleList($currentPage);
	AutoLink_MakeLink($titles, $text, $ignoreBlocks);
 
	return true;
}
 
function AutoLink_GetTitleList($currentPage)
{
	$dbr = &wfGetDB(DB_SLAVE);
	$result = $dbr->select('page', array('page_title'), 'page_namespace=0 AND page_title <> "'.$currentPage.'"', __METHOD__, array('ORDER BY' =>'CHAR_LENGTH(page_title) DESC'));
 
	$titles = array();
 
	while (($row = $dbr->fetchObject($result)))
	{
		$titles[] = $row->page_title;
	}
	$dbr->freeResult($result);
 
	return $titles;
}
 
function AutoLink_FindFirstSkipBlock(&$ignoreBlocks, &$text)
{
	$startTag = "";
	$endTag = "";
	$firstTag_start = strlen($text) + 1; # sentinel value

	foreach($ignoreBlocks as $tagPair)
	{
		$curTag_start = stripos($text, $tagPair[0]);
		if ( $curTag_start !== false && $firstTag_start > $curTag_start )
		{
			$startTag = $tagPair[0];
			$endTag = $tagPair[1];
			$firstTag_start = $curTag_start;
		}
	}
 
	if ( $firstTag_start > strlen($text) ) return false;
 
	$startTagLength = strlen($startTag);
	$endTagLength = strlen($endTag);
	$firstTag_end = stripos($text, $endTag, $firstTag_start + $startTagLength);
	$nextPosition = $firstTag_start + $startTagLength;
	$tagDepth = 0;
	while ( true )
	{
		$findPosition = stripos($text, $startTag, $nextPosition);
		if ( $findPosition === false || $findPosition > $firstTag_end )
		{
			break;
		}
 
		$nextPosition = $findPosition + $startTagLength;
		++$tagDepth;
	}
 
	$nextPosition = $firstTag_end + $endTagLength;
 
	while ( $tagDepth > 0 )
	{
		$findPosition = stripos($text, $endTag, $nextPosition);
 
		# If orpant tag has been detected, whole block is selected.
		if ( $findPosition === false )
		{
			$nextPosition = strlen($text);
			break;
		}
 
		$nextPosition = $findPosition + $endTagLength;
		--$tagDepth;
	}
 
	$firstTag_end = $nextPosition;
 
	return array($firstTag_start, $firstTag_end);
}
 
function AutoLink_MakeRegion(&$text, &$ignoreBlocks)
{
	$textLength = strlen($text);
 
	# Region :: Even : Normal text area, Odd : Protected area(skip autolink)
	$region = array();
 
	$skipBlock = AutoLink_FindFirstSkipBlock($ignoreBlocks, $text);
 
	# Recursion Terminate condition
	if ( $skipBlock === false )
	{
		return array($text);
	}
 
	$splitBegin = $skipBlock[0];
	$splitEnd = $skipBlock[1];
 
	$region = array_merge(
		array(substr($text, 0, $splitBegin),
		substr($text, $splitBegin, $splitEnd - $splitBegin)),
		AutoLink_MakeRegion(substr($text, $splitEnd  , $textLength - $splitEnd), $ignoreBlocks)
		);
 
	return $region;
}
 
function AutoLink_MakeLink(&$titles, &$text, &$ignoreBlocks)
{
	$autoLinkTag = array(array("[[","]]"));
	$region = AutoLink_MakeRegion($text, $ignoreBlocks);
 
	foreach($titles as $page)
	{
		$pattern = str_replace('_','[_ ]', preg_quote($page, '/'));
		$patternLength = strlen($page);
		$replace = '[['.str_replace('_', ' ', $page).']]';
 
		# Make links. It only work for even number region.
		# Odd number region is ignoring block(include already linked text)
		for ( $i = 0; $i < count($region); )
		{
			if ( strlen($region[$i]) < $patternLength )
			{
				$i += 2;
				continue;
			}
 
			$region[$i] = preg_replace('/'.$pattern.'/i', $replace, $region[$i]);
			$newRegion = AutoLink_MakeRegion($region[$i], $autoLinkTag);
			array_splice($region, $i, 1, $newRegion);
			$i += count($newRegion) + 1;
		}
	}
 
	$text = implode($region);
}
?>

[edit] Contact

In case of any issues please get in touch with Sanjeev. Thanks!

[edit] See also