includes/wikiengine/Parse/Mediawiki/Wikilink.php
changeset 1 fe660c52c48f
child 35 efae425e9b98
equal deleted inserted replaced
0:902822492a68 1:fe660c52c48f
       
     1 <?php
       
     2 // vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4:
       
     3 /**
       
     4  * Mediawiki: Parses for links to (inter)wiki pages or images.
       
     5  *
       
     6  * Text_Wiki rule parser to find links, it groups the 3 rules:
       
     7  * # Wikilink: links to internal Wiki pages
       
     8  * # Interwiki: links to external Wiki pages (sister projects, interlangage)
       
     9  * # Image: Images
       
    10  * as defined by text surrounded by double brackets [[]]
       
    11  * Translated are the link itself, the section (anchor) and alternate text
       
    12  *
       
    13  * PHP versions 4 and 5
       
    14  *
       
    15  * @category   Text
       
    16  * @package    Text_Wiki
       
    17  * @author     Bertrand Gugger <bertrand@toggg.com>
       
    18  * @author     Paul M. Jones <pmjones@php.net>
       
    19  * @copyright  2005 bertrand Gugger
       
    20  * @license    http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
       
    21  * @version    CVS: $Id: Wikilink.php,v 1.7 2006/02/25 13:34:50 toggg Exp $
       
    22  * @link       http://pear.php.net/package/Text_Wiki
       
    23  */
       
    24 
       
    25 /**
       
    26  * Wikilink, Interwiki and Image rules parser class for Mediawiki.
       
    27  * This class implements a Text_Wiki_Parse to find links marked
       
    28  * in source by text surrounded by 2 opening/closing brackets as 
       
    29  * [[Wiki page name#Section|Alternate text]]
       
    30  * On parsing, the link is replaced with a token.
       
    31  *
       
    32  * @category   Text
       
    33  * @package    Text_Wiki
       
    34  * @author     Bertrand Gugger <bertrand@toggg.com>
       
    35  * @copyright  2005 bertrand Gugger
       
    36  * @license    http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
       
    37  * @version    Release: @package_version@
       
    38  * @link       http://pear.php.net/package/Text_Wiki
       
    39  * @see        Text_Wiki_Parse::Text_Wiki_Parse()
       
    40  */
       
    41 class Text_Wiki_Parse_Wikilink extends Text_Wiki_Parse {
       
    42 
       
    43     /**
       
    44      * Configuration for this rule (Wikilink)
       
    45      *
       
    46      * @access public
       
    47      * @var array
       
    48     */
       
    49     var $conf = array(
       
    50         'spaceUnderscore' => true,
       
    51         'project' => array('demo', 'd'),
       
    52         'url' => 'http://example.com/en/page=%s',
       
    53         'langage' => 'en'
       
    54     );
       
    55 
       
    56     /**
       
    57      * Configuration for the Image rule
       
    58      *
       
    59      * @access public
       
    60      * @var array
       
    61     */
       
    62     var $imageConf = array(
       
    63         'prefix' => array('Image', 'image')
       
    64     );
       
    65 
       
    66     /**
       
    67      * Configuration for the Interwiki rule
       
    68      *
       
    69      * @access public
       
    70      * @var array
       
    71     */
       
    72     var $interwikiConf = array(
       
    73         'sites' => array(
       
    74             'manual' => 'http://www.php.net/manual/en/%s',
       
    75             'pear'   => 'http://pear.php.net/package/%s',
       
    76             'bugs'   => 'http://pear.php.net/package/%s/bugs'
       
    77         ),
       
    78         'interlangage' => array('en', 'de', 'fr')
       
    79     );
       
    80 
       
    81     /**
       
    82      * The regular expression used to parse the source text and find
       
    83      * matches conforming to this rule.  Used by the parse() method.
       
    84      *
       
    85      * @access public
       
    86      * @var string
       
    87      * @see Text_Wiki_Parse::parse()
       
    88      */
       
    89     var $regex = '/(?<!\[)\[\[(?!\[)\s*(:?)((?:[^:]+:)+)?([^:]+)(?:#(.*))?\s*(?:\|(((?R))|.*))?]]/msU';
       
    90 
       
    91      /**
       
    92      * Constructor.
       
    93      * We override the constructor to get Image and Interwiki config
       
    94      *
       
    95      * @param object &$obj the base conversion handler
       
    96      * @return The parser object
       
    97      * @access public
       
    98      */
       
    99     function Text_Wiki_Parse_Wikilink(&$obj)
       
   100     {
       
   101         $default = $this->conf;
       
   102         parent::Text_Wiki_Parse($obj);
       
   103 
       
   104         // override config options for image if specified
       
   105         if (in_array('Image', $this->wiki->disable)) {
       
   106             $this->imageConf['prefix'] = array();
       
   107         } else {
       
   108             if (isset($this->wiki->parseConf['Image']) &&
       
   109                 is_array($this->wiki->parseConf['Image'])) {
       
   110                 $this->imageConf = array_merge(
       
   111                     $this->imageConf,
       
   112                     $this->wiki->parseConf['Image']
       
   113                 );
       
   114             }
       
   115         }
       
   116 
       
   117         // override config options for interwiki if specified
       
   118         if (in_array('Interwiki', $this->wiki->disable)) {
       
   119             $this->interwikiConf['sites'] = array();
       
   120             $this->interwikiConf['interlangage'] = array();
       
   121         } else {
       
   122             if (isset($this->wiki->parseConf['Interwiki']) &&
       
   123                 is_array($this->wiki->parseConf['Interwiki'])) {
       
   124                 $this->interwikiConf = array_merge(
       
   125                     $this->interwikiConf,
       
   126                     $this->wiki->parseConf['Interwiki']
       
   127                 );
       
   128             }
       
   129             if (empty($this->conf['langage'])) {
       
   130                 $this->interwikiConf['interlangage'] = array();
       
   131             }
       
   132         }
       
   133         // convert the list of recognized schemes to a regex OR,
       
   134 /*        $schemes = $this->getConf('schemes', $default['schemes']);
       
   135         $this->url = str_replace( '#delim#', $this->wiki->delim,
       
   136            '#(?:' . (is_array($schemes) ? implode('|', $schemes) : $schemes) . ')://'
       
   137            . $this->getConf('host_regexp', $default['host_regexp'])
       
   138            . $this->getConf('path_regexp', $default['path_regexp']) .'#'); */
       
   139     }
       
   140 
       
   141     /**
       
   142      * Generates a replacement for the matched text.  Token options are:
       
   143      * - 'page' => the name of the target wiki page
       
   144      * -'anchor' => the optional section in it
       
   145      * - 'text' => the optional alternate link text
       
   146      *
       
   147      * @access public
       
   148      * @param array &$matches The array of matches from parse().
       
   149      * @return string token to be used as replacement 
       
   150      */
       
   151     function process(&$matches)
       
   152     {
       
   153         // Starting colon ?
       
   154         $colon = !empty($matches[1]);
       
   155         $auto = $interlang = $interwiki = $image = $site = '';
       
   156         // Prefix ?
       
   157         if (!empty($matches[2])) {
       
   158             $prefix = explode(':', substr($matches[2], 0, -1));
       
   159             $count = count($prefix);
       
   160             $i = -1;
       
   161             // Autolink
       
   162             if (isset($this->conf['project']) &&
       
   163                     in_array(trim($prefix[0]), $this->conf['project'])) {
       
   164                 $auto = trim($prefix[0]);
       
   165                 unset($prefix[0]);
       
   166                 $i = 0;
       
   167             }
       
   168             while (++$i < $count) {
       
   169                 $prefix[$i] = trim($prefix[$i]);
       
   170                 // interlangage
       
   171                 if (!$interlang &&
       
   172                     in_array($prefix[$i], $this->interwikiConf['interlangage'])) {
       
   173                     $interlang = $prefix[$i];
       
   174                     unset($prefix[$i]);
       
   175                     continue;
       
   176                 }
       
   177                 // image
       
   178                 if (!$image && in_array($prefix[$i], $this->imageConf['prefix'])) {
       
   179                     $image = $prefix[$i];
       
   180                     unset($prefix[$i]);
       
   181                     break;
       
   182                 }
       
   183                 // interwiki
       
   184                 if (isset($this->interwikiConf['sites'][$prefix[$i]])) {
       
   185                     $interwiki = $this->interwikiConf['sites'][$prefix[$i]];
       
   186                     $site = $prefix[$i];
       
   187                     unset($prefix[$i]);
       
   188                 }
       
   189                 break;
       
   190             }
       
   191             if ($prefix) {
       
   192                 $matches[3] = implode(':', $prefix) . ':' . $matches[3];
       
   193             }
       
   194         }
       
   195         $text = empty($matches[5]) ? $matches[3] : $matches[5];
       
   196         $matches[3] = trim($matches[3]);
       
   197         $matches[4] = empty($matches[4]) ? '' : trim($matches[4]);
       
   198         if ($this->conf['spaceUnderscore']) {
       
   199             $matches[3] = preg_replace('/\s+/', '_', $matches[3]);
       
   200             $matches[4] = preg_replace('/\s+/', '_', $matches[4]);
       
   201         }
       
   202         if ($image) {
       
   203             return $this->image($matches[3] . (empty($matches[4]) ? '' : '#' . $matches[4]),
       
   204                                 $text, $interlang, $colon);
       
   205         }
       
   206         if (!$interwiki && $interlang && isset($this->conf['url'])) {
       
   207             if ($interlang == $this->conf['langage']) {
       
   208                 $interlang = '';
       
   209             } else {
       
   210                 $interwiki = $this->conf['url'];
       
   211                 $site = isset($this->conf['project']) ? $this->conf['project'][0] : '';
       
   212             }
       
   213         }
       
   214         if ($interwiki) {
       
   215             return $this->interwiki($site, $interwiki,
       
   216                 $matches[3] . (empty($matches[4]) ? '' : '#' . $matches[4]),
       
   217                 $text, $interlang, $colon);
       
   218         }
       
   219         if ($interlang) {
       
   220             $matches[3] = $interlang . ':' . $matches[3];
       
   221             $text = (empty($matches[5]) ? $interlang . ':' : '') . $text;
       
   222         }
       
   223         // set the options
       
   224         $options = array(
       
   225             'page'   => $matches[3],
       
   226             'anchor' => (empty($matches[4]) ? '' : $matches[4]),
       
   227             'text'   => $text
       
   228         );
       
   229 
       
   230         // create and return the replacement token
       
   231         return $this->wiki->addToken($this->rule, $options);
       
   232     }
       
   233 
       
   234     /**
       
   235      * Generates an image token.  Token options are:
       
   236      * - 'src' => the name of the image file
       
   237      * - 'attr' => an array of attributes for the image:
       
   238      * | - 'alt' => the optional alternate image text
       
   239      * | - 'align => 'left', 'center' or 'right'
       
   240      *
       
   241      * @access public
       
   242      * @param array &$matches The array of matches from parse().
       
   243      * @return string token to be used as replacement 
       
   244      */
       
   245     function image($name, $text, $interlang, $colon)
       
   246     {
       
   247         $attr = array('alt' => '');
       
   248         // scan text for supplementary attibutes
       
   249         if (strpos($text, '|') !== false) {
       
   250             $splits = explode('|', $text);
       
   251             $sep = '';
       
   252             foreach ($splits as $split) {
       
   253                 switch (strtolower($split)) {
       
   254                     case 'left': case 'center': case 'right':
       
   255                         $attr['align'] = strtolower($split);
       
   256                         break;
       
   257                     default:
       
   258                         $attr['alt'] .= $sep . $split;
       
   259                         $sep = '|';
       
   260                 }
       
   261             }
       
   262         } else {
       
   263             $attr['alt'] = $text;
       
   264         }
       
   265         $options = array(
       
   266             'src' => ($interlang ? $interlang . ':' : '') . $name,
       
   267             'attr' => $attr);
       
   268 
       
   269         // create and return the replacement token
       
   270         return $this->wiki->addToken('Image', $options);
       
   271     }
       
   272 
       
   273     /**
       
   274      * Generates an interwiki token.  Token options are:
       
   275      * - 'page' => the name of the target wiki page
       
   276      * - 'site' => the key for external site
       
   277      * - 'url'  => the full target url
       
   278      * - 'text' => the optional alternate link text
       
   279      *
       
   280      * @access public
       
   281      * @param array &$matches The array of matches from parse().
       
   282      * @return string token to be used as replacement 
       
   283      */
       
   284     function interwiki($site, $interwiki, $page, $text, $interlang, $colon)
       
   285     {
       
   286         if ($interlang) {
       
   287             $interwiki = preg_replace('/\b' . $this->conf['langage'] . '\b/i',
       
   288                             $interlang, $interwiki);
       
   289         }
       
   290         // set the options
       
   291         $options = array(
       
   292             'page' => $page,
       
   293             'site' => $site,
       
   294             'url'  => sprintf($interwiki, $page),
       
   295             'text' => $text
       
   296         );
       
   297 
       
   298         // create and return the replacement token
       
   299         return $this->wiki->addToken('Interwiki', $options);
       
   300     }
       
   301 }
       
   302 ?>