'|', '<' -> '[', '>' -> ']' in SearchTitle Version: 0.2 2008.11.11 Change: - change 'like search' to 'regexp search' in searchtitle - compliant mediawiki 1.12 or later - bug fix searchTitle/Title2/Line History Version: 0.1 2008.09.26 ********************************************************************* Copyright (C) 2008-2010 Metabolomics.JP Development Team 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ********************************************************************* Author: Arita laboratory, with Kazuhiro Suwa URL: http://metabolomics.jp/ */ if ( !defined( 'MEDIAWIKI' ) ) { die( 'This file is a MediaWiki extension, see ExtendedFunctions.php.' ); } $wgExtensionFunctions[] = 'efSetupExFunctions'; $wgExtensionCredits['parserhook'][] = array( 'name' => 'ExtendedFunctions', 'version' => '0.3', 'author' => 'K, Suwa
Original Source - Tim Starling', 'description' => 'Powerful parser functions', 'url' => 'http://metabolomics.jp/wiki/Help:Extension/ExtendedFunctions', ); $wgHooks['LanguageGetMagic'][] = 'efExFunctionsLanguageGetMagic'; class ExFunctions { /** * Extracting string * e.g. {{#substring:Hello world|1}} => "ello world" * e.g. {{#substring:Hello world|1|4}} => "ell" * * @param $parser Parser Parent parser * @param $str string Target string * @param $start int Start index (including value) * @param $end int End index (not including value) * @return string Parts string */ function substring( &$parser, $str, $start = 0, $end = 0 ) { if($start < 0) $start = 0; if($end <= 0) $end = mb_strlen( $str ); return mb_substr( $str, $start, $end-$start ); } /** * Examine string length * e.g. {{#length:Hello world}} => 11 * * @param $parser Parser Parent parser * @param $str string Target string * @return string String length */ function length( &$parser, $str ) { return mb_strlen( $str ); } /** * Get position which $pattern in $str. You can use ' ' as ' '(space). * e.g. {{#indexOf:Hello world|wor}} => 6 * e.g. {{#indexOf:Hello world| }} => 5 * * @param $parser Parser Parent parser * @param $str string Target string * @param $pattern string search string * @param $offset int start position * @return int If exists $pattern, then String position, else ''. */ function indexOf( &$parser, $str, $pattern = ' ', $offset = 0 ) { if( strlen( $pattern ) == 0 ) $pattern = ' '; # replace ' ' to ' ' $pattern = ereg_replace( ' ', ' ', $pattern ); # check offset # if( strncmp( $offset, '', 4 ) == 0 ) if( strlen( $offset ) == 0 ) $offset = 0; if( !ereg( '^[0-9]+$', $offset ) ) $offset = 0; $length = mb_strlen( $str ); if( $length <= $offset ) return ''; $index = mb_strpos( $str, $pattern, $offset ); if( $index === false ) return ''; return $index; } /** * Get last position which $pattern in $str. You can use ' ' as ' '(space). * e.g. {{#lastIndexOf:abc abc abc|abc}} => 8 * e.g. {{#lastIndexOf:abc abc abc| }} => 7 * * @param $parser Parser Parent parser * @param $str string Target string * @param $pattern string search string * @return int If exists $pattern, then String last position, else ''. */ function lastIndexOf( &$parser, $str, $pattern = ' ' ) { $pattern = ereg_replace( ' ', ' ', $pattern ); $index = mb_strrpos( $str, $pattern ); if( $index === false ) return ''; return $index; } /** * Is $str digit? 'digit' is $str including 0-9 only * e.g. {{#isdigit:1234567890|This is digit|This isn't digit}} => 'This is digit' * e.g. {{#isdigit:123abc456|This is alphanumeric|This isn't alphanumeric}} => 'This isn't alphanumeric}} * * @param $parser Parser Parent parser * @param $str str Target string * @param $then then return string, if $str is digit * @param $else else return string, if $str isn't digit * @return if $str is digit, then return $then, else return $else */ function isdigit( &$parser, $str, $then = '', $else = '' ) { if( ereg( '^[0-9]+$', $str ) ) return $then; else return $else; } /** * Is $str alphanumeric? 'alphanumeric' is $str including 0-9,a-z,A-Z only * e.g. {{#isdigit:123abc456|This is alphanumeric|This isn't alphanumeric}} => 'This is alphanumeric}} * e.g. {{#isdigit:*123abc456*|This is alphanumeric|This isn't alphanumeric}} => 'This isn't alphanumeric}} * * @param $parser Parser Parent parser * @param $str string Target string * @param $then string return string, if $str is alphanumeric * @param $else string return string, if $str isn't alphanumeric * @return string if $str is alphanumeric, then return $then, else return $else */ function isalnum( &$parser, $str = '', $then = '', $else = '' ) { if( ereg( '^[0-9a-zA-Z]+$', $str ) ) return $then; else return $else; } /** * Call specified template, until finishing consuming argument * e.g. {{#repeat:template|3|a,b,c,d,e,f,g,h,i|,}} => {{template|a|b|c}} {{template|d,e,f}} {{template|g|h|i}} * * @param $parser Parser Parent parser * @param $template string Called template * @param $args int Use argument number which consumed a call * @param $argv string argument which splited $sep * @param $sep string separator of $argv * @param $pre string concatenate to string head * @param $post string concatenate to string tail * @return string wiki template string parsed by mediawiki */ function repeat( &$parser, $template, $args, $argv, $sep = "\n", $pre = '', $post = '' ) { # replace ' ' to ' ' if(strncmp($sep, ' ', 7) == 0) $sep = ' '; # replace '\n' to "\n" if(strncmp($sep, '\n', 4) == 0) $sep = "\n"; # check $args, $args max 2000 if($args <= 0) return ""; if($args > 2000) $args = 2000; if( strlen( $argv ) == 0 ){ return ""; } $sep = str_replace( '$', '\$', $sep ); $arg = split($sep, $argv); $size = count($arg); $str = ""; for($i = 0; $i < $size; $i += $args) { $str .= "{{" . $template; for($j = 0; $j < $args && $i+$j < $size; $j ++){ $str .= "|" . $pre . $arg[$i+$j] . $post; } $str .= "}}"; } if( method_exists( $parser, 'preprocessToDom' ) ){ # mw 1.12 or later return array( $parser->preprocessToDom( $str ), 'isChildObj' => true ); } # mw 1.11 or under return $str; } /** * Get carriage return * e.g. {{#cr:}} => "\n" * * @param $parser Parser Parent parser * @return string carriage return */ function cr( &$parser ) { return "\n"; } /** * Get pipe(|) * e.g. {{#bar:}} => '|' * * @param $parser Parser Parent parser * @return string pipe(|) */ function bar( &$parser ) { return "|"; } /** * Examine number $pattern in $str * e.g. {{#count:abcabcabca|a}} => 4 * * @param $parser Parser Parent parser * @param $str string Target String * @param $pattern string Search pattern * @return int $pattern number in $str */ function countHook( &$parser, $str, $pattern = "\n" ) { if( mb_strlen( $str ) == 0 || mb_strlen( $pattern ) == 0 ) return 0; if( strncmp( $pattern, "\n", 4) == 0 ) return substr_count( trim( $str ), $pattern ) + 1; return mb_substr_count( $str, $pattern ); } /** * Examine exists file * e.g. {{#ifexistfile:/index.htm}} -> [http://DOMAIN/index.html index.html] * * @param $parser Parser Parent parser * @param $str string Path to file from DOCUMENT_ROOT * @return string If exists, then return link to path, else return '' */ function ifexistfile( &$parser, $path ) { # check path, if including '..'(Parent directory), return '' if( !( strpos( $path, '..' ) === false ) ) return ''; if( !isset( $_SERVER["DOCUMENT_ROOT"] ) || strlen( $_SERVER["DOCUMENT_ROOT"] ) == 0 ) $prefix = "/var/www/htdocs"; // DOCUMENT_ROOT else $prefix = $_SERVER["DOCUMENT_ROOT"]; if( !isset( $_SERVER["SERVER_NAME"] ) || strlen( $_SERVER["SERVER_NAME"] ) == 0 ) $server = "metabolomics.jp/"; // "[your domain]/". ex. "metabolomics.jp/" else $server = $_SERVER["SERVER_NAME"]; if( file_exists( $prefix . '/' . $path ) ){ $index = strrpos( $path, '/' ); if( $index < 0 ) $index = 0; return '[http://' . $server . $path . ' ' . substr($path, $index+1) . ']'; } return ""; } /** * Replace string. You can use ' ' as ' '(space), '|' as '|'(Bar) and ' ' as '\n'(cr) * e.g. {{#replace|abcdefghi|def|123}} => abc123ghi * * @param $parser Parser Parent parser * @param $string string Target string * @param $pattern string Replace target * @param $replacement string Replace string * @return string Return $string which replace $pattern to $replacement */ function replace( &$parser, $string, $pattern, $replacement ) { $pattern = ereg_replace( ' ', ' ', $pattern ); $replacement = ereg_replace( ' ', ' ', $replacement ); $pattern = ereg_replace( '|', '\|', $pattern ); $replacement = ereg_replace( '|', '|', $replacement ); $pattern = ereg_replace( ' ', "\n", $pattern ); $replacement = ereg_replace( ' ', "\n", $replacement ); mb_regex_encoding("UTF-8"); return mb_ereg_replace( $pattern, $replacement, $string ); } /** * java applet with * e.g. {{#javawithparam:Main.class|Main.jar|.|100|100|data=123;id=java}} => * * * * * * @param $parser Parser Parent parser * @param $class string Main class file * @param $archive string Archive file * @param $codebase string Codebase * @param $width int Applet width * @param $height int Applet height * @param $param string Passed parameter * @return string Java applet HTML string */ function javaWithParam( &$parser, $class, $archive, $codebase = '.', $width = 100, $height = 100, $param = '' ) { # if( strncmp( $param, '', 4) != 0) if( strlen( $param ) > 0 ) $parser->disableCache(); $output = ""; $params = split( ';', $param ); foreach( $params as $p ){ $keys = split( '=', $p ); $output .= " \n"; } $output .= ""; return array( $output, 'noparse' => true ); } /** * Search $word from all page * e.g. {{#searchline:search|0}} => * 'you can search ...' * 'search is not ...' * ... * * @param $parser Parser Parent parser * @param $word string Search word * @param $namespace int Target namespace. Default is 0(Main) * @param $page string Target page. Option. * @return string All lines including $word.(But excluding myself) */ function searchLine( &$parser, $word, $namespace = 'Main', $page = '' ) { global $wgCanonicalNamespaceNames, $wgExtraNamespaces; if( defined( 'REMOTE_SEARCH' ) && ereg( ':', $namespace ) ){ $rs = new RemoteSearch(); list( $server, $ns ) = split( ':', $namespace ); return $rs->remoteSearchLine( $parser, $server, $word, $ns, $page ); } $curTitle = $parser->getTitle(); $curNs = $curTitle->getNamespace(); # minimum length is 3. if( strlen( $page ) == 0 && mb_strlen( $word ) < 3) return ''; # escape character caused SQL injection. $word = mysql_real_escape_string( $word ); if( $word == FALSE ) return ''; $lTitle = mysql_real_escape_string( str_replace( " ", "_", $curTitle->getBaseText() ) ); if( $lTitle == FALSE ) return ''; # if( strncmp( $page, '', 4 ) != 0 ){ if( strlen( $page ) > 0 ){ $page = mysql_real_escape_string( str_replace( " ", "_", $page ) ); if( $page == FALSE ) return ''; } # support simple regex. $sqlWord = $word; if( ereg( '^\^.*$', $sqlWord ) ) $sqlWord = substr( $sqlWord, 1 ); if( ereg( '^.*\$$', $sqlWord ) ) $sqlWord = substr( $sqlWord, 0, mb_strlen( $sqlWord )-1 ); # search namespace. $ns = array_keys( $wgCanonicalNamespaceNames, $namespace ); if( count( $ns ) == 0 && isset( $wgExtraNamespaces ) ){ $ns = array_keys( $wgExtraNamespaces, $namespace ); } if( count( $ns ) == 0 ) $ns[0] = 0; # specified page $option = ''; if( strlen( $page ) > 0 )//&& strncmp( $lTitle, $page, 1024 ) != 0 ) // $option = ' and page_title = \'' . $page . '\''; $option = ' and page_title like \'' . $page . '\''; # read database. $dbr =& wfGetDB( DB_READ ); if( $curNs == $ns[0] ){ $res = $dbr->select( array( 'page', 'revision', 'text' ), 'page_title, old_text', 'page_latest = rev_id and rev_text_id = old_id and old_text like \'%' . $sqlWord . '%\' and page_title != \'' . $lTitle . '\' and page_namespace = ' . $ns[0] . $option, '', '' ); } else { $res = $dbr->select( array( 'page', 'revision', 'text' ), 'page_title, old_text', 'page_latest = rev_id and rev_text_id = old_id and old_text like \'%' . $sqlWord . '%\' and page_namespace = ' . $ns[0] . $option, '', '' ); } $num = $dbr->numRows( $res ); $result = ''; # $word = preg_replace( '/[^\\\\]\%/', ".*", $word ); # $word = preg_replace( '/[^\\\\]\_/', ".", $word ); # $word = preg_quote( $word ); $word = preg_replace( '/\+/', "\\+", $word ); $word = preg_replace( '/([^\\\\])\%/', "$1.*", $word ); $word = preg_replace( '/([^\\\\])_/', "$1.", $word ); $word = preg_replace( '/([^\\\\])\%/', "$1.*", $word ); $word = preg_replace( '/([^\\\\])_/', "$1.", $word ); if( $num > 0 ){ while ( $row = $dbr->fetchObject( $res ) ) { $buf = $row->old_text; $lines = split( "\n", $buf ); $size = count( $lines ); for( $i = 0; $i < $size; $i ++ ){ // Search line including '$word'. if( !ereg( $word, $lines[$i] ) ) # $match = strpos( $lines[$i], $word ); # if( $match === false ) continue; // Is there myself. (Save infinity recursion) $checkLine = strtolower( $lines[$i] ); $own1 = strpos( $checkLine, '{{#searchline:' ); $own2 = strpos( $checkLine, '{{#countline:' ); if( $own1 === false && $own2 === false ){ $result .= '&&' . $row->page_title . $lines[$i] . "\n"; } } } } else { $result = ''; } $dbr->freeResult( $res ); return $result; } /** * Emulate Lisp 'car' * e.g. {{#car:A;B;C;D;E|;}} => A * * @param $parser Parser Parent parser * @param $str string Target string * @param $sep string Separator. Default is ' '(space) * @return string String which before first separator. */ function car( &$parser, $str, $sep = ' ' ) { $index = strpos( $str, $sep ); if( $index === false ) # return '';; return $str; return substr( $str, 0, $index); } /** * Emulate Lisp 'cdr' * e.g. {{#car:A;B;C;D;E|;}} => B;C;D;E * * @param $parser Parser Parent parser * @param $str string Target string * @param $sep string Separator. Default is ' '(space) * @return string String which after first separator. */ function cdr( &$parser, $str, $sep = ' ' ) { $index = strpos( $str, $sep ); if( $index === false ) return ''; return substr( $str, $index+mb_strlen( $sep ) ); } /** * Emulate Lisp 'cadr' * e.g. {{#car:A;B;C;D;E|;}} => B * * @param $parser Parser Parent parser * @param $str string Target string * @param $sep string Separator. Default is ' '(space) * @return string car after cdr */ function cadr( &$parser, $str, $sep = ' ' ) { return $this->car( $parser, $this->cdr( $parser, $str, $sep ), $sep ); } /** * Emulate Lisp 'cddr' * e.g. {{#car:A;B;C;D;E|;}} => C;D;E * * @param $parser Parser Parent parser * @param $str string Target string * @param $str string Separator. Default is ' '(space) * @return string String cdr after cdr */ function cddr( &$parser, $str, $sep = ' ' ) { return $this->cdr( $parser, $this->cdr( $parser, $str, $sep ), $sep ); } /** * Emulate Lisp 'caadr' * e.g. {{#car:A;B;C;D;E|;}} => C * * @param $parser Parser Parent parser * @param $str string Target string * @param $sep string Separator. Default is ' '(space) * @return string car after cdr after cdr */ function caddr( &$parser, $str, $sep = ' ' ) { return $this->car( $parser, $this->cdr( $parser, $this->cdr( $parser, $str, $sep ), $sep ), $sep ); } /** * Emulate Lisp 'cdddr' * e.g. {{#car:A;B;C;D;E|;}} => D;E * * @param $parser Parser Parent parser * @param $str string Target string * @param $sep string Separator. Default is ' '(space) * @return string String cdr after cdr after cdr */ function cdddr( &$parser, $str, $sep = ' ' ) { return $this->cdr( $parser, $this->cdr( $parser, $this->cdr( $parser, $str, $sep ), $sep ), $sep ); } /** * php trim. * e.g. {{#trim:abc123\n}} => abc123 * * @param $parser Parser Parent parser * @param $str string Target string * @return string Trimmed string */ function trimHook( &$parser, $str ) { return trim( $str ); } /** * delete white space. * e.g. {{#trimex:ab c1\t23\n}} => abc123 * * @param $parser Parser Parent parser * @param $str string Target string * @return string Trimmed string */ function trimExHook( &$parser, $str ) { return ereg_replace( "[ \t\n]", "", $str ); } /** * forced
. * e.g. {{#forcedbr:1234567890|5}} => 1234567890 * * @param $parser Parser Parent parser * @param $str string data * @param $size int separate size * @return inclue string */ function forcedbr( &$parser, $str, $size = 25 ) { $length = mb_strlen( $str ); $pos = 0; $new_str = ""; do { if( $pos+$size >= $length ){ $new_str .= mb_substr( $str, $pos, $length - $pos); } else { $new_str .= mb_substr( $str, $pos, $size ) . ''; } $pos += $size; } while( $pos < $length ); if( method_exists( $parser, 'preprocessToDom' ) ){ # mw 1.12 or later return array( $parser->preprocessToDom( $new_str ), 'isChildObj' => true ); } # mw 1.11 or under return $new_str; } /** * define variable * e.g. {{#def:i|1}} => i = 1; * * @param $parser Parser Parent parser * @param $name string variable name * @param $var string data */ function def( &$parser, $name, $var = '' ) { global $egUserDefineVariables; # if( strncmp( $name, '', 4 ) == 0 ) if( strlen( $name ) == 0 ) return ''; $egUserDefineVariables[$name] = $var; } /** * get variable * e.g. {{#get:i}} => 1 * * @param $parser Parser Parent parser * @param $name string variable name * @return string data */ function getVar( &$parser, $name ) { global $egUserDefineVariables; # if( strncmp( $name, '', 4 ) == 0 ) if( strlen( $name ) == 0 ) return ''; if( isset( $egUserDefineVariables[$name] ) ) return $egUserDefineVariables[$name]; return ""; } /** * and operation to string list * e.g. {{#and:1 * 2 * 4|1 * 3 * 4}} => 1 4 * * @param $parser Parser Parent parser * @param $list1 string first list * @param $list2 string second list * @return string list which and operated */ function andString( &$parser, $list1 = '', $list2 = '' ) { if( strlen( $list1 ) == 0 || strlen( $list2 ) == 0 ) return ''; $list = split( "\n", $list1 ); $counter = ""; for( $i = 0; $i < count( $list ); $i ++) $counter[$list[$i]] = 1; $list = split( "\n", $list2 ); $result = ""; for( $i = 0; $i < count( $list ); $i ++){ if( isset( $counter[$list[$i]] ) && $counter[$list[$i]] == 1 ) $result .= $list[$i] . "\n"; } return $result; } /** * or operation to string list * e.g. {{#or:1 * 2 * 4|1 * 3 * 4}} => 1 2 3 4 * * @param $parser Parser Parent parser * @param $list1 string first list * @param $list2 string second list * @return string list which or operated */ function orString( &$parser, $list1 = '', $list2 = '' ) { if( strlen( $list1 ) == 0 && strlen( $list2 ) == 0 ) return ''; if( strlen( $list1 ) == 0 ) return $list2; if( strlen( $list2 ) == 0 ) return $list1; $list1 = split( "\n", $list1 ); $list2 = split( "\n", $list2 ); $max1 = count( $list1 ); $max2 = count( $list2 ); $l1 = 0; $l2 = 0; $result = ""; while( $max1 > $l1 or $max2 > $l2 ){ $cmp = strncmp( $list1[$l1], $list2[$l2], 1024 ); if( $cmp == 0 ){ $result .= $list1[$l1] . "\n"; $l1 ++; $l2 ++; } else if( $cmp < 0 ){ $result .= $list1[$l1] . "\n"; $l1 ++; } else if( $cmp > 0 ){ $result .= $list2[$l2] . "\n"; $l2 ++; } } return $result; } /** * Search $word from all page. obsolete. * e.g. {{#searchtitle:FL_|0}} => * 'FL1A19NF0001' * 'FL2AF3NF0001' * ... * * @param $parser Parser Parent parser * @param $word string Search word * @param $namespace int Target namespace. Default is 0(Main) * @return string All titles including $word.(But excluding myself) */ function searchTitle2( &$parser, $word, $namespace = 'Main' ) { global $wgCanonicalNamespaceNames, $wgExtraNamespaces; $curTitle = $parser->getTitle(); $curNs = $curTitle->getNamespace(); # minimum length is 2. if( mb_strlen( $word ) < 2) return ''; # escape character caused SQL injection. $word = mysql_real_escape_string( $word ); if( $word == FALSE ) return ''; $lTitle = mysql_real_escape_string( str_replace( " ", "_", $curTitle->getBaseText() ) ); if( $lTitle == FALSE ) return ''; # support simple regex. $sqlWord = $word; if( ereg( '^\^.*$', $sqlWord ) ) $sqlWord = substr( $sqlWord, 1 ); else $sqlWord = '%' . $sqlWord; if( ereg( '^.*\$$', $sqlWord ) ) $sqlWord = substr( $sqlWord, 0, mb_strlen( $sqlWord )-1 ); else $sqlWord = $sqlWord . '%'; # search namespace. $ns = array_keys( $wgCanonicalNamespaceNames, $namespace ); if( count( $ns ) == 0 && isset( $wgExtraNamespaces ) ){ $ns = array_keys( $wgExtraNamespaces, $namespace ); } if( count( $ns ) == 0 ) $ns[0] = 0; # read database. $dbr =& wfGetDB( DB_READ ); if( $curNs == $ns[0] ){ $res = $dbr->select( array( 'page' ), 'page_title', 'page_title like \'' . $sqlWord . '\' and page_title != \'' . $lTitle . '\' and page_namespace = ' . $ns[0], '', '' ); } else { $res = $dbr->select( array( 'page' ), 'page_title', 'page_title like \'' . $sqlWord . '\' and page_namespace = ' . $ns[0], '', '' ); } $num = $dbr->numRows( $res ); $result = ''; if( $num > 0 ){ while ( $row = $dbr->fetchObject( $res ) ) { $buf = $row->page_title; // Is there myself. (Save infinity recursion) $own = strpos( $buf, '{{#SearchTitle:' ); if( $own === false ) $result .= $buf . "\n"; } } else { $result = ''; } $dbr->freeResult( $res ); return $result; } /** * Search $word from all page. You can use regular expression. Obsolete searchTitle2. * e.g. {{#searchtitle:FL_|0}} => * 'FL1A19NF0001' * 'FL2AF3NF0001' * ... * * @param $parser Parser Parent parser * @param $word string Search word * @param $namespace int Target namespace. Default is 0(Main) * @return string All titles including $word.(But excluding myself) */ function searchTitle( &$parser, $word, $namespace = 'Main' ) { global $wgCanonicalNamespaceNames, $wgExtraNamespaces; if( defined( 'REMOTE_SEARCH' ) && ereg( ':', $namespace ) ){ $rs = new RemoteSearch(); list( $server, $ns ) = split( ':', $namespace ); return $rs->remoteSearchTitle( $parser, $server, $word, $ns ); } $curTitle = $parser->getTitle(); $curNs = $curTitle->getNamespace(); # minimum length is 2. if( mb_strlen( $word ) < 2) return ''; # escape character caused SQL injection. $word = str_replace( '<', '[', $word ); $word = str_replace( '>', ']', $word ); $word = mysql_real_escape_string( str_replace( '[]', '', $word ) ); if( $word == FALSE ) return ''; $lTitle = mysql_real_escape_string( str_replace( " ", "_", $curTitle->getBaseText() ) ); if( $lTitle == FALSE ) return ''; # support simple regex. $sqlWord = str_replace( ' ', '_', $word ); $sqlWord = str_replace( '~', '|', $sqlWord ); /* if( ereg( '^\^.*$', $sqlWord ) ) $sqlWord = substr( $sqlWord, 1 ); else $sqlWord = '%' . $sqlWord; if( ereg( '^.*\$$', $sqlWord ) ) $sqlWord = substr( $sqlWord, 0, mb_strlen( $sqlWord )-1 ); else $sqlWord = $sqlWord . '%'; */ # search namespace. $ns = array_keys( $wgCanonicalNamespaceNames, $namespace ); if( count( $ns ) == 0 && isset( $wgExtraNamespaces ) ){ $ns = array_keys( $wgExtraNamespaces, $namespace ); } if( count( $ns ) == 0 ) $ns[0] = 0; # read database. $dbr =& wfGetDB( DB_READ ); if( $curNs == $ns[0] ){ $res = $dbr->select( array( 'page' ), 'page_title', 'page_title regexp \'' . $sqlWord . '\' and page_title != \'' . $lTitle . '\' and page_namespace = ' . $ns[0], '', '' ); } else { $res = $dbr->select( array( 'page' ), 'page_title', 'page_title regexp \'' . $sqlWord . '\' and page_namespace = ' . $ns[0], '', '' ); } $num = $dbr->numRows( $res ); $result = ''; if( $num > 0 ){ while ( $row = $dbr->fetchObject( $res ) ) { $buf = $row->page_title; // Is there myself. (Avoid infinity recursion) $own = strpos( $buf, '{{#SearchTitle:' ); if( $own === false ) $result .= $buf . "\n"; } } else { $result = ''; } $dbr->freeResult( $res ); return $result; } /** * Call specified template, until finishing consuming argument * e.g. {{#numrepeat:template|3|a,b,c,d,e,f,g,h,i|,}} => {{template|1=a|2=b|3=c}} {{template|1=d,2=e,3=f}} {{template|1=g|2=h|3=i}} * * @param $parser Parser Parent parser * @param $template string Called template * @param $args int Use argument number which consumed a call * @param $argv string argument which splited $sep * @param $sep string separator of $argv * @return string wiki template string parsed by mediawiki */ function numberingRepeat( &$parser, $template, $args, $argv, $sep = "\n") { # replace ' ' to ' ' if(strncmp($sep, ' ',7) == 0) $sep = ' '; # replace '\n' to "\n" if(strncmp($sep, '\n',4) == 0) $sep = "\n"; # check $args, $args max 2000 if($args <= 0) return ""; if($args > 2000) $args = 2000; if( strlen( $argv ) == 0 ){ return ""; } $arg = split($sep, $argv); $size = count($arg); $str = ""; for($i = 0; $i < $size; $i += $args) { $str .= "{{" . $template; for($j = 0; $j < $args && $i+$j < $size; $j ++){ $str .= "|" . ($j+1) . "=" . $arg[$i+$j]; } $str .= "}}"; } if( method_exists( $parser, 'preprocessToDom' ) ){ # mw 1.12 or later return array( $parser->preprocessToDom( $str ), 'isChildObj' => true ); } # mw 1.11 or under return $str; } /** * Search $word from all page * e.g. {{#countline:search|0}} => 3 * * @param $parser Parser Parent parser * @param $word string Search word * @param $namespace int Target namespace. Default is 0(Main) * @param $page string Target page. Option. * @return int Count lines including $word.(But excluding myself) */ function countLine( &$parser, $word, $namespace = 'Main', $page = '' ) { $str = $this->searchLine( $parser, $word, $namespace, $page ); return $this->countHook( $parser, $str ); } /** * Count $word from all page * e.g. {{#counttitle:FL_|0}} => 53 * * @param $parser Parser Parent parser * @param $word string Search word * @param $namespace int Target namespace. Default is 0(Main) * @return int Count titles including $word.(But excluding myself) */ function countTitle( &$parser, $word, $namespace = 'Main' ) { $str = $this->searchTitle( $parser, $word, $namespace ); return $this->countHook( $parser, $str ); } /** * extract line contains $pattern from $str * e.g. {{#choose:abc * def * agh|a}} -> abc * agh * * @param $parser Parser Parent parser * @param $str string Target string * @param $pattern string Search pattern * @return int Count titles including $word.(But excluding myself) */ function choose( &$parser, $str, $pattern = '') { if( strlen( $pattern ) == 0) return $str; $lines = split( "\n", $str ); $output = ''; for($i = 0; $i < count( $lines ) ; $i ++){ if( mb_strpos( $lines[$i], $pattern ) !== FALSE ) $output .= $lines[$i] . "\n"; } return $output; } /** * Search page not contains $word * e.g. {{#searchlinenot:search|0}} => * &&page1&&page2&&... * * @param $parser Parser Parent parser * @param $word string Search word * @param $namespace int Target namespace. Default is 0(Main) * @param $page string Target page. Option. * @return string All lines including $word.(But excluding myself) */ function searchLineNot( &$parser, $word, $namespace = 'Main', $page = '' ) { global $wgCanonicalNamespaceNames, $wgExtraNamespaces; $curTitle = $parser->getTitle(); $curNs = $curTitle->getNamespace(); # minimum length is 3. if( strlen( $page ) == 0 && mb_strlen( $word ) < 3) return ''; # escape character caused SQL injection. $word = mysql_real_escape_string( $word ); if( $word == FALSE ) return ''; $lTitle = mysql_real_escape_string( str_replace( " ", "_", $curTitle->getBaseText() ) ); if( $lTitle == FALSE ) return ''; if( strlen( $page ) > 0 ){ $page = mysql_real_escape_string( str_replace( " ", "_", $page ) ); if( $page == FALSE ) return ''; } # support simple regex. $sqlWord = $word; if( ereg( '^\^.*$', $sqlWord ) ) $sqlWord = substr( $sqlWord, 1 ); if( ereg( '^.*\$$', $sqlWord ) ) $sqlWord = substr( $sqlWord, 0, mb_strlen( $sqlWord )-1 ); # search namespace. $ns = array_keys( $wgCanonicalNamespaceNames, $namespace ); if( count( $ns ) == 0 && isset( $wgExtraNamespaces ) ){ $ns = array_keys( $wgExtraNamespaces, $namespace ); } if( count( $ns ) == 0 ) $ns[0] = 0; # specified page $option = ''; if( strlen( $page ) > 0 ) $option = ' and page_title like \'' . $page . '\''; # read database. $dbr =& wfGetDB( DB_READ ); if( $curNs == $ns[0] ){ $res = $dbr->select( array( 'page', 'revision', 'text' ), 'page_title', 'page_latest = rev_id and rev_text_id = old_id and old_text not like \'%' . $sqlWord . '%\' and page_title != \'' . $lTitle . '\' and page_namespace = ' . $ns[0] . $option, '', '' ); } else { $res = $dbr->select( array( 'page', 'revision', 'text' ), 'page_title', 'page_latest = rev_id and rev_text_id = old_id and old_text not like \'%' . $sqlWord . '%\' and page_namespace = ' . $ns[0] . $option, '', '' ); } $num = $dbr->numRows( $res ); $result = ''; $word = preg_replace( '/([^\\\\])\%/', "$1.*", $word ); $word = preg_replace( '/([^\\\\])_/', "$1.", $word ); $word = preg_replace( '/([^\\\\])\%/', "$1.*", $word ); $word = preg_replace( '/([^\\\\])_/', "$1.", $word ); if( $num > 0 ){ while ( $row = $dbr->fetchObject( $res ) ) $result .= '&&' . $row->page_title . "\n"; } else { $result = ''; } $dbr->freeResult( $res ); return $result; } /** * Do $page exists? * e.g. {{#ifexists:Main_Page|exists|do not exists}} => 'exists' * e.g. {{#ifexists:Dont_Exists|exists|do not exists}} => 'do not exists' * * @param $parser Parser Parent parser * @param $page page name * @param $then then return string, if $page exists. * @param $else else return string, if $page do not exists. * @return if $page exists, return $then, else return $else */ function ifExists( &$parser, $page, $then = '', $else = '' ) { $targetTitle = Title::newFromText( $page ); if( $targetTitle == null ) return $else; $ns = $targetTitle->getNamespace(); $page = $targetTitle->getText(); $dbr =& wfGetDB( DB_READ ); $res = $dbr->select( array( 'page' ), 'page_title', 'page_title = \'' . $page . '\' and page_namespace = ' . $ns, '', '' ); $num = $dbr->numRows( $res ); $dbr->freeResult( $res ); if($num > 0) return $then; return $else; } /** * get category links which separated '\n' * e.g. {{#clink:category}} => 'page_A * page_B * page_C * ... * * @param $parser Parser Parent parser * @param $page category page name * @return if $page exists, return category links. */ function clink( &$parser, $page ) { $page = mysql_real_escape_string( $page ); if( $page == FALSE ) return ''; $dbr =& wfGetDB( DB_READ ); $res = $dbr->select( array( 'categorylinks' ), 'cl_sortkey', 'cl_to = \'' . $page . '\'', '', '' ); $num = $dbr->numRows( $res ); $result = ''; if( $num > 0 ) { while ( $row = $dbr->fetchObject( $res ) ) $result .= $row->cl_sortkey . "\n"; } $dbr->freeResult( $res ); return $result; } /** * Call specified template, until finishing consuming argument. Difference to #repeat is that template's arguments are separated by '|'(Bar). * e.g. {{#map:template|3|a|b|c|d|e|f|g|h|i}} => {{template|a|b|c}} {{template|d|e|f}} {{template|g|h|i}} * * @param $parser Parser Parent parser * @param $template string Called template * @param $args int Use argument number which consumed a call * @param $argv... string arguments * @return string wiki template string parsed by mediawiki */ function map( ) { $argv = func_get_args(); if( count( $argv ) <= 3 ) return ""; $parser = $argv[0]; $template = $argv[1]; $args = $argv[2]; if( $args <= 0 ) return ""; if( $args > 2000 ) $args = 2000; $str = ""; for($i = 3; $i < count($argv); $i += $args ) { $str .= "{{" . $template; for($j = 0; $j < $args && $i+$j < count($argv); $j ++ ){ $str .= "|" . $argv[$i+$j]; } $str .= "}}"; } if( method_exists( $parser, 'preprocessToDom' ) ){ # mw 1.12 or later return array( $parser->preprocessToDom( $str ), 'isChildObj' => true ); } return $str; } /** * Search $word from all page. You can use regular expression. * e.g. {{#searchline:search|0}} => * 'you can search ...' * 'search is not ...' * ... * * @param $parser Parser Parent parser * @param $word string Search word * @param $namespace int Target namespace. Default is 0(Main) * @param $page string Target page. Option. * @return string All lines including $word.(But excluding myself) */ function searchLineReg( &$parser, $word, $namespace = 'Main', $page = '' ) { global $wgCanonicalNamespaceNames, $wgExtraNamespaces; $curTitle = $parser->getTitle(); $curNs = $curTitle->getNamespace(); # minimum length is 3. if( strlen( $page ) == 0 && mb_strlen( $word ) < 3) return ''; # escape character caused SQL injection. $sqlWord = mysql_real_escape_string( $word ); if( $sqlWord == FALSE ) return ''; $lTitle = mysql_real_escape_string( str_replace( " ", "_", $curTitle->getBaseText() ) ); if( $lTitle == FALSE ) return ''; # if( strncmp( $page, '', 4 ) != 0 ){ if( strlen( $page ) > 0 ){ $page = mysql_real_escape_string( str_replace( " ", "_", $page ) ); if( $page == FALSE ) return ''; } if( ereg( '^\^.*$', $sqlWord ) ) $sqlWord = substr( $sqlWord, 1 ); if( ereg( '^.*\$$', $sqlWord ) ) $sqlWord = substr( $sqlWord, 0, mb_strlen( $sqlWord )-1 ); # search namespace. $ns = array_keys( $wgCanonicalNamespaceNames, $namespace ); if( count( $ns ) == 0 && isset( $wgExtraNamespaces ) ){ $ns = array_keys( $wgExtraNamespaces, $namespace ); } if( count( $ns ) == 0 ) $ns[0] = 0; # specified page $option = ''; if( strlen( $page ) > 0 )//&& strncmp( $lTitle, $page, 1024 ) != 0 ) // $option = ' and page_title = \'' . $page . '\''; $option = ' and page_title like \'' . $page . '\''; # read database. $dbr =& wfGetDB( DB_READ ); if( $curNs == $ns[0] ){ $res = $dbr->select( array( 'page', 'revision', 'text' ), 'page_title, old_text', 'page_latest = rev_id and rev_text_id = old_id and old_text regexp \'' . $sqlWord . '\' and page_title != \'' . $lTitle . '\' and page_namespace = ' . $ns[0] . $option, '', '' ); } else { $res = $dbr->select( array( 'page', 'revision', 'text' ), 'page_title, old_text', 'page_latest = rev_id and rev_text_id = old_id and old_text regexp \'' . $sqlWord . '\' and page_namespace = ' . $ns[0] . $option, '', '' ); } $num = $dbr->numRows( $res ); $result = "";//$num"; if( $num > 0 ){ while ( $row = $dbr->fetchObject( $res ) ) { $buf = $row->old_text; $lines = split( "\n", $buf ); $size = count( $lines ); for( $i = 0; $i < $size; $i ++ ){ // Search line including '$word'. if( !ereg( $word, $lines[$i] ) ) # $match = strpos( $lines[$i], $word ); # if( $match === false ) continue; // Is there myself. (Save infinity recursion) $checkLine = strtolower( $lines[$i] ); $own1 = strpos( $checkLine, '{{#searchline:' ); $own2 = strpos( $checkLine, '{{#countline:' ); if( $own1 === false && $own2 === false ){ $result .= '&&' . $row->page_title . $lines[$i] . "\n"; } } } } else { $result = "$sqlWord"; } $dbr->freeResult( $res ); return $result; } /** * get N'th string * e.g. {{#nth:abc def ghi 123|4}} => ghi * {{#nth:123,456,789|2|,}} => 456 * * @param $parser Parser Parent parser * @param $str target string separated $sep * @param $index number * @param $sep separator in $str. default is " "(space) * @return $index'th string in splited $str */ function nth( &$parser, $str, $index, $sep = " " ) { $words = split( $sep, $str ); $index = $index - 1; if( count( $words ) <= $index || $index < 0 ) return ""; return $words[$index]; } /** * create repeated string * e.g. {{#createString:a|4}} => aaaa * * @param $parser Parser Parent parser * @param $char repeat character * @param $length repeat count * @return repeated string */ function createString( &$parser, $char, $length ) { if( $length < 0 || $length > 100 ) return ""; $str = ""; for( $i = 0; $i < $length; $i ++ ) $str .= $char; return $str; } /** * get max number * e.g. {{#max:1|2|3}} => 3 * * @param $parser Parser Parent parser * @param $n1, $n2, $n3 ... number data * @return repeated string */ function getMax( ) { $argv = func_get_args(); if( count( $argv ) <= 1 ) return ""; array_shift( $argv ); for( $i = 0; $i < count( $argv ); $i ++ ){ if( !preg_match( "/^[0-9]+$/", $argv[$i] ) ) return -1; } return max( $argv ); } /** * get min number * e.g. {{#min:1|2|3}} => 1 * * @param $parser Parser Parent parser * @param $n1, $n2, $n3 ... number data * @return repeated string */ function getMin( ) { $argv = func_get_args(); if( count( $argv ) <= 1 ) return ""; array_shift( $argv ); for( $i = 0; $i < count( $argv ); $i ++ ){ if( !preg_match( "/^[0-9]+$/", $argv[$i] ) ) return -1; } return min( $argv ); } /** * Replace multibyte string. You can use ' ' as ' '(space) * e.g. {{#replace|abcdefghi|def|123}} => abc123ghi * * @param $parser Parser Parent parser * @param $string multibyte string Target string * @param $pattern multibyte string Replace target * @param $replacement multibyte string Replace string * @return string Return $string which replace $pattern to $replacement */ /* function mbreplace( &$parser, $string, $pattern, $replacement ) { $pattern = ereg_replace( ' ', ' ', $pattern ); $replacement = ereg_replace( ' ', ' ', $replacement ); $pattern = ereg_replace( '|', '\|', $pattern ); $replacement = ereg_replace( '|', '|', $replacement ); $pattern = ereg_replace( ' ', "\n", $pattern ); $replacement = ereg_replace( ' ', "\n", $replacement ); mb_regex_encoding("UTF-8"); return mb_ereg_replace( $pattern, $replacement, $string ); }*/ } function efSetupExFunctions() { global $wgParser; $exFunctions = new ExFunctions; $wgParser->setFunctionHook( 'substring', array( &$exFunctions, 'substring' ) ); $wgParser->setFunctionHook( 'length', array( &$exFunctions, 'length' ) ); $wgParser->setFunctionHook( 'indexOf', array( &$exFunctions, 'indexOf' ) ); $wgParser->setFunctionHook( 'lastindexof', array( &$exFunctions, 'lastIndexOf' ) ); $wgParser->setFunctionHook( 'isdigit', array( &$exFunctions, 'isdigit' ) ); $wgParser->setFunctionHook( 'isalnum', array( &$exFunctions, 'isalnum' ) ); $wgParser->setFunctionHook( 'repeat', array( &$exFunctions, 'repeat' ) ); $wgParser->setFunctionHook( 'cr', array( &$exFunctions, 'cr' ) ); $wgParser->setFunctionHook( 'bar', array( &$exFunctions, 'bar' ) ); $wgParser->setFunctionHook( 'count', array( &$exFunctions, 'countHook' ) ); $wgParser->setFunctionHook( 'ifexistfile', array( &$exFunctions, 'ifexistfile' ) ); $wgParser->setFunctionHook( 'replace', array( &$exFunctions, 'replace' ) ); $wgParser->setFunctionHook( 'javawithparam', array( &$exFunctions, 'javaWithParam' ) ); $wgParser->setFunctionHook( 'searchline', array( &$exFunctions, 'searchLine' ) ); $wgParser->setFunctionHook( 'car', array( &$exFunctions, 'car' ) ); $wgParser->setFunctionHook( 'cdr', array( &$exFunctions, 'cdr' ) ); $wgParser->setFunctionHook( 'cadr', array( &$exFunctions, 'cadr' ) ); $wgParser->setFunctionHook( 'cddr', array( &$exFunctions, 'cddr' ) ); $wgParser->setFunctionHook( 'caddr', array( &$exFunctions, 'caddr' ) ); $wgParser->setFunctionHook( 'cdddr', array( &$exFunctions, 'cdddr' ) ); $wgParser->setFunctionHook( 'trim', array( &$exFunctions, 'trimHook' ) ); $wgParser->setFunctionHook( 'trimex', array( &$exFunctions, 'trimExHook' ) ); $wgParser->setFunctionHook( 'forcedbr', array( &$exFunctions, 'forcedbr' ) ); $wgParser->setFunctionHook( 'def', array( &$exFunctions, 'def' ) ); $wgParser->setFunctionHook( 'var', array( &$exFunctions, 'getVar' ) ); $wgParser->setFunctionHook( 'and', array( &$exFunctions, 'andString' ) ); $wgParser->setFunctionHook( 'or', array( &$exFunctions, 'orString' ) ); $wgParser->setFunctionHook( 'searchtitle', array( &$exFunctions, 'searchtitle' ) ); $wgParser->setFunctionHook( 'repeatnum', array( &$exFunctions, 'numberingRepeat' ) ); $wgParser->setFunctionHook( 'countline', array( &$exFunctions, 'countLine' ) ); $wgParser->setFunctionHook( 'counttitle', array( &$exFunctions, 'countTitle' ) ); $wgParser->setFunctionHook( 'choose', array( &$exFunctions, 'choose' ) ); $wgParser->setFunctionHook( 'searchlinenot', array( &$exFunctions, 'searchLineNot' ) ); $wgParser->setFunctionHook( 'ifexists', array( &$exFunctions, 'ifExists' ) ); $wgParser->setFunctionHook( 'clink', array( &$exFunctions, 'clink' ) ); $wgParser->setFunctionHook( 'map', array( &$exFunctions, 'map' ) ); $wgParser->setFunctionHook( 'searchLineReg', array( &$exFunctions, 'searchLineReg' ) ); $wgParser->setFunctionHook( 'nth', array( &$exFunctions, 'nth' ) ); $wgParser->setFunctionHook( 'createstring', array( &$exFunctions, 'createString' ) ); $wgParser->setFunctionHook( 'max', array( &$exFunctions, 'getMax' ) ); $wgParser->setFunctionHook( 'min', array( &$exFunctions, 'getMin' ) ); # $wgParser->setFunctionHook( 'mbreplace', array( &$exFunctions, 'mbreplace' ) ); } function efExFunctionsLanguageGetMagic( &$magicWords, $langCode ) { $magicWords['substring'] = array( 0, 'substring' ); $magicWords['length'] = array( 0, 'length' ); $magicWords['indexOf'] = array( 0, 'indexOf' ); $magicWords['lastindexof'] = array( 0, 'lastindexof' ); $magicWords['isdigit'] = array( 0, 'isdigit' ); $magicWords['isalnum'] = array( 0, 'isalnum' ); $magicWords['repeat'] = array( 0, 'repeat' ); $magicWords['cr'] = array( 0, 'cr' ); $magicWords['bar'] = array( 0, 'bar' ); $magicWords['count'] = array( 0, 'count' ); $magicWords['ifexistfile'] = array( 0, 'ifexistfile' ); $magicWords['replace'] = array( 0, 'replace' ); $magicWords['javawithparam']= array( 0, 'javawithparam' ); $magicWords['searchline'] = array( 0, 'searchline' ); $magicWords['car'] = array( 0, 'car' ); $magicWords['cdr'] = array( 0, 'cdr' ); $magicWords['cadr'] = array( 0, 'cadr' ); $magicWords['cddr'] = array( 0, 'cddr' ); $magicWords['caddr'] = array( 0, 'caddr' ); $magicWords['cdddr'] = array( 0, 'cdddr' ); $magicWords['trim'] = array( 0, 'trim' ); $magicWords['trimex'] = array( 0, 'trimex' ); $magicWords['forcedbr'] = array( 0, 'forcedbr' ); $magicWords['def'] = array( 0, 'def' ); $magicWords['var'] = array( 0, 'var' ); $magicWords['and'] = array( 0, 'and' ); $magicWords['or'] = array( 0, 'or' ); $magicWords['searchtitle'] = array( 0, 'searchtitle' ); $magicWords['repeatnum'] = array( 0, 'repeatnum' ); $magicWords['countline'] = array( 0, 'countline' ); $magicWords['counttitle'] = array( 0, 'counttitle' ); $magicWords['choose'] = array( 0, 'choose' ); $magicWords['searchlinenot']= array( 0, 'searchlinenot' ); $magicWords['ifexists'] = array( 0, 'ifexists' ); $magicWords['clink'] = array( 0, 'clink' ); $magicWords['map'] = array( 0, 'map' ); $magicWords['searchLineReg'] = array( 0, 'searchLineReg' ); $magicWords['nth'] = array( 0, 'nth' ); $magicWords['createstring'] = array( 0, 'createstring' ); $magicWords['max'] = array( 0, 'max' ); $magicWords['min'] = array( 0, 'min' ); # $magicWords['mbreplace'] = array( 0, 'mbreplace' ); return true; }