xref: /dokuwiki/inc/parser/handler.php (revision d8ab874693a369332dbbecf425e5e612fb1095a6)
10cecf9d5Sandi<?php
25c2aad12SAndreas Gohr
3cbb44eabSAndreas Gohruse dokuwiki\Extension\Event;
4e1d9dcc8SAndreas Gohruse dokuwiki\Extension\SyntaxPlugin;
5be906b56SAndreas Gohruse dokuwiki\Parsing\Handler\Block;
6be906b56SAndreas Gohruse dokuwiki\Parsing\Handler\CallWriter;
7be906b56SAndreas Gohruse dokuwiki\Parsing\Handler\CallWriterInterface;
8be906b56SAndreas Gohruse dokuwiki\Parsing\Handler\Lists;
9be906b56SAndreas Gohruse dokuwiki\Parsing\Handler\Nest;
10be906b56SAndreas Gohruse dokuwiki\Parsing\Handler\Preformatted;
11be906b56SAndreas Gohruse dokuwiki\Parsing\Handler\Quote;
12be906b56SAndreas Gohruse dokuwiki\Parsing\Handler\Table;
135c2aad12SAndreas Gohr
148b1b81beSAndreas Gohr/**
158b1b81beSAndreas Gohr * Class Doku_Handler
168b1b81beSAndreas Gohr */
170cecf9d5Sandiclass Doku_Handler {
188b1b81beSAndreas Gohr    /** @var CallWriterInterface */
198b1b81beSAndreas Gohr    protected $callWriter = null;
200cecf9d5Sandi
218b1b81beSAndreas Gohr    /** @var array The current CallWriter will write directly to this list of calls, Parser reads it */
228b1b81beSAndreas Gohr    public $calls = array();
230cecf9d5Sandi
248b1b81beSAndreas Gohr    /** @var array internal status holders for some modes */
258b1b81beSAndreas Gohr    protected $status = array(
2644881bd0Shenning.noren        'section' => false,
27e950d12fSChristopher Smith        'doublequote' => 0,
280cecf9d5Sandi    );
290cecf9d5Sandi
308b1b81beSAndreas Gohr    /** @var bool should blocks be rewritten? FIXME seems to always be true */
318b1b81beSAndreas Gohr    protected $rewriteBlocks = true;
32b7c441b9SHarry Fuecks
338b1b81beSAndreas Gohr    /**
348b1b81beSAndreas Gohr     * Doku_Handler constructor.
358b1b81beSAndreas Gohr     */
36e1cdd96cSAndreas Gohr    public function __construct() {
378b1b81beSAndreas Gohr        $this->callWriter = new CallWriter($this);
380cecf9d5Sandi    }
390cecf9d5Sandi
40276820f7SScrutinizer Auto-Fixer    /**
418b1b81beSAndreas Gohr     * Add a new call by passing it to the current CallWriter
428b1b81beSAndreas Gohr     *
438b1b81beSAndreas Gohr     * @param string $handler handler method name (see mode handlers below)
448b1b81beSAndreas Gohr     * @param mixed $args arguments for this call
458b1b81beSAndreas Gohr     * @param int $pos  byte position in the original source file
46276820f7SScrutinizer Auto-Fixer     */
4731c0895aSAndreas Gohr    public function addCall($handler, $args, $pos) {
480cecf9d5Sandi        $call = array($handler,$args, $pos);
498b1b81beSAndreas Gohr        $this->callWriter->writeCall($call);
500cecf9d5Sandi    }
510cecf9d5Sandi
52533aca44SAndreas Gohr    /**
53533aca44SAndreas Gohr     * Accessor for the current CallWriter
54533aca44SAndreas Gohr     *
55533aca44SAndreas Gohr     * @return CallWriterInterface
56533aca44SAndreas Gohr     */
57533aca44SAndreas Gohr    public function getCallWriter() {
58533aca44SAndreas Gohr        return $this->callWriter;
59533aca44SAndreas Gohr    }
60533aca44SAndreas Gohr
61533aca44SAndreas Gohr    /**
62533aca44SAndreas Gohr     * Set a new CallWriter
63533aca44SAndreas Gohr     *
64533aca44SAndreas Gohr     * @param CallWriterInterface $callWriter
65533aca44SAndreas Gohr     */
66533aca44SAndreas Gohr    public function setCallWriter($callWriter) {
67533aca44SAndreas Gohr        $this->callWriter = $callWriter;
68533aca44SAndreas Gohr    }
69533aca44SAndreas Gohr
70eb33b670SAndreas Gohr    /**
71eb33b670SAndreas Gohr     * Return the current internal status of the given name
72eb33b670SAndreas Gohr     *
73eb33b670SAndreas Gohr     * @param string $status
74eb33b670SAndreas Gohr     * @return mixed|null
75eb33b670SAndreas Gohr     */
76eb33b670SAndreas Gohr    public function getStatus($status) {
77eb33b670SAndreas Gohr        if (!isset($this->status[$status])) return null;
78eb33b670SAndreas Gohr        return $this->status[$status];
79eb33b670SAndreas Gohr    }
80eb33b670SAndreas Gohr
81eb33b670SAndreas Gohr    /**
82eb33b670SAndreas Gohr     * Set a new internal status
83eb33b670SAndreas Gohr     *
84eb33b670SAndreas Gohr     * @param string $status
85eb33b670SAndreas Gohr     * @param mixed $value
86eb33b670SAndreas Gohr     */
87eb33b670SAndreas Gohr    public function setStatus($status, $value) {
88eb33b670SAndreas Gohr        $this->status[$status] = $value;
89eb33b670SAndreas Gohr    }
90eb33b670SAndreas Gohr
9131c0895aSAndreas Gohr    /** @deprecated 2019-10-31 use addCall() instead */
9231c0895aSAndreas Gohr    public function _addCall($handler, $args, $pos) {
9331c0895aSAndreas Gohr        dbg_deprecated('addCall');
9431c0895aSAndreas Gohr        $this->addCall($handler, $args, $pos);
9531c0895aSAndreas Gohr    }
9631c0895aSAndreas Gohr
978b1b81beSAndreas Gohr    /**
988b1b81beSAndreas Gohr     * Similar to addCall, but adds a plugin call
998b1b81beSAndreas Gohr     *
1008b1b81beSAndreas Gohr     * @param string $plugin name of the plugin
1018b1b81beSAndreas Gohr     * @param mixed $args arguments for this call
1028b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
1038b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
1048b1b81beSAndreas Gohr     * @param string $match matched syntax
1058b1b81beSAndreas Gohr     */
106767b83f9SAndreas Gohr    public function addPluginCall($plugin, $args, $state, $pos, $match) {
10782d61635Spierre.spring        $call = array('plugin',array($plugin, $args, $state, $match), $pos);
1088b1b81beSAndreas Gohr        $this->callWriter->writeCall($call);
10904ebd214Schris    }
11004ebd214Schris
1118b1b81beSAndreas Gohr    /**
1128b1b81beSAndreas Gohr     * Finishes handling
1138b1b81beSAndreas Gohr     *
1148b1b81beSAndreas Gohr     * Called from the parser. Calls finalise() on the call writer, closes open
1158b1b81beSAndreas Gohr     * sections, rewrites blocks and adds document_start and document_end calls.
1168b1b81beSAndreas Gohr     *
1178b1b81beSAndreas Gohr     * @triggers PARSER_HANDLER_DONE
1188b1b81beSAndreas Gohr     */
1198b1b81beSAndreas Gohr    public function finalize(){
1208b1b81beSAndreas Gohr        $this->callWriter->finalise();
121f4f02a0fSchris
122e1c10e4dSchris        if ( $this->status['section'] ) {
123e1c10e4dSchris            $last_call = end($this->calls);
124e1c10e4dSchris            array_push($this->calls,array('section_close',array(), $last_call[2]));
1250cecf9d5Sandi        }
1260cecf9d5Sandi
127b7c441b9SHarry Fuecks        if ( $this->rewriteBlocks ) {
1285c2aad12SAndreas Gohr            $B = new Block();
1290cecf9d5Sandi            $this->calls = $B->process($this->calls);
130b7c441b9SHarry Fuecks        }
131e0ad864eSchris
132cbb44eabSAndreas Gohr        Event::createAndTrigger('PARSER_HANDLER_DONE',$this);
1330cecf9d5Sandi
1340cecf9d5Sandi        array_unshift($this->calls,array('document_start',array(),0));
1350cecf9d5Sandi        $last_call = end($this->calls);
1360cecf9d5Sandi        array_push($this->calls,array('document_end',array(),$last_call[2]));
1370cecf9d5Sandi    }
1380cecf9d5Sandi
1399e491c01SAndreas Gohr    /**
1409e491c01SAndreas Gohr     * fetch the current call and advance the pointer to the next one
1419e491c01SAndreas Gohr     *
1428b1b81beSAndreas Gohr     * @fixme seems to be unused?
1439e491c01SAndreas Gohr     * @return bool|mixed
1449e491c01SAndreas Gohr     */
1458b1b81beSAndreas Gohr    public function fetch() {
1469e491c01SAndreas Gohr        $call = current($this->calls);
1479e491c01SAndreas Gohr        if($call !== false) {
1489e491c01SAndreas Gohr            next($this->calls); //advance the pointer
1499e491c01SAndreas Gohr            return $call;
1500cecf9d5Sandi        }
15144881bd0Shenning.noren        return false;
1520cecf9d5Sandi    }
153ee20e7d1Sandi
154ee20e7d1Sandi
155ee20e7d1Sandi    /**
156e2d88156SLarsDW223     * Internal function for parsing highlight options.
157e2d88156SLarsDW223     * $options is parsed for key value pairs separated by commas.
158e2d88156SLarsDW223     * A value might also be missing in which case the value will simple
159e2d88156SLarsDW223     * be set to true. Commas in strings are ignored, e.g. option="4,56"
160e2d88156SLarsDW223     * will work as expected and will only create one entry.
161e2d88156SLarsDW223     *
16254f741e8SAndreas Gohr     * @param string $options space separated list of key-value pairs,
163e2d88156SLarsDW223     *                        e.g. option1=123, option2="456"
164e2d88156SLarsDW223     * @return array|null     Array of key-value pairs $array['key'] = 'value';
165e2d88156SLarsDW223     *                        or null if no entries found
166e2d88156SLarsDW223     */
167e2d88156SLarsDW223    protected function parse_highlight_options($options) {
168e2d88156SLarsDW223        $result = array();
16954f741e8SAndreas Gohr        preg_match_all('/(\w+(?:="[^"]*"))|(\w+(?:=[^\s]*))|(\w+[^=\s\]])(?:\s*)/', $options, $matches, PREG_SET_ORDER);
170e2d88156SLarsDW223        foreach ($matches as $match) {
171e2d88156SLarsDW223            $equal_sign = strpos($match [0], '=');
172e2d88156SLarsDW223            if ($equal_sign === false) {
17354f741e8SAndreas Gohr                $key = trim($match[0]);
174e2d88156SLarsDW223                $result [$key] = 1;
175e2d88156SLarsDW223            } else {
176e2d88156SLarsDW223                $key = substr($match[0], 0, $equal_sign);
177e2d88156SLarsDW223                $value = substr($match[0], $equal_sign+1);
178e2d88156SLarsDW223                $value = trim($value, '"');
179e2d88156SLarsDW223                if (strlen($value) > 0) {
180e2d88156SLarsDW223                    $result [$key] = $value;
181e2d88156SLarsDW223                } else {
182e2d88156SLarsDW223                    $result [$key] = 1;
183e2d88156SLarsDW223                }
184e2d88156SLarsDW223            }
185e2d88156SLarsDW223        }
186e2d88156SLarsDW223
187e2d88156SLarsDW223        // Check for supported options
188e2d88156SLarsDW223        $result = array_intersect_key(
189e2d88156SLarsDW223            $result,
190e2d88156SLarsDW223            array_flip(array(
191e2d88156SLarsDW223                           'enable_line_numbers',
192e2d88156SLarsDW223                           'start_line_numbers_at',
193e2d88156SLarsDW223                           'highlight_lines_extra',
194e2d88156SLarsDW223                           'enable_keyword_links')
195e2d88156SLarsDW223            )
196e2d88156SLarsDW223        );
197e2d88156SLarsDW223
198e2d88156SLarsDW223        // Sanitize values
199e2d88156SLarsDW223        if(isset($result['enable_line_numbers'])) {
20054f741e8SAndreas Gohr            if($result['enable_line_numbers'] === 'false') {
20154f741e8SAndreas Gohr                $result['enable_line_numbers'] = false;
20254f741e8SAndreas Gohr            }
203e2d88156SLarsDW223            $result['enable_line_numbers'] = (bool) $result['enable_line_numbers'];
204e2d88156SLarsDW223        }
205e2d88156SLarsDW223        if(isset($result['highlight_lines_extra'])) {
206e2d88156SLarsDW223            $result['highlight_lines_extra'] = array_map('intval', explode(',', $result['highlight_lines_extra']));
207e2d88156SLarsDW223            $result['highlight_lines_extra'] = array_filter($result['highlight_lines_extra']);
208e2d88156SLarsDW223            $result['highlight_lines_extra'] = array_unique($result['highlight_lines_extra']);
209e2d88156SLarsDW223        }
210e2d88156SLarsDW223        if(isset($result['start_line_numbers_at'])) {
211e2d88156SLarsDW223            $result['start_line_numbers_at'] = (int) $result['start_line_numbers_at'];
212e2d88156SLarsDW223        }
213e2d88156SLarsDW223        if(isset($result['enable_keyword_links'])) {
21454f741e8SAndreas Gohr            if($result['enable_keyword_links'] === 'false') {
21554f741e8SAndreas Gohr                $result['enable_keyword_links'] = false;
21654f741e8SAndreas Gohr            }
21754f741e8SAndreas Gohr            $result['enable_keyword_links'] = (bool) $result['enable_keyword_links'];
218e2d88156SLarsDW223        }
219e2d88156SLarsDW223        if (count($result) == 0) {
220e2d88156SLarsDW223            return null;
221e2d88156SLarsDW223        }
222e2d88156SLarsDW223
223e2d88156SLarsDW223        return $result;
224e2d88156SLarsDW223    }
225e2d88156SLarsDW223
2268b1b81beSAndreas Gohr    /**
2278b1b81beSAndreas Gohr     * Simplifies handling for the formatting tags which all behave the same
2288b1b81beSAndreas Gohr     *
2298b1b81beSAndreas Gohr     * @param string $match matched syntax
2308b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
2318b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
2328b1b81beSAndreas Gohr     * @param string $name actual mode name
2338b1b81beSAndreas Gohr     */
2348b1b81beSAndreas Gohr    protected function nestingTag($match, $state, $pos, $name) {
2358b1b81beSAndreas Gohr        switch ( $state ) {
2368b1b81beSAndreas Gohr            case DOKU_LEXER_ENTER:
2378b1b81beSAndreas Gohr                $this->addCall($name.'_open', array(), $pos);
2388b1b81beSAndreas Gohr                break;
2398b1b81beSAndreas Gohr            case DOKU_LEXER_EXIT:
2408b1b81beSAndreas Gohr                $this->addCall($name.'_close', array(), $pos);
2418b1b81beSAndreas Gohr                break;
2428b1b81beSAndreas Gohr            case DOKU_LEXER_UNMATCHED:
2438b1b81beSAndreas Gohr                $this->addCall('cdata', array($match), $pos);
2448b1b81beSAndreas Gohr                break;
2458b1b81beSAndreas Gohr        }
2468b1b81beSAndreas Gohr    }
2478b1b81beSAndreas Gohr
2488b1b81beSAndreas Gohr
2498b1b81beSAndreas Gohr    /**
2508b1b81beSAndreas Gohr     * The following methods define the handlers for the different Syntax modes
2518b1b81beSAndreas Gohr     *
252be906b56SAndreas Gohr     * The handlers are called from dokuwiki\Parsing\Lexer\Lexer\invokeParser()
2538b1b81beSAndreas Gohr     *
2548b1b81beSAndreas Gohr     * @todo it might make sense to move these into their own class or merge them with the
2558b1b81beSAndreas Gohr     *       ParserMode classes some time.
2568b1b81beSAndreas Gohr     */
2578b1b81beSAndreas Gohr    // region mode handlers
2588b1b81beSAndreas Gohr
2598b1b81beSAndreas Gohr    /**
2608b1b81beSAndreas Gohr     * Special plugin handler
2618b1b81beSAndreas Gohr     *
2628b1b81beSAndreas Gohr     * This handler is called for all modes starting with 'plugin_'.
2638b1b81beSAndreas Gohr     * An additional parameter with the plugin name is passed. The plugin's handle()
2648b1b81beSAndreas Gohr     * method is called here
2658b1b81beSAndreas Gohr     *
2668b1b81beSAndreas Gohr     * @author Andreas Gohr <andi@splitbrain.org>
2678b1b81beSAndreas Gohr     *
2688b1b81beSAndreas Gohr     * @param string $match matched syntax
2698b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
2708b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
2718b1b81beSAndreas Gohr     * @param string $pluginname name of the plugin
2728b1b81beSAndreas Gohr     * @return bool mode handled?
2738b1b81beSAndreas Gohr     */
2748b1b81beSAndreas Gohr    public function plugin($match, $state, $pos, $pluginname){
2758b1b81beSAndreas Gohr        $data = array($match);
276e1d9dcc8SAndreas Gohr        /** @var SyntaxPlugin $plugin */
2778b1b81beSAndreas Gohr        $plugin = plugin_load('syntax',$pluginname);
2788b1b81beSAndreas Gohr        if($plugin != null){
2798b1b81beSAndreas Gohr            $data = $plugin->handle($match, $state, $pos, $this);
2808b1b81beSAndreas Gohr        }
2818b1b81beSAndreas Gohr        if ($data !== false) {
2828b1b81beSAndreas Gohr            $this->addPluginCall($pluginname,$data,$state,$pos,$match);
2838b1b81beSAndreas Gohr        }
2848b1b81beSAndreas Gohr        return true;
2858b1b81beSAndreas Gohr    }
2868b1b81beSAndreas Gohr
2878b1b81beSAndreas Gohr    /**
2888b1b81beSAndreas Gohr     * @param string $match matched syntax
2898b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
2908b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
2918b1b81beSAndreas Gohr     * @return bool mode handled?
2928b1b81beSAndreas Gohr     */
2938b1b81beSAndreas Gohr    public function base($match, $state, $pos) {
2948b1b81beSAndreas Gohr        switch ( $state ) {
2958b1b81beSAndreas Gohr            case DOKU_LEXER_UNMATCHED:
2968b1b81beSAndreas Gohr                $this->addCall('cdata', array($match), $pos);
2978b1b81beSAndreas Gohr                return true;
2988b1b81beSAndreas Gohr            break;
2998b1b81beSAndreas Gohr        }
3008b1b81beSAndreas Gohr        return false;
3018b1b81beSAndreas Gohr    }
3028b1b81beSAndreas Gohr
3038b1b81beSAndreas Gohr    /**
3048b1b81beSAndreas Gohr     * @param string $match matched syntax
3058b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
3068b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
3078b1b81beSAndreas Gohr     * @return bool mode handled?
3088b1b81beSAndreas Gohr     */
3098b1b81beSAndreas Gohr    public function header($match, $state, $pos) {
3108b1b81beSAndreas Gohr        // get level and title
3118b1b81beSAndreas Gohr        $title = trim($match);
3128b1b81beSAndreas Gohr        $level = 7 - strspn($title,'=');
3138b1b81beSAndreas Gohr        if($level < 1) $level = 1;
3148b1b81beSAndreas Gohr        $title = trim($title,'=');
3158b1b81beSAndreas Gohr        $title = trim($title);
3168b1b81beSAndreas Gohr
3178b1b81beSAndreas Gohr        if ($this->status['section']) $this->addCall('section_close', array(), $pos);
3188b1b81beSAndreas Gohr
3198b1b81beSAndreas Gohr        $this->addCall('header', array($title, $level, $pos), $pos);
3208b1b81beSAndreas Gohr
3218b1b81beSAndreas Gohr        $this->addCall('section_open', array($level), $pos);
3228b1b81beSAndreas Gohr        $this->status['section'] = true;
3238b1b81beSAndreas Gohr        return true;
3248b1b81beSAndreas Gohr    }
3258b1b81beSAndreas Gohr
3268b1b81beSAndreas Gohr    /**
3278b1b81beSAndreas Gohr     * @param string $match matched syntax
3288b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
3298b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
3308b1b81beSAndreas Gohr     * @return bool mode handled?
3318b1b81beSAndreas Gohr     */
3328b1b81beSAndreas Gohr    public function notoc($match, $state, $pos) {
3338b1b81beSAndreas Gohr        $this->addCall('notoc', array(), $pos);
3348b1b81beSAndreas Gohr        return true;
3358b1b81beSAndreas Gohr    }
3368b1b81beSAndreas Gohr
3378b1b81beSAndreas Gohr    /**
3388b1b81beSAndreas Gohr     * @param string $match matched syntax
3398b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
3408b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
3418b1b81beSAndreas Gohr     * @return bool mode handled?
3428b1b81beSAndreas Gohr     */
3438b1b81beSAndreas Gohr    public function nocache($match, $state, $pos) {
3448b1b81beSAndreas Gohr        $this->addCall('nocache', array(), $pos);
3458b1b81beSAndreas Gohr        return true;
3468b1b81beSAndreas Gohr    }
3478b1b81beSAndreas Gohr
3488b1b81beSAndreas Gohr    /**
3498b1b81beSAndreas Gohr     * @param string $match matched syntax
3508b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
3518b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
3528b1b81beSAndreas Gohr     * @return bool mode handled?
3538b1b81beSAndreas Gohr     */
3548b1b81beSAndreas Gohr    public function linebreak($match, $state, $pos) {
3558b1b81beSAndreas Gohr        $this->addCall('linebreak', array(), $pos);
3568b1b81beSAndreas Gohr        return true;
3578b1b81beSAndreas Gohr    }
3588b1b81beSAndreas Gohr
3598b1b81beSAndreas Gohr    /**
3608b1b81beSAndreas Gohr     * @param string $match matched syntax
3618b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
3628b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
3638b1b81beSAndreas Gohr     * @return bool mode handled?
3648b1b81beSAndreas Gohr     */
3658b1b81beSAndreas Gohr    public function eol($match, $state, $pos) {
3668b1b81beSAndreas Gohr        $this->addCall('eol', array(), $pos);
3678b1b81beSAndreas Gohr        return true;
3688b1b81beSAndreas Gohr    }
3698b1b81beSAndreas Gohr
3708b1b81beSAndreas Gohr    /**
3718b1b81beSAndreas Gohr     * @param string $match matched syntax
3728b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
3738b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
3748b1b81beSAndreas Gohr     * @return bool mode handled?
3758b1b81beSAndreas Gohr     */
3768b1b81beSAndreas Gohr    public function hr($match, $state, $pos) {
3778b1b81beSAndreas Gohr        $this->addCall('hr', array(), $pos);
3788b1b81beSAndreas Gohr        return true;
3798b1b81beSAndreas Gohr    }
3808b1b81beSAndreas Gohr
3818b1b81beSAndreas Gohr    /**
3828b1b81beSAndreas Gohr     * @param string $match matched syntax
3838b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
3848b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
3858b1b81beSAndreas Gohr     * @return bool mode handled?
3868b1b81beSAndreas Gohr     */
3878b1b81beSAndreas Gohr    public function strong($match, $state, $pos) {
3888b1b81beSAndreas Gohr        $this->nestingTag($match, $state, $pos, 'strong');
3898b1b81beSAndreas Gohr        return true;
3908b1b81beSAndreas Gohr    }
3918b1b81beSAndreas Gohr
3928b1b81beSAndreas Gohr    /**
3938b1b81beSAndreas Gohr     * @param string $match matched syntax
3948b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
3958b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
3968b1b81beSAndreas Gohr     * @return bool mode handled?
3978b1b81beSAndreas Gohr     */
3988b1b81beSAndreas Gohr    public function emphasis($match, $state, $pos) {
3998b1b81beSAndreas Gohr        $this->nestingTag($match, $state, $pos, 'emphasis');
4008b1b81beSAndreas Gohr        return true;
4018b1b81beSAndreas Gohr    }
4028b1b81beSAndreas Gohr
4038b1b81beSAndreas Gohr    /**
4048b1b81beSAndreas Gohr     * @param string $match matched syntax
4058b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
4068b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
4078b1b81beSAndreas Gohr     * @return bool mode handled?
4088b1b81beSAndreas Gohr     */
4098b1b81beSAndreas Gohr    public function underline($match, $state, $pos) {
4108b1b81beSAndreas Gohr        $this->nestingTag($match, $state, $pos, 'underline');
4118b1b81beSAndreas Gohr        return true;
4128b1b81beSAndreas Gohr    }
4138b1b81beSAndreas Gohr
4148b1b81beSAndreas Gohr    /**
4158b1b81beSAndreas Gohr     * @param string $match matched syntax
4168b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
4178b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
4188b1b81beSAndreas Gohr     * @return bool mode handled?
4198b1b81beSAndreas Gohr     */
4208b1b81beSAndreas Gohr    public function monospace($match, $state, $pos) {
4218b1b81beSAndreas Gohr        $this->nestingTag($match, $state, $pos, 'monospace');
4228b1b81beSAndreas Gohr        return true;
4238b1b81beSAndreas Gohr    }
4248b1b81beSAndreas Gohr
4258b1b81beSAndreas Gohr    /**
4268b1b81beSAndreas Gohr     * @param string $match matched syntax
4278b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
4288b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
4298b1b81beSAndreas Gohr     * @return bool mode handled?
4308b1b81beSAndreas Gohr     */
4318b1b81beSAndreas Gohr    public function subscript($match, $state, $pos) {
4328b1b81beSAndreas Gohr        $this->nestingTag($match, $state, $pos, 'subscript');
4338b1b81beSAndreas Gohr        return true;
4348b1b81beSAndreas Gohr    }
4358b1b81beSAndreas Gohr
4368b1b81beSAndreas Gohr    /**
4378b1b81beSAndreas Gohr     * @param string $match matched syntax
4388b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
4398b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
4408b1b81beSAndreas Gohr     * @return bool mode handled?
4418b1b81beSAndreas Gohr     */
4428b1b81beSAndreas Gohr    public function superscript($match, $state, $pos) {
4438b1b81beSAndreas Gohr        $this->nestingTag($match, $state, $pos, 'superscript');
4448b1b81beSAndreas Gohr        return true;
4458b1b81beSAndreas Gohr    }
4468b1b81beSAndreas Gohr
4478b1b81beSAndreas Gohr    /**
4488b1b81beSAndreas Gohr     * @param string $match matched syntax
4498b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
4508b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
4518b1b81beSAndreas Gohr     * @return bool mode handled?
4528b1b81beSAndreas Gohr     */
4538b1b81beSAndreas Gohr    public function deleted($match, $state, $pos) {
4548b1b81beSAndreas Gohr        $this->nestingTag($match, $state, $pos, 'deleted');
4558b1b81beSAndreas Gohr        return true;
4568b1b81beSAndreas Gohr    }
4578b1b81beSAndreas Gohr
4588b1b81beSAndreas Gohr    /**
4598b1b81beSAndreas Gohr     * @param string $match matched syntax
4608b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
4618b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
4628b1b81beSAndreas Gohr     * @return bool mode handled?
4638b1b81beSAndreas Gohr     */
4648b1b81beSAndreas Gohr    public function footnote($match, $state, $pos) {
4658b1b81beSAndreas Gohr        if (!isset($this->_footnote)) $this->_footnote = false;
4668b1b81beSAndreas Gohr
4678b1b81beSAndreas Gohr        switch ( $state ) {
4688b1b81beSAndreas Gohr            case DOKU_LEXER_ENTER:
4698b1b81beSAndreas Gohr                // footnotes can not be nested - however due to limitations in lexer it can't be prevented
4708b1b81beSAndreas Gohr                // we will still enter a new footnote mode, we just do nothing
4718b1b81beSAndreas Gohr                if ($this->_footnote) {
4728b1b81beSAndreas Gohr                    $this->addCall('cdata', array($match), $pos);
4738b1b81beSAndreas Gohr                    break;
4748b1b81beSAndreas Gohr                }
4758b1b81beSAndreas Gohr                $this->_footnote = true;
4768b1b81beSAndreas Gohr
4778b1b81beSAndreas Gohr                $this->callWriter = new Nest($this->callWriter, 'footnote_close');
4788b1b81beSAndreas Gohr                $this->addCall('footnote_open', array(), $pos);
4798b1b81beSAndreas Gohr            break;
4808b1b81beSAndreas Gohr            case DOKU_LEXER_EXIT:
4818b1b81beSAndreas Gohr                // check whether we have already exitted the footnote mode, can happen if the modes were nested
4828b1b81beSAndreas Gohr                if (!$this->_footnote) {
4838b1b81beSAndreas Gohr                    $this->addCall('cdata', array($match), $pos);
4848b1b81beSAndreas Gohr                    break;
4858b1b81beSAndreas Gohr                }
4868b1b81beSAndreas Gohr
4878b1b81beSAndreas Gohr                $this->_footnote = false;
4888b1b81beSAndreas Gohr                $this->addCall('footnote_close', array(), $pos);
4898b1b81beSAndreas Gohr
4908b1b81beSAndreas Gohr                /** @var Nest $reWriter */
4918b1b81beSAndreas Gohr                $reWriter = $this->callWriter;
4928b1b81beSAndreas Gohr                $this->callWriter = $reWriter->process();
4938b1b81beSAndreas Gohr            break;
4948b1b81beSAndreas Gohr            case DOKU_LEXER_UNMATCHED:
4958b1b81beSAndreas Gohr                $this->addCall('cdata', array($match), $pos);
4968b1b81beSAndreas Gohr            break;
4978b1b81beSAndreas Gohr        }
4988b1b81beSAndreas Gohr        return true;
4998b1b81beSAndreas Gohr    }
5008b1b81beSAndreas Gohr
5018b1b81beSAndreas Gohr    /**
5028b1b81beSAndreas Gohr     * @param string $match matched syntax
5038b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
5048b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
5058b1b81beSAndreas Gohr     * @return bool mode handled?
5068b1b81beSAndreas Gohr     */
5078b1b81beSAndreas Gohr    public function listblock($match, $state, $pos) {
5088b1b81beSAndreas Gohr        switch ( $state ) {
5098b1b81beSAndreas Gohr            case DOKU_LEXER_ENTER:
5108b1b81beSAndreas Gohr                $this->callWriter = new Lists($this->callWriter);
5118b1b81beSAndreas Gohr                $this->addCall('list_open', array($match), $pos);
5128b1b81beSAndreas Gohr            break;
5138b1b81beSAndreas Gohr            case DOKU_LEXER_EXIT:
5148b1b81beSAndreas Gohr                $this->addCall('list_close', array(), $pos);
5158b1b81beSAndreas Gohr                /** @var Lists $reWriter */
5168b1b81beSAndreas Gohr                $reWriter = $this->callWriter;
5178b1b81beSAndreas Gohr                $this->callWriter = $reWriter->process();
5188b1b81beSAndreas Gohr            break;
5198b1b81beSAndreas Gohr            case DOKU_LEXER_MATCHED:
5208b1b81beSAndreas Gohr                $this->addCall('list_item', array($match), $pos);
5218b1b81beSAndreas Gohr            break;
5228b1b81beSAndreas Gohr            case DOKU_LEXER_UNMATCHED:
5238b1b81beSAndreas Gohr                $this->addCall('cdata', array($match), $pos);
5248b1b81beSAndreas Gohr            break;
5258b1b81beSAndreas Gohr        }
5268b1b81beSAndreas Gohr        return true;
5278b1b81beSAndreas Gohr    }
5288b1b81beSAndreas Gohr
5298b1b81beSAndreas Gohr    /**
5308b1b81beSAndreas Gohr     * @param string $match matched syntax
5318b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
5328b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
5338b1b81beSAndreas Gohr     * @return bool mode handled?
5348b1b81beSAndreas Gohr     */
5358b1b81beSAndreas Gohr    public function unformatted($match, $state, $pos) {
5368b1b81beSAndreas Gohr        if ( $state == DOKU_LEXER_UNMATCHED ) {
5378b1b81beSAndreas Gohr            $this->addCall('unformatted', array($match), $pos);
5388b1b81beSAndreas Gohr        }
5398b1b81beSAndreas Gohr        return true;
5408b1b81beSAndreas Gohr    }
5418b1b81beSAndreas Gohr
5428b1b81beSAndreas Gohr    /**
5438b1b81beSAndreas Gohr     * @param string $match matched syntax
5448b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
5458b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
5468b1b81beSAndreas Gohr     * @return bool mode handled?
5478b1b81beSAndreas Gohr     */
5488b1b81beSAndreas Gohr    public function php($match, $state, $pos) {
5498b1b81beSAndreas Gohr        if ( $state == DOKU_LEXER_UNMATCHED ) {
5508b1b81beSAndreas Gohr            $this->addCall('php', array($match), $pos);
5518b1b81beSAndreas Gohr        }
5528b1b81beSAndreas Gohr        return true;
5538b1b81beSAndreas Gohr    }
5548b1b81beSAndreas Gohr
5558b1b81beSAndreas Gohr    /**
5568b1b81beSAndreas Gohr     * @param string $match matched syntax
5578b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
5588b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
5598b1b81beSAndreas Gohr     * @return bool mode handled?
5608b1b81beSAndreas Gohr     */
5618b1b81beSAndreas Gohr    public function phpblock($match, $state, $pos) {
5628b1b81beSAndreas Gohr        if ( $state == DOKU_LEXER_UNMATCHED ) {
5638b1b81beSAndreas Gohr            $this->addCall('phpblock', array($match), $pos);
5648b1b81beSAndreas Gohr        }
5658b1b81beSAndreas Gohr        return true;
5668b1b81beSAndreas Gohr    }
5678b1b81beSAndreas Gohr
5688b1b81beSAndreas Gohr    /**
5698b1b81beSAndreas Gohr     * @param string $match matched syntax
5708b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
5718b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
5728b1b81beSAndreas Gohr     * @return bool mode handled?
5738b1b81beSAndreas Gohr     */
5748b1b81beSAndreas Gohr    public function html($match, $state, $pos) {
5758b1b81beSAndreas Gohr        if ( $state == DOKU_LEXER_UNMATCHED ) {
5768b1b81beSAndreas Gohr            $this->addCall('html', array($match), $pos);
5778b1b81beSAndreas Gohr        }
5788b1b81beSAndreas Gohr        return true;
5798b1b81beSAndreas Gohr    }
5808b1b81beSAndreas Gohr
5818b1b81beSAndreas Gohr    /**
5828b1b81beSAndreas Gohr     * @param string $match matched syntax
5838b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
5848b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
5858b1b81beSAndreas Gohr     * @return bool mode handled?
5868b1b81beSAndreas Gohr     */
5878b1b81beSAndreas Gohr    public function htmlblock($match, $state, $pos) {
5888b1b81beSAndreas Gohr        if ( $state == DOKU_LEXER_UNMATCHED ) {
5898b1b81beSAndreas Gohr            $this->addCall('htmlblock', array($match), $pos);
5908b1b81beSAndreas Gohr        }
5918b1b81beSAndreas Gohr        return true;
5928b1b81beSAndreas Gohr    }
5938b1b81beSAndreas Gohr
5948b1b81beSAndreas Gohr    /**
5958b1b81beSAndreas Gohr     * @param string $match matched syntax
5968b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
5978b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
5988b1b81beSAndreas Gohr     * @return bool mode handled?
5998b1b81beSAndreas Gohr     */
6008b1b81beSAndreas Gohr    public function preformatted($match, $state, $pos) {
6018b1b81beSAndreas Gohr        switch ( $state ) {
6028b1b81beSAndreas Gohr            case DOKU_LEXER_ENTER:
6038b1b81beSAndreas Gohr                $this->callWriter = new Preformatted($this->callWriter);
6048b1b81beSAndreas Gohr                $this->addCall('preformatted_start', array(), $pos);
6058b1b81beSAndreas Gohr            break;
6068b1b81beSAndreas Gohr            case DOKU_LEXER_EXIT:
6078b1b81beSAndreas Gohr                $this->addCall('preformatted_end', array(), $pos);
6088b1b81beSAndreas Gohr                /** @var Preformatted $reWriter */
6098b1b81beSAndreas Gohr                $reWriter = $this->callWriter;
6108b1b81beSAndreas Gohr                $this->callWriter = $reWriter->process();
6118b1b81beSAndreas Gohr            break;
6128b1b81beSAndreas Gohr            case DOKU_LEXER_MATCHED:
6138b1b81beSAndreas Gohr                $this->addCall('preformatted_newline', array(), $pos);
6148b1b81beSAndreas Gohr            break;
6158b1b81beSAndreas Gohr            case DOKU_LEXER_UNMATCHED:
6168b1b81beSAndreas Gohr                $this->addCall('preformatted_content', array($match), $pos);
6178b1b81beSAndreas Gohr            break;
6188b1b81beSAndreas Gohr        }
6198b1b81beSAndreas Gohr
6208b1b81beSAndreas Gohr        return true;
6218b1b81beSAndreas Gohr    }
6228b1b81beSAndreas Gohr
6238b1b81beSAndreas Gohr    /**
6248b1b81beSAndreas Gohr     * @param string $match matched syntax
6258b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
6268b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
6278b1b81beSAndreas Gohr     * @return bool mode handled?
6288b1b81beSAndreas Gohr     */
6298b1b81beSAndreas Gohr    public function quote($match, $state, $pos) {
6308b1b81beSAndreas Gohr
6318b1b81beSAndreas Gohr        switch ( $state ) {
6328b1b81beSAndreas Gohr
6338b1b81beSAndreas Gohr            case DOKU_LEXER_ENTER:
6348b1b81beSAndreas Gohr                $this->callWriter = new Quote($this->callWriter);
6358b1b81beSAndreas Gohr                $this->addCall('quote_start', array($match), $pos);
6368b1b81beSAndreas Gohr            break;
6378b1b81beSAndreas Gohr
6388b1b81beSAndreas Gohr            case DOKU_LEXER_EXIT:
6398b1b81beSAndreas Gohr                $this->addCall('quote_end', array(), $pos);
6408b1b81beSAndreas Gohr                /** @var Lists $reWriter */
6418b1b81beSAndreas Gohr                $reWriter = $this->callWriter;
6428b1b81beSAndreas Gohr                $this->callWriter = $reWriter->process();
6438b1b81beSAndreas Gohr            break;
6448b1b81beSAndreas Gohr
6458b1b81beSAndreas Gohr            case DOKU_LEXER_MATCHED:
6468b1b81beSAndreas Gohr                $this->addCall('quote_newline', array($match), $pos);
6478b1b81beSAndreas Gohr            break;
6488b1b81beSAndreas Gohr
6498b1b81beSAndreas Gohr            case DOKU_LEXER_UNMATCHED:
6508b1b81beSAndreas Gohr                $this->addCall('cdata', array($match), $pos);
6518b1b81beSAndreas Gohr            break;
6528b1b81beSAndreas Gohr
6538b1b81beSAndreas Gohr        }
6548b1b81beSAndreas Gohr
6558b1b81beSAndreas Gohr        return true;
6568b1b81beSAndreas Gohr    }
6578b1b81beSAndreas Gohr
6588b1b81beSAndreas Gohr    /**
6598b1b81beSAndreas Gohr     * @param string $match matched syntax
6608b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
6618b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
6628b1b81beSAndreas Gohr     * @return bool mode handled?
6638b1b81beSAndreas Gohr     */
6648b1b81beSAndreas Gohr    public function file($match, $state, $pos) {
6653d491f75SAndreas Gohr        return $this->code($match, $state, $pos, 'file');
6663d491f75SAndreas Gohr    }
6673d491f75SAndreas Gohr
6688b1b81beSAndreas Gohr    /**
6698b1b81beSAndreas Gohr     * @param string $match matched syntax
6708b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
6718b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
6728b1b81beSAndreas Gohr     * @param string $type either 'code' or 'file'
6738b1b81beSAndreas Gohr     * @return bool mode handled?
6748b1b81beSAndreas Gohr     */
6758b1b81beSAndreas Gohr    public function code($match, $state, $pos, $type='code') {
6763d491f75SAndreas Gohr        if ( $state == DOKU_LEXER_UNMATCHED ) {
6774b7f9e70STom N Harris            $matches = explode('>',$match,2);
678e2d88156SLarsDW223            // Cut out variable options enclosed in []
679e2d88156SLarsDW223            preg_match('/\[.*\]/', $matches[0], $options);
680e2d88156SLarsDW223            if (!empty($options[0])) {
681e2d88156SLarsDW223                $matches[0] = str_replace($options[0], '', $matches[0]);
682e2d88156SLarsDW223            }
6830139312bSAdrian Lang            $param = preg_split('/\s+/', $matches[0], 2, PREG_SPLIT_NO_EMPTY);
6840139312bSAdrian Lang            while(count($param) < 2) array_push($param, null);
6850139312bSAdrian Lang            // We shortcut html here.
6860139312bSAdrian Lang            if ($param[0] == 'html') $param[0] = 'html4strict';
6870139312bSAdrian Lang            if ($param[0] == '-') $param[0] = null;
6880139312bSAdrian Lang            array_unshift($param, $matches[1]);
689e2d88156SLarsDW223            if (!empty($options[0])) {
690e2d88156SLarsDW223                $param [] = $this->parse_highlight_options ($options[0]);
691e2d88156SLarsDW223            }
6928b1b81beSAndreas Gohr            $this->addCall($type, $param, $pos);
6930cecf9d5Sandi        }
69444881bd0Shenning.noren        return true;
6950cecf9d5Sandi    }
6960cecf9d5Sandi
6978b1b81beSAndreas Gohr    /**
6988b1b81beSAndreas Gohr     * @param string $match matched syntax
6998b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
7008b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
7018b1b81beSAndreas Gohr     * @return bool mode handled?
7028b1b81beSAndreas Gohr     */
7038b1b81beSAndreas Gohr    public function acronym($match, $state, $pos) {
7048b1b81beSAndreas Gohr        $this->addCall('acronym', array($match), $pos);
70544881bd0Shenning.noren        return true;
7060cecf9d5Sandi    }
7070cecf9d5Sandi
7088b1b81beSAndreas Gohr    /**
7098b1b81beSAndreas Gohr     * @param string $match matched syntax
7108b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
7118b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
7128b1b81beSAndreas Gohr     * @return bool mode handled?
7138b1b81beSAndreas Gohr     */
7148b1b81beSAndreas Gohr    public function smiley($match, $state, $pos) {
7158b1b81beSAndreas Gohr        $this->addCall('smiley', array($match), $pos);
71644881bd0Shenning.noren        return true;
7170cecf9d5Sandi    }
7180cecf9d5Sandi
7198b1b81beSAndreas Gohr    /**
7208b1b81beSAndreas Gohr     * @param string $match matched syntax
7218b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
7228b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
7238b1b81beSAndreas Gohr     * @return bool mode handled?
7248b1b81beSAndreas Gohr     */
7258b1b81beSAndreas Gohr    public function wordblock($match, $state, $pos) {
7268b1b81beSAndreas Gohr        $this->addCall('wordblock', array($match), $pos);
72744881bd0Shenning.noren        return true;
7280cecf9d5Sandi    }
7290cecf9d5Sandi
7308b1b81beSAndreas Gohr    /**
7318b1b81beSAndreas Gohr     * @param string $match matched syntax
7328b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
7338b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
7348b1b81beSAndreas Gohr     * @return bool mode handled?
7358b1b81beSAndreas Gohr     */
7368b1b81beSAndreas Gohr    public function entity($match, $state, $pos) {
7378b1b81beSAndreas Gohr        $this->addCall('entity', array($match), $pos);
73844881bd0Shenning.noren        return true;
7390cecf9d5Sandi    }
7400cecf9d5Sandi
7418b1b81beSAndreas Gohr    /**
7428b1b81beSAndreas Gohr     * @param string $match matched syntax
7438b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
7448b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
7458b1b81beSAndreas Gohr     * @return bool mode handled?
7468b1b81beSAndreas Gohr     */
7478b1b81beSAndreas Gohr    public function multiplyentity($match, $state, $pos) {
7480cecf9d5Sandi        preg_match_all('/\d+/',$match,$matches);
7498b1b81beSAndreas Gohr        $this->addCall('multiplyentity', array($matches[0][0], $matches[0][1]), $pos);
75044881bd0Shenning.noren        return true;
7510cecf9d5Sandi    }
7520cecf9d5Sandi
7538b1b81beSAndreas Gohr    /**
7548b1b81beSAndreas Gohr     * @param string $match matched syntax
7558b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
7568b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
7578b1b81beSAndreas Gohr     * @return bool mode handled?
7588b1b81beSAndreas Gohr     */
7598b1b81beSAndreas Gohr    public function singlequoteopening($match, $state, $pos) {
7608b1b81beSAndreas Gohr        $this->addCall('singlequoteopening', array(), $pos);
76144881bd0Shenning.noren        return true;
7620cecf9d5Sandi    }
7630cecf9d5Sandi
7648b1b81beSAndreas Gohr    /**
7658b1b81beSAndreas Gohr     * @param string $match matched syntax
7668b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
7678b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
7688b1b81beSAndreas Gohr     * @return bool mode handled?
7698b1b81beSAndreas Gohr     */
7708b1b81beSAndreas Gohr    public function singlequoteclosing($match, $state, $pos) {
7718b1b81beSAndreas Gohr        $this->addCall('singlequoteclosing', array(), $pos);
77244881bd0Shenning.noren        return true;
7730cecf9d5Sandi    }
7740cecf9d5Sandi
7758b1b81beSAndreas Gohr    /**
7768b1b81beSAndreas Gohr     * @param string $match matched syntax
7778b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
7788b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
7798b1b81beSAndreas Gohr     * @return bool mode handled?
7808b1b81beSAndreas Gohr     */
7818b1b81beSAndreas Gohr    public function apostrophe($match, $state, $pos) {
7828b1b81beSAndreas Gohr        $this->addCall('apostrophe', array(), $pos);
78357d757d1SAndreas Gohr        return true;
78457d757d1SAndreas Gohr    }
78557d757d1SAndreas Gohr
7868b1b81beSAndreas Gohr    /**
7878b1b81beSAndreas Gohr     * @param string $match matched syntax
7888b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
7898b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
7908b1b81beSAndreas Gohr     * @return bool mode handled?
7918b1b81beSAndreas Gohr     */
7928b1b81beSAndreas Gohr    public function doublequoteopening($match, $state, $pos) {
7938b1b81beSAndreas Gohr        $this->addCall('doublequoteopening', array(), $pos);
794e950d12fSChristopher Smith        $this->status['doublequote']++;
79544881bd0Shenning.noren        return true;
7960cecf9d5Sandi    }
7970cecf9d5Sandi
7988b1b81beSAndreas Gohr    /**
7998b1b81beSAndreas Gohr     * @param string $match matched syntax
8008b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
8018b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
8028b1b81beSAndreas Gohr     * @return bool mode handled?
8038b1b81beSAndreas Gohr     */
8048b1b81beSAndreas Gohr    public function doublequoteclosing($match, $state, $pos) {
805e950d12fSChristopher Smith        if ($this->status['doublequote'] <= 0) {
806e950d12fSChristopher Smith            $this->doublequoteopening($match, $state, $pos);
807e950d12fSChristopher Smith        } else {
8088b1b81beSAndreas Gohr            $this->addCall('doublequoteclosing', array(), $pos);
809e950d12fSChristopher Smith            $this->status['doublequote'] = max(0, --$this->status['doublequote']);
810e950d12fSChristopher Smith        }
81144881bd0Shenning.noren        return true;
8120cecf9d5Sandi    }
8130cecf9d5Sandi
8148b1b81beSAndreas Gohr    /**
8158b1b81beSAndreas Gohr     * @param string $match matched syntax
8168b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
8178b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
8188b1b81beSAndreas Gohr     * @return bool mode handled?
8198b1b81beSAndreas Gohr     */
8208b1b81beSAndreas Gohr    public function camelcaselink($match, $state, $pos) {
8218b1b81beSAndreas Gohr        $this->addCall('camelcaselink', array($match), $pos);
82244881bd0Shenning.noren        return true;
8230cecf9d5Sandi    }
8240cecf9d5Sandi
8258b1b81beSAndreas Gohr    /**
8268b1b81beSAndreas Gohr     * @param string $match matched syntax
8278b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
8288b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
8298b1b81beSAndreas Gohr     * @return bool mode handled?
8300cecf9d5Sandi     */
8318b1b81beSAndreas Gohr    public function internallink($match, $state, $pos) {
8320cecf9d5Sandi        // Strip the opening and closing markup
8330cecf9d5Sandi        $link = preg_replace(array('/^\[\[/','/\]\]$/u'),'',$match);
8340cecf9d5Sandi
8350cecf9d5Sandi        // Split title from URL
8364b7f9e70STom N Harris        $link = explode('|',$link,2);
8370cecf9d5Sandi        if ( !isset($link[1]) ) {
8380ea51e63SMatt Perry            $link[1] = null;
8390cecf9d5Sandi        } else if ( preg_match('/^\{\{[^\}]+\}\}$/',$link[1]) ) {
8405578eb8fSandi            // If the title is an image, convert it to an array containing the image details
841b625487dSandi            $link[1] = Doku_Handler_Parse_Media($link[1]);
8420cecf9d5Sandi        }
8430b7c14c2Sandi        $link[0] = trim($link[0]);
8440cecf9d5Sandi
8450e1c636eSandi        //decide which kind of link it is
8460e1c636eSandi
8476efc45a2SDmitry Katsubo        if ( link_isinterwiki($link[0]) ) {
8480e1c636eSandi            // Interwiki
8494b7f9e70STom N Harris            $interwiki = explode('>',$link[0],2);
8508b1b81beSAndreas Gohr            $this->addCall(
8510cecf9d5Sandi                'interwikilink',
8520cecf9d5Sandi                array($link[0],$link[1],strtolower($interwiki[0]),$interwiki[1]),
8530cecf9d5Sandi                $pos
8540cecf9d5Sandi                );
85515f1b77cSAndreas Gohr        }elseif ( preg_match('/^\\\\\\\\[^\\\\]+?\\\\/u',$link[0]) ) {
8560e1c636eSandi            // Windows Share
8578b1b81beSAndreas Gohr            $this->addCall(
8580cecf9d5Sandi                'windowssharelink',
8590cecf9d5Sandi                array($link[0],$link[1]),
8600cecf9d5Sandi                $pos
8610cecf9d5Sandi                );
8624468cb4cSAndreas Gohr        }elseif ( preg_match('#^([a-z0-9\-\.+]+?)://#i',$link[0]) ) {
8630e1c636eSandi            // external link (accepts all protocols)
8648b1b81beSAndreas Gohr            $this->addCall(
8650cecf9d5Sandi                    'externallink',
8660cecf9d5Sandi                    array($link[0],$link[1]),
8670cecf9d5Sandi                    $pos
8680cecf9d5Sandi                    );
8690a1d30bfSchris        }elseif ( preg_match('<'.PREG_PATTERN_VALID_EMAIL.'>',$link[0]) ) {
8700a1d30bfSchris            // E-Mail (pattern above is defined in inc/mail.php)
8718b1b81beSAndreas Gohr            $this->addCall(
872a6755281Sandi                'emaillink',
873a6755281Sandi                array($link[0],$link[1]),
874a6755281Sandi                $pos
875a6755281Sandi                );
8760b7c14c2Sandi        }elseif ( preg_match('!^#.+!',$link[0]) ){
8770b7c14c2Sandi            // local link
8788b1b81beSAndreas Gohr            $this->addCall(
8790b7c14c2Sandi                'locallink',
8800b7c14c2Sandi                array(substr($link[0],1),$link[1]),
8810b7c14c2Sandi                $pos
8820b7c14c2Sandi                );
8830e1c636eSandi        }else{
8840e1c636eSandi            // internal link
8858b1b81beSAndreas Gohr            $this->addCall(
8860e1c636eSandi                'internallink',
8870e1c636eSandi                array($link[0],$link[1]),
8880e1c636eSandi                $pos
8890e1c636eSandi                );
8900cecf9d5Sandi        }
8910e1c636eSandi
89244881bd0Shenning.noren        return true;
8930cecf9d5Sandi    }
8940cecf9d5Sandi
8958b1b81beSAndreas Gohr    /**
8968b1b81beSAndreas Gohr     * @param string $match matched syntax
8978b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
8988b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
8998b1b81beSAndreas Gohr     * @return bool mode handled?
9008b1b81beSAndreas Gohr     */
9018b1b81beSAndreas Gohr    public function filelink($match, $state, $pos) {
9028b1b81beSAndreas Gohr        $this->addCall('filelink', array($match, null), $pos);
90344881bd0Shenning.noren        return true;
9040cecf9d5Sandi    }
9050cecf9d5Sandi
9068b1b81beSAndreas Gohr    /**
9078b1b81beSAndreas Gohr     * @param string $match matched syntax
9088b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
9098b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
9108b1b81beSAndreas Gohr     * @return bool mode handled?
9118b1b81beSAndreas Gohr     */
9128b1b81beSAndreas Gohr    public function windowssharelink($match, $state, $pos) {
9138b1b81beSAndreas Gohr        $this->addCall('windowssharelink', array($match, null), $pos);
91444881bd0Shenning.noren        return true;
9150cecf9d5Sandi    }
9160cecf9d5Sandi
9178b1b81beSAndreas Gohr    /**
9188b1b81beSAndreas Gohr     * @param string $match matched syntax
9198b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
9208b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
9218b1b81beSAndreas Gohr     * @return bool mode handled?
9228b1b81beSAndreas Gohr     */
9238b1b81beSAndreas Gohr    public function media($match, $state, $pos) {
9240cecf9d5Sandi        $p = Doku_Handler_Parse_Media($match);
9250cecf9d5Sandi
9268b1b81beSAndreas Gohr        $this->addCall(
9270cecf9d5Sandi              $p['type'],
928dc673a5bSjoe.lapp              array($p['src'], $p['title'], $p['align'], $p['width'],
929*d8ab8746SAndreas Gohr                     $p['height'], $p['cache'], $p['linking']),
9300cecf9d5Sandi              $pos
9310cecf9d5Sandi             );
93244881bd0Shenning.noren        return true;
9330cecf9d5Sandi    }
9340cecf9d5Sandi
9358b1b81beSAndreas Gohr    /**
9368b1b81beSAndreas Gohr     * @param string $match matched syntax
9378b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
9388b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
9398b1b81beSAndreas Gohr     * @return bool mode handled?
9408b1b81beSAndreas Gohr     */
9418b1b81beSAndreas Gohr    public function rss($match, $state, $pos) {
942b625487dSandi        $link = preg_replace(array('/^\{\{rss>/','/\}\}$/'),'',$match);
9433db95becSAndreas Gohr
9443db95becSAndreas Gohr        // get params
9453db95becSAndreas Gohr        list($link,$params) = explode(' ',$link,2);
9463db95becSAndreas Gohr
9473db95becSAndreas Gohr        $p = array();
9483db95becSAndreas Gohr        if(preg_match('/\b(\d+)\b/',$params,$match)){
9493db95becSAndreas Gohr            $p['max'] = $match[1];
9503db95becSAndreas Gohr        }else{
9513db95becSAndreas Gohr            $p['max'] = 8;
9523db95becSAndreas Gohr        }
9533db95becSAndreas Gohr        $p['reverse'] = (preg_match('/rev/',$params));
9543db95becSAndreas Gohr        $p['author']  = (preg_match('/\b(by|author)/',$params));
9553db95becSAndreas Gohr        $p['date']    = (preg_match('/\b(date)/',$params));
9563db95becSAndreas Gohr        $p['details'] = (preg_match('/\b(desc|detail)/',$params));
95738c6f603SRobin H. Johnson        $p['nosort']  = (preg_match('/\b(nosort)\b/',$params));
9583db95becSAndreas Gohr
9590a69dff7Schris        if (preg_match('/\b(\d+)([dhm])\b/',$params,$match)) {
9600a69dff7Schris            $period = array('d' => 86400, 'h' => 3600, 'm' => 60);
9610a69dff7Schris            $p['refresh'] = max(600,$match[1]*$period[$match[2]]);  // n * period in seconds, minimum 10 minutes
9620a69dff7Schris        } else {
9630a69dff7Schris            $p['refresh'] = 14400;   // default to 4 hours
9640a69dff7Schris        }
9650a69dff7Schris
9668b1b81beSAndreas Gohr        $this->addCall('rss', array($link, $p), $pos);
96744881bd0Shenning.noren        return true;
968b625487dSandi    }
969b625487dSandi
9708b1b81beSAndreas Gohr    /**
9718b1b81beSAndreas Gohr     * @param string $match matched syntax
9728b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
9738b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
9748b1b81beSAndreas Gohr     * @return bool mode handled?
9758b1b81beSAndreas Gohr     */
9768b1b81beSAndreas Gohr    public function externallink($match, $state, $pos) {
977da9f31c5SAndreas Gohr        $url   = $match;
978da9f31c5SAndreas Gohr        $title = null;
9790cecf9d5Sandi
980da9f31c5SAndreas Gohr        // add protocol on simple short URLs
981da9f31c5SAndreas Gohr        if(substr($url,0,3) == 'ftp' && (substr($url,0,6) != 'ftp://')){
982da9f31c5SAndreas Gohr            $title = $url;
983da9f31c5SAndreas Gohr            $url   = 'ftp://'.$url;
984da9f31c5SAndreas Gohr        }
985da9f31c5SAndreas Gohr        if(substr($url,0,3) == 'www' && (substr($url,0,7) != 'http://')){
986da9f31c5SAndreas Gohr            $title = $url;
987da9f31c5SAndreas Gohr            $url = 'http://'.$url;
988da9f31c5SAndreas Gohr        }
989da9f31c5SAndreas Gohr
9908b1b81beSAndreas Gohr        $this->addCall('externallink', array($url, $title), $pos);
99144881bd0Shenning.noren        return true;
9920cecf9d5Sandi    }
9930cecf9d5Sandi
9948b1b81beSAndreas Gohr    /**
9958b1b81beSAndreas Gohr     * @param string $match matched syntax
9968b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
9978b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
9988b1b81beSAndreas Gohr     * @return bool mode handled?
9998b1b81beSAndreas Gohr     */
10008b1b81beSAndreas Gohr    public function emaillink($match, $state, $pos) {
10010cecf9d5Sandi        $email = preg_replace(array('/^</','/>$/'),'',$match);
10028b1b81beSAndreas Gohr        $this->addCall('emaillink', array($email, null), $pos);
100344881bd0Shenning.noren        return true;
10040cecf9d5Sandi    }
10050cecf9d5Sandi
10068b1b81beSAndreas Gohr    /**
10078b1b81beSAndreas Gohr     * @param string $match matched syntax
10088b1b81beSAndreas Gohr     * @param int $state a LEXER_STATE_* constant
10098b1b81beSAndreas Gohr     * @param int $pos byte position in the original source file
10108b1b81beSAndreas Gohr     * @return bool mode handled?
10118b1b81beSAndreas Gohr     */
10128b1b81beSAndreas Gohr    public function table($match, $state, $pos) {
10130cecf9d5Sandi        switch ( $state ) {
10140cecf9d5Sandi
10150cecf9d5Sandi            case DOKU_LEXER_ENTER:
10160cecf9d5Sandi
10178b1b81beSAndreas Gohr                $this->callWriter = new Table($this->callWriter);
10180cecf9d5Sandi
10198b1b81beSAndreas Gohr                $this->addCall('table_start', array($pos + 1), $pos);
10200cecf9d5Sandi                if ( trim($match) == '^' ) {
10218b1b81beSAndreas Gohr                    $this->addCall('tableheader', array(), $pos);
10220cecf9d5Sandi                } else {
10238b1b81beSAndreas Gohr                    $this->addCall('tablecell', array(), $pos);
10240cecf9d5Sandi                }
10250cecf9d5Sandi            break;
10260cecf9d5Sandi
10270cecf9d5Sandi            case DOKU_LEXER_EXIT:
10288b1b81beSAndreas Gohr                $this->addCall('table_end', array($pos), $pos);
10295c2aad12SAndreas Gohr                /** @var Table $reWriter */
10308b1b81beSAndreas Gohr                $reWriter = $this->callWriter;
10318b1b81beSAndreas Gohr                $this->callWriter = $reWriter->process();
10320cecf9d5Sandi            break;
10330cecf9d5Sandi
10340cecf9d5Sandi            case DOKU_LEXER_UNMATCHED:
10350cecf9d5Sandi                if ( trim($match) != '' ) {
10368b1b81beSAndreas Gohr                    $this->addCall('cdata', array($match), $pos);
10370cecf9d5Sandi                }
10380cecf9d5Sandi            break;
10390cecf9d5Sandi
10400cecf9d5Sandi            case DOKU_LEXER_MATCHED:
10419ab75d9eSAndreas Gohr                if ( $match == ' ' ){
10428b1b81beSAndreas Gohr                    $this->addCall('cdata', array($match), $pos);
104325b97867Shakan.sandell                } else if ( preg_match('/:::/',$match) ) {
10448b1b81beSAndreas Gohr                    $this->addCall('rowspan', array($match), $pos);
1045e205b721SAndreas Gohr                } else if ( preg_match('/\t+/',$match) ) {
10468b1b81beSAndreas Gohr                    $this->addCall('table_align', array($match), $pos);
1047e205b721SAndreas Gohr                } else if ( preg_match('/ {2,}/',$match) ) {
10488b1b81beSAndreas Gohr                    $this->addCall('table_align', array($match), $pos);
10490cecf9d5Sandi                } else if ( $match == "\n|" ) {
10508b1b81beSAndreas Gohr                    $this->addCall('table_row', array(), $pos);
10518b1b81beSAndreas Gohr                    $this->addCall('tablecell', array(), $pos);
10520cecf9d5Sandi                } else if ( $match == "\n^" ) {
10538b1b81beSAndreas Gohr                    $this->addCall('table_row', array(), $pos);
10548b1b81beSAndreas Gohr                    $this->addCall('tableheader', array(), $pos);
10550cecf9d5Sandi                } else if ( $match == '|' ) {
10568b1b81beSAndreas Gohr                    $this->addCall('tablecell', array(), $pos);
10570cecf9d5Sandi                } else if ( $match == '^' ) {
10588b1b81beSAndreas Gohr                    $this->addCall('tableheader', array(), $pos);
10590cecf9d5Sandi                }
10600cecf9d5Sandi            break;
10610cecf9d5Sandi        }
106244881bd0Shenning.noren        return true;
10630cecf9d5Sandi    }
10648b1b81beSAndreas Gohr
10658b1b81beSAndreas Gohr    // endregion modes
10660cecf9d5Sandi}
10670cecf9d5Sandi
10680cecf9d5Sandi//------------------------------------------------------------------------
10690cecf9d5Sandifunction Doku_Handler_Parse_Media($match) {
1070*d8ab8746SAndreas Gohr
10710cecf9d5Sandi    // Strip the opening and closing markup
10720cecf9d5Sandi    $link = preg_replace(array('/^\{\{/','/\}\}$/u'),'',$match);
10730cecf9d5Sandi
10740cecf9d5Sandi    // Split title from URL
10754b7f9e70STom N Harris    $link = explode('|',$link,2);
10760cecf9d5Sandi
10770cecf9d5Sandi    // Check alignment
10780cecf9d5Sandi    $ralign = (bool)preg_match('/^ /',$link[0]);
10790cecf9d5Sandi    $lalign = (bool)preg_match('/ $/',$link[0]);
10800cecf9d5Sandi
10810cecf9d5Sandi    // Logic = what's that ;)...
10820cecf9d5Sandi    if ( $lalign & $ralign ) {
10830cecf9d5Sandi        $align = 'center';
10840cecf9d5Sandi    } else if ( $ralign ) {
10850cecf9d5Sandi        $align = 'right';
10860cecf9d5Sandi    } else if ( $lalign ) {
10870cecf9d5Sandi        $align = 'left';
10880cecf9d5Sandi    } else {
10890ea51e63SMatt Perry        $align = null;
10900cecf9d5Sandi    }
10910cecf9d5Sandi
10920cecf9d5Sandi    // The title...
10930cecf9d5Sandi    if ( !isset($link[1]) ) {
10940ea51e63SMatt Perry        $link[1] = null;
10950cecf9d5Sandi    }
10960cecf9d5Sandi
10974826ab45Sandi    //remove aligning spaces
10984826ab45Sandi    $link[0] = trim($link[0]);
10990cecf9d5Sandi
11004826ab45Sandi    //split into src and parameters (using the very last questionmark)
11014826ab45Sandi    $pos = strrpos($link[0], '?');
11024826ab45Sandi    if($pos !== false){
11034826ab45Sandi        $src   = substr($link[0],0,$pos);
11044826ab45Sandi        $param = substr($link[0],$pos+1);
11050cecf9d5Sandi    }else{
11064826ab45Sandi        $src   = $link[0];
11074826ab45Sandi        $param = '';
11080cecf9d5Sandi    }
11090cecf9d5Sandi
11104826ab45Sandi    //parse width and height
11114826ab45Sandi    if(preg_match('#(\d+)(x(\d+))?#i',$param,$size)){
1112c48d6608SAndreas Gohr        !empty($size[1]) ? $w = $size[1] : $w = null;
1113c48d6608SAndreas Gohr        !empty($size[3]) ? $h = $size[3] : $h = null;
1114fc1c55b1Shfuecks    } else {
11150ea51e63SMatt Perry        $w = null;
11160ea51e63SMatt Perry        $h = null;
11170cecf9d5Sandi    }
11180cecf9d5Sandi
1119dc673a5bSjoe.lapp    //get linking command
1120d35ab615Shenning.noren    if(preg_match('/nolink/i',$param)){
1121dc673a5bSjoe.lapp        $linking = 'nolink';
1122d35ab615Shenning.noren    }else if(preg_match('/direct/i',$param)){
1123dc673a5bSjoe.lapp        $linking = 'direct';
11248acb3108SAndreas Gohr    }else if(preg_match('/linkonly/i',$param)){
11258acb3108SAndreas Gohr        $linking = 'linkonly';
1126dc673a5bSjoe.lapp    }else{
1127dc673a5bSjoe.lapp        $linking = 'details';
1128dc673a5bSjoe.lapp    }
1129dc673a5bSjoe.lapp
11304826ab45Sandi    //get caching command
11314826ab45Sandi    if (preg_match('/(nocache|recache)/i',$param,$cachemode)){
11324826ab45Sandi        $cache = $cachemode[1];
11330cecf9d5Sandi    }else{
11344826ab45Sandi        $cache = 'cache';
11350cecf9d5Sandi    }
1136*d8ab8746SAndreas Gohr
11376efc45a2SDmitry Katsubo    // Check whether this is a local or remote image or interwiki
11386efc45a2SDmitry Katsubo    if (media_isexternal($src) || link_isinterwiki($src)){
11394826ab45Sandi        $call = 'externalmedia';
11400cecf9d5Sandi    } else {
11414826ab45Sandi        $call = 'internalmedia';
11420cecf9d5Sandi    }
11430cecf9d5Sandi
11440cecf9d5Sandi    $params = array(
11450cecf9d5Sandi        'type'=>$call,
11464826ab45Sandi        'src'=>$src,
11470cecf9d5Sandi        'title'=>$link[1],
11480cecf9d5Sandi        'align'=>$align,
11494826ab45Sandi        'width'=>$w,
11504826ab45Sandi        'height'=>$h,
11510cecf9d5Sandi        'cache'=>$cache,
1152dc673a5bSjoe.lapp        'linking'=>$linking,
11530cecf9d5Sandi    );
11540cecf9d5Sandi
11550cecf9d5Sandi    return $params;
11560cecf9d5Sandi}
11570cecf9d5Sandi
1158