1<?php
2/**
3 @file       linkbonus/syntax/base.php
4 @brief      Base syntax component for Linkbonus plugin.
5 @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
6 @author     Luis Machuca Bezzaza <luis.machuca [at] gulix.cl>
7 @version    0.04
8**/
9
10if(!defined('DW_LF')) define('DW_LF',"\n");
11
12if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
13if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
14if(!defined('POWERLINKS_DIR')) define('POWERLINKS_DIR',DOKU_INC.'lib/plugins/powerlinks/');
15if(!defined('DOKU_FVDIR')) define('DOKU_FVDIR',POWERLINKS_DIR.'favicons/');
16
17require_once(DOKU_PLUGIN.'syntax.php');
18require_once(DOKU_INC. 'inc/init.php'); // for getBaseURL
19
20/**
21 * All DokuWiki plugins to extend the parser/rendering mechanism
22 * need to inherit from this class
23 */
24class syntax_plugin_powerlinks_interwiki extends DokuWiki_Syntax_Plugin {
25
26    var $helper = null;
27    var $interwiki = array();
28
29    private $_url_regex = '[a-zA-Z0-9\.]+>[^\|\]]+';
30    private $_features  = array ('fetchname','doa','title');
31
32    /**
33     * Constructor. Load helper plugin
34     */
35    function syntax_plugin_powerlinks_interwiki(){
36      $this->helper =& plugin_load('helper', 'powerlinks');
37      if(!$this->helper) msg('Can not load powerlinks helper -- check that plugin is correctly installed.',-1);
38      $this->interwiki = getInterwiki();
39      }
40
41    /**
42     * return some info
43     */
44    function getInfo() {
45      return $this->helper->syntax_getInfo();
46      }
47
48    function getType() {
49      return $this->helper->syntax_getType();
50      }
51
52    function getSort() {
53      return 200; // must be lower than external's.
54      }
55
56    function getAllowedTypes() {
57      return array();
58      }
59
60    function connectTo($mode) {
61      /**
62       * pattern information
63       * the pattern is @/path/to/page|name|title|param1=val1|param2=val2|...|
64       */
65      $REGEX     = '\[\['.$this->_url_regex. '\|(?!\{)[^\|\]]+\|' .'.*?(?<!\\\\)\]\]';
66      $this->Lexer->addSpecialPattern(
67        $REGEX,$mode,'plugin_powerlinks_interwiki');
68      }
69
70    /**
71     * Handle the match
72     */
73    function handle($match, $state, $pos, &$handler) {
74        /* separate the call into its components */
75        $match = substr ($match, 2, -2).'|'; // correct for preg_split ending with delimiter
76        $data  = preg_split('/(?<!\\\\)\|/', $match);
77        /* Go>uri  |  Text  | key="val" | ... */
78        $link= array();
79        $link['url']     = array_shift($data);
80
81        list ($iw_shortcut, $iw_uri) = explode ('>', $link['url'] );
82        reset ($data);
83        $iw_url= $this->_resolveInterWiki($iw_shortcut, $iw_uri);
84        /* lets check if the 'name' is a medialink, if so, we bail out
85         */
86        if (preg_match('/{{.+/', $data[0]) ) {
87          $data[0]= '**Image Link**';
88          }
89
90        // unescape the characters pipe (|) and square brackets ([ ])
91        foreach ($data as &$D) {
92          $D= str_replace ('\|', '|', $D);
93          $D= str_replace ('\[', '[', $D);
94          $D= str_replace ('\]', ']', $D);
95          }
96        reset ($data);
97
98
99        $link['name']    = array_shift($data);
100
101        /* if at this point $data is empty, we are dealing with a
102           "normal" dokuwiki link
103        */
104        if (empty($data) || $data[0] == array() ) {
105          $handler->_addCall(
106                    'interwikilink',
107                    array (
108                      $link['url'],
109                      $link['name'],
110                      strtolower( $iw_shortcut),
111                      $iw_text
112                      ),
113                    $pos);
114          return array();
115          }
116
117        /* otherwise, we are dealing with extended link,
118           let's check the rest of the parameters
119        */
120
121        $do        = array(); // list of operations to perform
122        $set       = array(); // {false} if paramenter has not been detected
123        // default link behaviour
124        $link['_type'] = 'interwiki';
125        $link['target']= $conf['target']['wiki'];
126        $link['title'] = htmlspecialchars($link['url']);
127        $class = preg_replace('/[^_\-a-z0-9]+/i','_',$iw_shortcut);
128        $link['class'] = "iw_$class";
129
130        foreach ($data as $D) {
131          list ($key, $val) = explode ('=', $D, 2);
132          if (empty($key) && !empty($val) ) {
133            $key=$val; $val= false;
134            }
135          else $val= substr($val, 1, -1); // remove quotes
136
137          if (!$set[$key] ) {
138            switch ($key) {
139            case 'target':
140              $link['target']= str_replace('_', '', $val); // remove eg.: "_" from "_blank"
141              break;
142
143            case 'title':
144              $link['title']= $val;
145              break;
146
147            case 'fetchname':
148              $link['title_in'] = $val ? $val : 'title';
149              $set['fetchname_method'] = ($this->helper->TitleAged($link['url']) ) ? 'recheck' : 'cache';
150              $docheck = true;
151              break;
152
153            case 'doa':
154              $docheck= true;
155              break;
156
157            default:
158              break; // does nothing
159
160              } // end switch
161            $set[$key] = true;
162            } // end if
163
164          } // end foreach
165
166        /* -----------------------------------------------------------
167           PostProcess some requirements
168         */
169        $link['url']= $iw_url;
170
171
172        /* if there is any need to fetch external page, do so */
173        $xcontents= '';
174        $xstatus= 0;
175
176        if ($docheck) $set['result_']= $this->helper->getExternalPage($link['url'], $xcontents, $xstatus);
177        else $set['result_']= 'cache';
178        $this->helper->composeLink ($link, $set, array($xcontents, $xstatus) );
179
180       /* -----------------------------------------------------
181          at this point we have all the information required to
182          ask the Renderer system to create the link */
183      $data= array(
184       'link'   => $link,
185       'match'  => $match,
186       'state'  => $state
187       );
188      return $data;
189      }
190
191    /**
192     * Create output
193     */
194    function render($mode, &$renderer, $data) {
195      return $this->helper->syntax_render
196             ($mode, $renderer, $data, 'interwiki');
197      }
198
199    /**
200     * @fn    _resolveInterWiki
201     * @brief imported from renderer due to being defined too late in the stage
202     */
203    private function _resolveInterWiki(&$shortcut,$reference){
204        //get interwiki URL
205        if ( isset($this->interwiki[$shortcut]) ) {
206            $url = $this->interwiki[$shortcut];
207        } else {
208            // Default to Google I'm feeling lucky
209            $url = 'http://www.google.com/search?q={URL}&amp;btnI=lucky';
210            $shortcut = 'go';
211        }
212
213        //split into hash and url part
214        list($reference,$hash) = explode('#',$reference,2);
215
216        //replace placeholder
217        if(preg_match('#\{(URL|NAME|SCHEME|HOST|PORT|PATH|QUERY)\}#',$url)){
218            //use placeholders
219            $url = str_replace('{URL}',rawurlencode($reference),$url);
220            $url = str_replace('{NAME}',$reference,$url);
221            $parsed = parse_url($reference);
222            if(!$parsed['port']) $parsed['port'] = 80;
223            $url = str_replace('{SCHEME}',$parsed['scheme'],$url);
224            $url = str_replace('{HOST}',$parsed['host'],$url);
225            $url = str_replace('{PORT}',$parsed['port'],$url);
226            $url = str_replace('{PATH}',$parsed['path'],$url);
227            $url = str_replace('{QUERY}',$parsed['query'],$url);
228        }else{
229            //default
230            $url = $url.rawurlencode($reference);
231        }
232        if($hash) $url .= '#'.rawurlencode($hash);
233
234        return $url;
235    }
236
237}
238
239