xref: /plugin/mikioplugin/syntax/core.php (revision 358ba801512b8af1a6a8fe2c1997a27b96bab6ae)
117e6d639SJames Collins<?php
217e6d639SJames Collins/**
317e6d639SJames Collins * Mikio Core Syntax Plugin
417e6d639SJames Collins *
57935713eSJames Collins * @link        http://github.com/nomadjimbob/mikioplugin
617e6d639SJames Collins * @license     GPL 2 (http://www.gnu.org/licenses/gpl.html)
717e6d639SJames Collins * @author      James Collins <james.collins@outlook.com.au>
817e6d639SJames Collins */
917e6d639SJames Collinsif (!defined('DOKU_INC')) die();
1017e6d639SJames Collinsif (!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN', DOKU_INC . 'lib/plugins/');
1117e6d639SJames Collins
127935713eSJames Collinsdefine('MIKIO_LEXER_AUTO', 0);
137935713eSJames Collinsdefine('MIKIO_LEXER_ENTER', 1);
147935713eSJames Collinsdefine('MIKIO_LEXER_EXIT', 2);
157935713eSJames Collinsdefine('MIKIO_LEXER_SPECIAL', 3);
1617e6d639SJames Collins
177935713eSJames Collinsclass syntax_plugin_mikioplugin_core extends DokuWiki_Syntax_Plugin
187935713eSJames Collins{
1917e6d639SJames Collins    public $pattern_entry       = '';
203deaf3a5SJames Collins    public $pattern             = '';
2117e6d639SJames Collins    public $pattern_exit        = '';
2217e6d639SJames Collins    public $tag                 = '';
237935713eSJames Collins    public $hasEndTag           = true;
2417e6d639SJames Collins    public $options             = array();
257935713eSJames Collins
267935713eSJames Collins    protected $tagPrefix          = ''; //'mikio-';
277935713eSJames Collins    protected $classPrefix        = 'mikiop-';
287935713eSJames Collins    protected $elemClass          = 'mikiop';
297935713eSJames Collins
307935713eSJames Collins    private $values              = array();
3117e6d639SJames Collins
3217e6d639SJames Collins
337935713eSJames Collins    function __construct() { }
347935713eSJames Collins    public function getType() { return 'formatting'; }
357935713eSJames Collins    public function getAllowedTypes() { return array('formatting', 'substition', 'disabled', 'paragraphs'); }
367935713eSJames Collins    // public function getAllowedTypes() { return array('formatting', 'substition', 'disabled'); }
3717e6d639SJames Collins    public function getSort() { return 32; }
387935713eSJames Collins    public function getPType() { return 'stack'; }
3917e6d639SJames Collins
4017e6d639SJames Collins
417935713eSJames Collins    public function connectTo($mode)
427935713eSJames Collins    {
4317e6d639SJames Collins        if ($this->pattern_entry == '' && $this->tag != '') {
447935713eSJames Collins            if ($this->hasEndTag) {
457935713eSJames Collins                $this->pattern_entry = '<(?i:' . $this->tagPrefix . $this->tag . ')(?=[ >]).*?>(?=.*?</(?i:' . $this->tagPrefix . $this->tag . ')>)';
4617e6d639SJames Collins            } else {
477935713eSJames Collins                $this->pattern_entry = '<(?i:' . $this->tagPrefix . $this->tag . ').*?>';
4817e6d639SJames Collins            }
4917e6d639SJames Collins        }
5017e6d639SJames Collins
5117e6d639SJames Collins        if ($this->pattern_entry != '') {
527935713eSJames Collins            if ($this->hasEndTag) {
5317e6d639SJames Collins                $this->Lexer->addEntryPattern($this->pattern_entry, $mode, 'plugin_mikioplugin_' . $this->getPluginComponent());
547935713eSJames Collins            } else {
557935713eSJames Collins                $this->Lexer->addSpecialPattern($this->pattern_entry, $mode, 'plugin_mikioplugin_' . $this->getPluginComponent());
567935713eSJames Collins            }
5717e6d639SJames Collins        }
5817e6d639SJames Collins    }
593deaf3a5SJames Collins
6017e6d639SJames Collins
617935713eSJames Collins    public function postConnect()
627935713eSJames Collins    {
637935713eSJames Collins        if ($this->hasEndTag) {
6417e6d639SJames Collins            if ($this->pattern_exit == '' && $this->tag != '') {
657935713eSJames Collins                $this->pattern_exit = '</(?i:' . $this->tagPrefix . $this->tag . ')>';
6617e6d639SJames Collins            }
6717e6d639SJames Collins
6817e6d639SJames Collins            if ($this->pattern_exit != '') {
6917e6d639SJames Collins                $this->Lexer->addExitPattern($this->pattern_exit, 'plugin_mikioplugin_' . $this->getPluginComponent());
7017e6d639SJames Collins            }
7117e6d639SJames Collins        }
7217e6d639SJames Collins    }
7317e6d639SJames Collins
747935713eSJames Collins    public function handle($match, $state, $pos, Doku_Handler $handler)
757935713eSJames Collins    {
7617e6d639SJames Collins        switch ($state) {
7717e6d639SJames Collins            case DOKU_LEXER_ENTER:
7817e6d639SJames Collins            case DOKU_LEXER_SPECIAL:
79c5f7fed6SJames Collins                $match_fix = preg_replace('/\s*=\s*/', '=', trim(substr($match, strlen($this->tagPrefix . $this->tag) + 1, -1)));
80c5f7fed6SJames Collins                $optionlist = preg_split('/\s(?=([^"]*"[^"]*")*[^"]*$)/', $match_fix);
8117e6d639SJames Collins
8217e6d639SJames Collins                $options = array();
8317e6d639SJames Collins                foreach ($optionlist as $item) {
8417e6d639SJames Collins                    $i = strpos($item, '=');
8517e6d639SJames Collins                    if ($i !== false) {
8617e6d639SJames Collins                        $value = substr($item, $i + 1);
8717e6d639SJames Collins
8817e6d639SJames Collins                        if (substr($value, 0, 1) == '"') $value = substr($value, 1);
8917e6d639SJames Collins                        if (substr($value, -1) == '"') $value = substr($value, 0, -1);
9017e6d639SJames Collins
9117e6d639SJames Collins                        $options[substr($item, 0, $i)] = $value;
9217e6d639SJames Collins                    } else {
9317e6d639SJames Collins                        $options[$item] = true;
9417e6d639SJames Collins                    }
9517e6d639SJames Collins                }
9617e6d639SJames Collins
977935713eSJames Collins                if(count($this->options) > 0) {
9831359b6fSJames Collins                    $options_clean = $this->cleanOptions($options);
997935713eSJames Collins                } else {
1007935713eSJames Collins                    $options_clean = $options;
1017935713eSJames Collins                }
10231359b6fSJames Collins
10331359b6fSJames Collins                $this->values = $options_clean;
10431359b6fSJames Collins
10531359b6fSJames Collins                return array($state, $options_clean);
10631359b6fSJames Collins
1073deaf3a5SJames Collins            case DOKU_LEXER_MATCHED:
1083deaf3a5SJames Collins                return array($state, $match);
1093deaf3a5SJames Collins
11031359b6fSJames Collins            case DOKU_LEXER_UNMATCHED:
11131359b6fSJames Collins                return array($state, $match);
11231359b6fSJames Collins
11331359b6fSJames Collins            case DOKU_LEXER_EXIT:
114f4aa5cdcSJames Collins                return array($state, $this->values);
11531359b6fSJames Collins        }
11631359b6fSJames Collins
11731359b6fSJames Collins        return array();
11831359b6fSJames Collins    }
11931359b6fSJames Collins
12031359b6fSJames Collins
1217935713eSJames Collins    /*
1227935713eSJames Collins    * clean element options to only supported attributes, setting defaults if required
1237935713eSJames Collins    *
1247935713eSJames Collins    * @param $options   options passed to element
1257935713eSJames Collins    * @return           array of options supported with default set
1267935713eSJames Collins    */
1277935713eSJames Collins    protected function cleanOptions($data, $options=null)
1287935713eSJames Collins    {
1297935713eSJames Collins        $optionsCleaned = array();
13031359b6fSJames Collins
1317935713eSJames Collins        if($options == null) $options = $this->options;
1327935713eSJames Collins
1337935713eSJames Collins        // Match DokuWiki passed options to syntax options
1347935713eSJames Collins        foreach ($data as $optionKey => $optionValue) {
1357935713eSJames Collins            foreach ($options as $syntaxKey => $syntaxValue) {
1367935713eSJames Collins                if (strcasecmp($optionKey, $syntaxKey) == 0) {
1377935713eSJames Collins                    if (array_key_exists('type', $options[$syntaxKey])) {
1387935713eSJames Collins                        $type = $options[$syntaxKey]['type'];
1397935713eSJames Collins
1407935713eSJames Collins                        switch ($type) {
1417935713eSJames Collins                            case 'boolean':
1427935713eSJames Collins                                $optionsCleaned[$syntaxKey] = filter_var($optionValue, FILTER_VALIDATE_BOOLEAN);
1437935713eSJames Collins                                break;
1447935713eSJames Collins                            case 'number':
1457935713eSJames Collins                                $optionsCleaned[$syntaxKey] = filter_var($optionValue, FILTER_VALIDATE_INT);
1467935713eSJames Collins                                break;
1477935713eSJames Collins                            case 'float':
1487935713eSJames Collins                                $optionsCleaned[$syntaxKey] = filter_var($optionValue, FILTER_VALIDATE_FLOAT);
1497935713eSJames Collins                                break;
1507935713eSJames Collins                            case 'text':
1517935713eSJames Collins                                $optionsCleaned[$syntaxKey] = $optionValue;
1527935713eSJames Collins                                break;
1537935713eSJames Collins                            case 'size':
1547935713eSJames Collins                                $s = strtolower($optionValue);
1557935713eSJames Collins                                $i = '';
1567935713eSJames Collins                                if (substr($s, -3) == 'rem') {
1577935713eSJames Collins                                    $i = substr($s, 0, -3);
1587935713eSJames Collins                                    $s = 'rem';
1597935713eSJames Collins                                } elseif (substr($s, -2) == 'em') {
1607935713eSJames Collins                                    $i = substr($s, 0, -2);
1617935713eSJames Collins                                    $s = 'em';
1627935713eSJames Collins                                }
1637935713eSJames Collins                                elseif (substr($s, -2) == 'px') {
1647935713eSJames Collins                                    $i = substr($s, 0, -2);
1657935713eSJames Collins                                    $s = 'px';
1667935713eSJames Collins                                }
1677935713eSJames Collins                                elseif (substr($s, -1) == '%') {
1687935713eSJames Collins                                    $i = substr($s, 0, -1);
1697935713eSJames Collins                                    $s = '%';
1707935713eSJames Collins                                }
1717935713eSJames Collins                                else {
17218e323fdSJames Collins                                    if($s != 'auto') {
1737935713eSJames Collins                                        $i = filter_var($s, FILTER_VALIDATE_INT);
1747935713eSJames Collins                                        if ($i == '') $i = '1';
1757935713eSJames Collins                                        $s = 'rem';
1767935713eSJames Collins                                    }
17718e323fdSJames Collins                                }
1787935713eSJames Collins
1797935713eSJames Collins                                $optionsCleaned[$syntaxKey] = $i . $s;
1807935713eSJames Collins                                break;
18118e323fdSJames Collins                            case 'multisize':
18218e323fdSJames Collins                                $val = '';
18318e323fdSJames Collins                                $parts = explode(' ', $optionValue);
18418e323fdSJames Collins                                foreach($parts as &$part) {
18518e323fdSJames Collins                                    $s = strtolower($part);
18618e323fdSJames Collins                                    $i = '';
18718e323fdSJames Collins                                    if (substr($s, -3) == 'rem') {
18818e323fdSJames Collins                                        $i = substr($s, 0, -3);
18918e323fdSJames Collins                                        $s = 'rem';
19018e323fdSJames Collins                                    } elseif (substr($s, -2) == 'em') {
19118e323fdSJames Collins                                        $i = substr($s, 0, -2);
19218e323fdSJames Collins                                        $s = 'em';
19318e323fdSJames Collins                                    }
19418e323fdSJames Collins                                    elseif (substr($s, -2) == 'px') {
19518e323fdSJames Collins                                        $i = substr($s, 0, -2);
19618e323fdSJames Collins                                        $s = 'px';
19718e323fdSJames Collins                                    }
1982608c53cSJames Collins                                    elseif (substr($s, -2) == 'fr') {
1992608c53cSJames Collins                                        $i = substr($s, 0, -2);
2002608c53cSJames Collins                                        $s = 'fr';
2012608c53cSJames Collins                                    }
20218e323fdSJames Collins                                    elseif (substr($s, -1) == '%') {
20318e323fdSJames Collins                                        $i = substr($s, 0, -1);
20418e323fdSJames Collins                                        $s = '%';
20518e323fdSJames Collins                                    }
20618e323fdSJames Collins                                    else {
20718e323fdSJames Collins                                        if($s != 'auto') {
20818e323fdSJames Collins                                            $i = filter_var($s, FILTER_VALIDATE_INT);
20918e323fdSJames Collins                                            if ($i === '') $i = '1';
21018e323fdSJames Collins                                            if ($i != 0) {
21118e323fdSJames Collins                                                $s = 'rem';
21218e323fdSJames Collins                                            } else {
21318e323fdSJames Collins                                                $s = '';
21418e323fdSJames Collins                                            }
21518e323fdSJames Collins                                        }
21618e323fdSJames Collins                                    }
21718e323fdSJames Collins
21818e323fdSJames Collins                                    $part = $i . $s;
21918e323fdSJames Collins                                }
22018e323fdSJames Collins
22118e323fdSJames Collins                                $optionsCleaned[$syntaxKey] = implode(' ' , $parts);
22218e323fdSJames Collins                                break;
2237935713eSJames Collins                            case 'color':
2247935713eSJames Collins                                if (strlen($optionValue) == 3 || strlen($optionValue) == 6) {
2257935713eSJames Collins                                    preg_match('/([[:xdigit:]]{3}){1,2}/', $optionValue, $matches);
2267935713eSJames Collins                                    if (count($matches) > 1) {
2277935713eSJames Collins                                        $optionsCleaned[$syntaxKey] = '#' . $matches[0];
2287935713eSJames Collins                                    }
22917e6d639SJames Collins                                } else {
2307935713eSJames Collins                                    $optionsCleaned[$syntaxKey] = $optionValue;
23117e6d639SJames Collins                                }
2327935713eSJames Collins                                break;
2337935713eSJames Collins                            case 'url':
2347935713eSJames Collins                                $optionsCleaned[$syntaxKey] = $this->buildLink($optionValue);
2357935713eSJames Collins                                break;
2367935713eSJames Collins                            case 'media':
2377935713eSJames Collins                                $optionsCleaned[$syntaxKey] = $this->buildMediaLink($optionValue);
2387935713eSJames Collins                                break;
2397935713eSJames Collins                            case 'choice':
2407935713eSJames Collins                                if (array_key_exists('data', $options[$syntaxKey])) {
2417935713eSJames Collins                                    foreach ($options[$syntaxKey]['data'] as $choiceKey => $choiceValue) {
24218e323fdSJames Collins                                        if (strcasecmp($optionValue, $choiceKey) == 0) {
24318e323fdSJames Collins                                            $optionsCleaned[$syntaxKey] = $choiceKey;
24418e323fdSJames Collins                                            break;
24518e323fdSJames Collins                                        }
24618e323fdSJames Collins
2477935713eSJames Collins                                        if (is_array($choiceValue)) {
2487935713eSJames Collins                                            foreach ($choiceValue as $choiceItem) {
2497935713eSJames Collins                                                if (strcasecmp($optionValue, $choiceItem) == 0) {
2507935713eSJames Collins                                                    $optionsCleaned[$syntaxKey] = $choiceKey;
2517935713eSJames Collins                                                    break 2;
25217e6d639SJames Collins                                                }
25317e6d639SJames Collins                                            }
254ebb7bc5aSJames Collins                                        } else {
2557935713eSJames Collins                                            if (strcasecmp($optionValue, $choiceValue) == 0) {
2567935713eSJames Collins                                                $optionsCleaned[$syntaxKey] = $choiceValue;
2577935713eSJames Collins                                                break;
2587935713eSJames Collins                                            }
2597935713eSJames Collins                                        }
2607935713eSJames Collins                                    }
2617935713eSJames Collins                                }
2627935713eSJames Collins                                break;
2637935713eSJames Collins                            case 'set':
2647935713eSJames Collins                                if (array_key_exists('option', $options[$syntaxKey]) && array_key_exists('data', $options[$syntaxKey])) {
2657935713eSJames Collins                                    $optionsCleaned[$options[$syntaxKey]['option']] = $options[$syntaxKey]['data'];
2667935713eSJames Collins                                }
2677935713eSJames Collins                                break;
2687935713eSJames Collins                        }
269ebb7bc5aSJames Collins                    }
27017e6d639SJames Collins
2717935713eSJames Collins                    break;
2727935713eSJames Collins                } else {
2737935713eSJames Collins                    if (array_key_exists('type', $options[$syntaxKey]) && $options[$syntaxKey]['type'] == 'choice' && array_key_exists('data', $options[$syntaxKey])) {
2747935713eSJames Collins                        foreach ($options[$syntaxKey]['data'] as $choiceKey => $choiceValue) {
2757935713eSJames Collins                            if (is_array($choiceValue)) {
2767935713eSJames Collins                                foreach ($choiceValue as $choiceItem) {
2777935713eSJames Collins                                    if (strcasecmp($optionKey, $choiceItem) == 0) {
2787935713eSJames Collins                                        $optionsCleaned[$syntaxKey] = $choiceKey;
2797935713eSJames Collins                                        break 2;
2807935713eSJames Collins                                    }
2817935713eSJames Collins                                }
2827935713eSJames Collins                            } else {
2837935713eSJames Collins                                if (strcasecmp($optionKey, $choiceValue) == 0) {
2847935713eSJames Collins                                    $optionsCleaned[$syntaxKey] = $choiceValue;
2857935713eSJames Collins                                    break;
2867935713eSJames Collins                                }
2877935713eSJames Collins                            }
2887935713eSJames Collins                        }
2897935713eSJames Collins                    }
2907935713eSJames Collins                }
2917935713eSJames Collins            }
29217e6d639SJames Collins        }
29317e6d639SJames Collins
2947935713eSJames Collins        // Add in syntax options that are missing
2957935713eSJames Collins        foreach ($options as $optionKey => $optionValue) {
2967935713eSJames Collins            if (!array_key_exists($optionKey, $optionsCleaned)) {
2977935713eSJames Collins                if (array_key_exists('default', $options[$optionKey])) {
2987935713eSJames Collins                    switch ($options[$optionKey]['type']) {
2997935713eSJames Collins                        case 'boolean':
3007935713eSJames Collins                            $optionsCleaned[$optionKey] = filter_var($options[$optionKey]['default'], FILTER_VALIDATE_BOOLEAN);
3017935713eSJames Collins                            break;
3027935713eSJames Collins                        case 'number':
3037935713eSJames Collins                            $optionsCleaned[$optionKey] = filter_var($options[$optionKey]['default'], FILTER_VALIDATE_INT);
3047935713eSJames Collins                            break;
3057935713eSJames Collins                        default:
3067935713eSJames Collins                            $optionsCleaned[$optionKey] = $options[$optionKey]['default'];
3077935713eSJames Collins                            break;
3087935713eSJames Collins                    }
3097935713eSJames Collins                }
3107935713eSJames Collins            }
31117e6d639SJames Collins        }
31217e6d639SJames Collins
3137935713eSJames Collins        return $optionsCleaned;
31417e6d639SJames Collins    }
31517e6d639SJames Collins
3167935713eSJames Collins    /* Lexer renderers */
3177935713eSJames Collins    protected function render_lexer_enter(Doku_Renderer $renderer, $data) { }
3187935713eSJames Collins    protected function render_lexer_unmatched(Doku_Renderer $renderer, $data) { $renderer->doc .= $renderer->_xmlEntities($data); }
3197935713eSJames Collins    protected function render_lexer_exit(Doku_Renderer $renderer, $data) { }
3207935713eSJames Collins    protected function render_lexer_special(Doku_Renderer $renderer, $data) { }
3217935713eSJames Collins    protected function render_lexer_match(Doku_Renderer $renderer, $data) { }
32217e6d639SJames Collins
3237935713eSJames Collins    /* Renderer */
3247935713eSJames Collins    public function render($mode, Doku_Renderer $renderer, $data)
3257935713eSJames Collins    {
32617e6d639SJames Collins        if ($mode == 'xhtml') {
32717e6d639SJames Collins            list($state, $match) = $data;
32817e6d639SJames Collins
32917e6d639SJames Collins            switch ($state) {
33017e6d639SJames Collins                case DOKU_LEXER_ENTER:
33117e6d639SJames Collins                    $this->render_lexer_enter($renderer, $match);
33217e6d639SJames Collins                    return true;
33317e6d639SJames Collins
33417e6d639SJames Collins                case DOKU_LEXER_UNMATCHED:
33517e6d639SJames Collins                    $this->render_lexer_unmatched($renderer, $match);
33617e6d639SJames Collins                    return true;
33717e6d639SJames Collins
3383deaf3a5SJames Collins                case DOKU_LEXER_MATCHED:
3393deaf3a5SJames Collins                    $this->render_lexer_match($renderer, $match);
3403deaf3a5SJames Collins                    return true;
3413deaf3a5SJames Collins
34217e6d639SJames Collins                case DOKU_LEXER_EXIT:
34317e6d639SJames Collins                    $this->render_lexer_exit($renderer, $match);
34417e6d639SJames Collins                    return true;
34517e6d639SJames Collins
34617e6d639SJames Collins                case DOKU_LEXER_SPECIAL:
34717e6d639SJames Collins                    $this->render_lexer_special($renderer, $match);
34817e6d639SJames Collins                    return true;
34917e6d639SJames Collins            }
35017e6d639SJames Collins
35117e6d639SJames Collins            return true;
35217e6d639SJames Collins        }
35317e6d639SJames Collins
35417e6d639SJames Collins        return false;
35517e6d639SJames Collins    }
35617e6d639SJames Collins
3577935713eSJames Collins    /*
3587935713eSJames Collins    * return a class list with mikiop- prefix
3597935713eSJames Collins    *
3607935713eSJames Collins    * @param $options       options of syntax element. Options with key 'class'=true are automatically added
3617935713eSJames Collins    * @param $classes       classes to build from options as array
3627935713eSJames Collins    * @param $inclAttr      include class="" in the return string
3639d56a2c2SJames Collins    * @param $optionsTemplate   allow a different options template instead of $this->options (for findTags)
3647935713eSJames Collins    * @return               a string of classes from options/classes variable
3657935713eSJames Collins    */
3669d56a2c2SJames Collins    public function buildClass($options = null, $classes = null, $inclAttr = false, $optionsTemplate = null)
3677935713eSJames Collins    {
36817e6d639SJames Collins        $s = array();
36917e6d639SJames Collins
3707935713eSJames Collins        if (is_array($options)) {
3717935713eSJames Collins            if($classes == null) $classes = array();
3729d56a2c2SJames Collins            if($optionsTemplate == null) $optionsTemplate = $this->options;
37317e6d639SJames Collins
3749d56a2c2SJames Collins            foreach($optionsTemplate as $key => $value) {
3757935713eSJames Collins                if(array_key_exists('class', $value) && $value['class'] == TRUE) {
3767935713eSJames Collins                    array_push($classes, $key);
37717e6d639SJames Collins                }
37817e6d639SJames Collins            }
37917e6d639SJames Collins
3807935713eSJames Collins            foreach ($classes as $class) {
3817935713eSJames Collins                if (array_key_exists($class, $options) && $options[$class] !== FALSE && $options[$class] != '') {
3827935713eSJames Collins                    $prefix = $this->classPrefix;
3837935713eSJames Collins
3849d56a2c2SJames Collins                    if (array_key_exists($class, $optionsTemplate) && array_key_exists('prefix', $optionsTemplate[$class])) {
3859d56a2c2SJames Collins                        $prefix .= $optionsTemplate[$class]['prefix'];
38617e6d639SJames Collins                    }
3877935713eSJames Collins
3882f5b9ce6SJames Collins                    if (array_key_exists($class, $optionsTemplate) && array_key_exists('classNoSuffix', $optionsTemplate[$class]) && $optionsTemplate[$class]['classNoSuffix'] == TRUE) {
3892f5b9ce6SJames Collins                        $s[] = $prefix . $class;
3902f5b9ce6SJames Collins                    } else {
3917935713eSJames Collins                        $s[] = $prefix . $class . ($options[$class] !== TRUE ? '-' . $options[$class] : '');
39217e6d639SJames Collins                    }
39317e6d639SJames Collins                }
3942f5b9ce6SJames Collins            }
39517e6d639SJames Collins
396a007b54fSJames Collins        }
39717e6d639SJames Collins
3987935713eSJames Collins        $s = implode(' ', $s);
3997935713eSJames Collins        if($s != '') $s = ' ' . $s;
4008f786230SJames Collins
4017935713eSJames Collins        if($inclAttr) $s = ' classes="' . $s . '"';
4026cfe6dadSJames Collins
403ad1dae96SJames Collins        return $s;
404ad1dae96SJames Collins    }
40517e6d639SJames Collins
4067935713eSJames Collins
4077935713eSJames Collins
4087935713eSJames Collins
4097935713eSJames Collins    /*
4107935713eSJames Collins    * build style string
4117935713eSJames Collins    *
4127935713eSJames Collins    * @param $list          style list as key => value. Empty values are not included
4137935713eSJames Collins    * @param $inclAttr      include style="" in the return string
4147935713eSJames Collins    * @return               style list string
4157935713eSJames Collins    */
4167935713eSJames Collins    public function buildStyle($list, $inclAttr = false)
4177935713eSJames Collins    {
4187935713eSJames Collins        $s = '';
4197935713eSJames Collins
4207935713eSJames Collins        if (is_array($list) && count($list) > 0) {
4217935713eSJames Collins            foreach ($list as $key => $value) {
4227935713eSJames Collins                if($value != '') {
4237935713eSJames Collins                    $s .= $key . ':' . $value . ';';
4247935713eSJames Collins                }
4257935713eSJames Collins            }
4267935713eSJames Collins        }
4277935713eSJames Collins
4287935713eSJames Collins        if($s != '' && $inclAttr) {
4297935713eSJames Collins            $s = ' style="' . $s . '"';
4307935713eSJames Collins        }
4317935713eSJames Collins
4327935713eSJames Collins        return $s;
4337935713eSJames Collins    }
4347935713eSJames Collins
4357935713eSJames Collins
4367935713eSJames Collins    public function buildTooltipString($options)
4377935713eSJames Collins    {
438a401c3b7SJames Collins        $dataPlacement = 'top';
439a401c3b7SJames Collins        $dataHtml = false;
440a401c3b7SJames Collins        $title = '';
441a401c3b7SJames Collins
442a401c3b7SJames Collins        if ($options != null) {
443a401c3b7SJames Collins            if (array_key_exists('tooltip-html-top', $options) && $options['tooltip-html-top'] != '') {
444a401c3b7SJames Collins                $title = $options['tooltip-html-top'];
445a401c3b7SJames Collins                $dataPlacement = 'top';
446a401c3b7SJames Collins            }
447a401c3b7SJames Collins
448a401c3b7SJames Collins            if (array_key_exists('tooltip-html-left', $options) && $options['tooltip-html-left'] != '') {
449a401c3b7SJames Collins                $title = $options['tooltip-html-left'];
450a401c3b7SJames Collins                $dataPlacement = 'left';
451a401c3b7SJames Collins            }
452a401c3b7SJames Collins
453a401c3b7SJames Collins            if (array_key_exists('tooltip-html-bottom', $options) && $options['tooltip-html-bottom'] != '') {
454a401c3b7SJames Collins                $title = $options['tooltip-html-bottom'];
455a401c3b7SJames Collins                $dataPlacement = 'bottom';
456a401c3b7SJames Collins            }
457a401c3b7SJames Collins
458a401c3b7SJames Collins            if (array_key_exists('tooltip-html-right', $options) && $options['tooltip-html-right'] != '') {
459a401c3b7SJames Collins                $title = $options['tooltip-html-right'];
460a401c3b7SJames Collins                $dataPlacement = 'right';
461a401c3b7SJames Collins            }
462a401c3b7SJames Collins
463a401c3b7SJames Collins            if (array_key_exists('tooltip-top', $options) && $options['tooltip-top'] != '') {
464a401c3b7SJames Collins                $title = $options['tooltip-top'];
465a401c3b7SJames Collins                $dataPlacement = 'top';
466a401c3b7SJames Collins            }
467a401c3b7SJames Collins
468a401c3b7SJames Collins            if (array_key_exists('tooltip-left', $options) && $options['tooltip-left'] != '') {
469a401c3b7SJames Collins                $title = $options['tooltip-left'];
470a401c3b7SJames Collins                $dataPlacement = 'left';
471a401c3b7SJames Collins            }
472a401c3b7SJames Collins
473a401c3b7SJames Collins            if (array_key_exists('tooltip-bottom', $options) && $options['tooltip-bottom'] != '') {
474a401c3b7SJames Collins                $title = $options['tooltip-bottom'];
475a401c3b7SJames Collins                $dataPlacement = 'bottom';
476a401c3b7SJames Collins            }
477a401c3b7SJames Collins
478a401c3b7SJames Collins            if (array_key_exists('tooltip-right', $options) && $options['tooltip-right'] != '') {
479a401c3b7SJames Collins                $title = $options['tooltip-right'];
480a401c3b7SJames Collins                $dataPlacement = 'right';
481a401c3b7SJames Collins            }
482a401c3b7SJames Collins
483a401c3b7SJames Collins            if (array_key_exists('tooltip-html', $options) && $options['tooltip-html'] != '') {
484a401c3b7SJames Collins                $title = $options['tooltip-html'];
485a401c3b7SJames Collins                $dataPlacement = 'top';
486a401c3b7SJames Collins            }
487a401c3b7SJames Collins
488a401c3b7SJames Collins            if (array_key_exists('tooltip', $options) && $options['tooltip'] != '') {
489a401c3b7SJames Collins                $title = $options['tooltip'];
490a401c3b7SJames Collins                $dataPlacement = 'top';
491a401c3b7SJames Collins            }
492a401c3b7SJames Collins        }
493a401c3b7SJames Collins
494a401c3b7SJames Collins        if ($title != '') {
495a401c3b7SJames Collins            return ' data-toggle="tooltip" data-placement="' . $dataPlacement . '" ' . ($dataHtml == true ? 'data-html="true" ' : '') . 'title="' . $title . '" ';
496a401c3b7SJames Collins        }
497a401c3b7SJames Collins
498a401c3b7SJames Collins        return '';
499a401c3b7SJames Collins    }
500a401c3b7SJames Collins
5017935713eSJames Collins    /*
5027935713eSJames Collins    * convert the URL to a DokuWiki media link (if required)
5037935713eSJames Collins    *
5047935713eSJames Collins    * @param $url   url to parse
5057935713eSJames Collins    * @return       url string
5067935713eSJames Collins    */
5077935713eSJames Collins    public function buildMediaLink($url)
5087935713eSJames Collins    {
5097935713eSJames Collins        $i = strpos($url, '?');
5107935713eSJames Collins        if ($i !== FALSE) $url = substr($url, 0, $i);
51117e6d639SJames Collins
51266f3b00dSJames Collins        $url = preg_replace('/[^\da-zA-Z:_.-]+/', '', $url);
51317e6d639SJames Collins
5147935713eSJames Collins        return (tpl_getMediaFile(array($url), FALSE));
51517e6d639SJames Collins    }
51617e6d639SJames Collins
51717e6d639SJames Collins
5187935713eSJames Collins    /*
5197935713eSJames Collins    * returns either a url or dokuwiki link
5207935713eSJames Collins    *
5217935713eSJames Collins    * @param    $url    link to build from
5227935713eSJames Collins    * @return           built link
5237935713eSJames Collins    */
5247935713eSJames Collins    public function buildLink($url)
5257935713eSJames Collins    {
5267935713eSJames Collins        $i = strpos($url, '://');
52721a27edbSJames Collins        if ($i !== FALSE || substr($url, 0, 1) == '#') return $url;
528f1a539d8SJames Collins
5297935713eSJames Collins        return wl($url);
530f1a539d8SJames Collins    }
531f1a539d8SJames Collins
5327935713eSJames Collins    /*
5337935713eSJames Collins    * Call syntax renderer of mikio syntax plugin
5347935713eSJames Collins    *
5357935713eSJames Collins    * @param $renderer          DokuWiki renderer object
5367935713eSJames Collins    * @param $className         mikio syntax class to call
5377935713eSJames Collins    * @param $text              unmatched text to pass outside of lexer. Only used when $lexer=MIKIO_LEXER_AUTO
5387935713eSJames Collins    * @param $data              tag options to pass to syntax class. Runs through cleanOptions to validate first
5397935713eSJames Collins    * @param $lexer             which lexer to call
5407935713eSJames Collins    */
5417935713eSJames Collins    public function syntaxRender(Doku_Renderer $renderer, $className, $text, $data = null, $lexer = MIKIO_LEXER_AUTO)
5427935713eSJames Collins    {
5437935713eSJames Collins        $className = 'syntax_plugin_mikioplugin_'.$className;
5447935713eSJames Collins
5457935713eSJames Collins        if(class_exists($className)) {
54617e6d639SJames Collins            $class = new $className;
54717e6d639SJames Collins
54831359b6fSJames Collins            if(!is_array($data)) $data = array();
54931359b6fSJames Collins
55018e323fdSJames Collins
5517935713eSJames Collins            if(count($class->options) > 0) {
55218e323fdSJames Collins                $data = $class->cleanOptions($data, $class->options);
5537935713eSJames Collins            }
55431359b6fSJames Collins
5557935713eSJames Collins            switch($lexer) {
5567935713eSJames Collins                case MIKIO_LEXER_AUTO:
5577935713eSJames Collins                    if ($class->hasEndTag) {
5587935713eSJames Collins                        if(method_exists($class, 'render_lexer_enter')) $class->render_lexer_enter($renderer, $data);
55917e6d639SJames Collins                        $renderer->doc .= $text;
5607935713eSJames Collins                        if(method_exists($class, 'render_lexer_exit')) $class->render_lexer_exit($renderer, $data);
5617935713eSJames Collins                    } else {
5627935713eSJames Collins                        if(method_exists($class, 'render_lexer_special')) $class->render_lexer_special($renderer, $data);
5637935713eSJames Collins                    }
5647935713eSJames Collins
5657935713eSJames Collins                    break;
5667935713eSJames Collins                case MIKIO_LEXER_ENTER:
5677935713eSJames Collins                    if(method_exists($class, 'render_lexer_enter')) $class->render_lexer_enter($renderer, $data);
5687935713eSJames Collins                    break;
5697935713eSJames Collins                case MIKIO_LEXER_EXIT:
5707935713eSJames Collins                    if(method_exists($class, 'render_lexer_exit')) $class->render_lexer_exit($renderer, $data);
5717935713eSJames Collins                    break;
5727935713eSJames Collins                case MIKIO_LEXER_SPECIAL:
5737935713eSJames Collins                    if(method_exists($class, 'render_lexer_special')) $class->render_lexer_special($renderer, $data);
5747935713eSJames Collins                    break;
5757935713eSJames Collins            }
57617e6d639SJames Collins        }
57717e6d639SJames Collins    }
578ebb7bc5aSJames Collins
5792f5b9ce6SJames Collins
58018e323fdSJames Collins    protected function callMikioTag($className, $data) {
58118e323fdSJames Collins        // $className = 'syntax_plugin_mikioplugin_'.$className;
5822f5b9ce6SJames Collins
5832f5b9ce6SJames Collins
58418e323fdSJames Collins        // if(class_exists($className)) {
58518e323fdSJames Collins            //$class = new $className;
58618e323fdSJames Collins            if(!plugin_isdisabled('mikioplugin')) {
58718e323fdSJames Collins                $class = plugin_load('syntax', 'mikioplugin_' . $className);
58818e323fdSJames Collins                // echo '^^'.$className.'^^';
58918e323fdSJames Collins
59018e323fdSJames Collins
59118e323fdSJames Collins                if(method_exists($class, 'mikioCall')) return $class->mikioCall($data);
59218e323fdSJames Collins
5932f5b9ce6SJames Collins            }
5942f5b9ce6SJames Collins
59518e323fdSJames Collins        // }
59618e323fdSJames Collins
5972f5b9ce6SJames Collins        return '';
5982f5b9ce6SJames Collins    }
5992f5b9ce6SJames Collins
6002f5b9ce6SJames Collins
601f003e4a8SJames Collins    protected function callMikioOptionDefault($className, $option) {
602f003e4a8SJames Collins        $className = 'syntax_plugin_mikioplugin_'.$className;
603f003e4a8SJames Collins
604f003e4a8SJames Collins        if(class_exists($className)) {
605f003e4a8SJames Collins            $class = new $className;
606f003e4a8SJames Collins
607f003e4a8SJames Collins            if(array_key_exists($option, $class->options) && array_key_exists('default', $class->options[$option])) {
608f003e4a8SJames Collins                return $class->options[$option]['default'];
609f003e4a8SJames Collins            }
610f003e4a8SJames Collins        }
611f003e4a8SJames Collins
612f003e4a8SJames Collins        return '';
613f003e4a8SJames Collins    }
614f003e4a8SJames Collins
615f003e4a8SJames Collins
6162f5b9ce6SJames Collins    protected function buildTooltip($text) {
6172f5b9ce6SJames Collins        if($text != '') {
6182f5b9ce6SJames Collins            return ' data-tooltip="' . $text . '"';
6192f5b9ce6SJames Collins        }
6202f5b9ce6SJames Collins
6212f5b9ce6SJames Collins        return '';
6222f5b9ce6SJames Collins    }
6232f5b9ce6SJames Collins
6247935713eSJames Collins    /*
6257935713eSJames Collins    * Create array with passed elements and include them if their values are not empty
6267935713eSJames Collins    *
6277935713eSJames Collins    * @param ...        array items
6287935713eSJames Collins    */
6297935713eSJames Collins    protected function arrayRemoveEmpties($items) {
6307935713eSJames Collins        $result = array();
6317935713eSJames Collins
6327935713eSJames Collins        foreach($items as $key => $value) {
6337935713eSJames Collins            if($value != '') {
6347935713eSJames Collins                $result[$key] = $value;
6357935713eSJames Collins            }
6367935713eSJames Collins        }
6377935713eSJames Collins
6387935713eSJames Collins        return $result;
6397935713eSJames Collins    }
6407935713eSJames Collins
6417935713eSJames Collins    public function getFirstArrayKey($data)
6427935713eSJames Collins    {
643ebb7bc5aSJames Collins        if (!function_exists('array_key_first')) {
644ebb7bc5aSJames Collins            foreach ($data as $key => $unused) {
645ebb7bc5aSJames Collins                return $key;
646ebb7bc5aSJames Collins            }
647ebb7bc5aSJames Collins        }
648ebb7bc5aSJames Collins
649ebb7bc5aSJames Collins        return array_key_first($data);
650ebb7bc5aSJames Collins    }
6517935713eSJames Collins
6527935713eSJames Collins
6537935713eSJames Collins    /*
6547935713eSJames Collins    * add common options to options
6557935713eSJames Collins    *
6567935713eSJames Collins    * @param $typelist      common option to add
6577935713eSJames Collins    * @param $options   save in options
6587935713eSJames Collins    */
6597935713eSJames Collins    public function addCommonOptions($typelist) {
6607935713eSJames Collins        $types = explode(' ', $typelist);
6617935713eSJames Collins        foreach($types as $type) {
6627935713eSJames Collins            if(strcasecmp($type, 'shadow') == 0) {
6637935713eSJames Collins                $this->options['shadow'] =          array('type'     => 'choice',
6647935713eSJames Collins                                                          'data'     => array('large'=> array('shadow-large', 'shadow-lg'), 'small' => array('shadow-small', 'shadow-sm'), true),
6657935713eSJames Collins                                                          'default'  => '',
6667935713eSJames Collins                                                          'class'    => true);
6677935713eSJames Collins            }
6687935713eSJames Collins
6697935713eSJames Collins            if(strcasecmp($type, 'width') == 0) {
6707935713eSJames Collins                $this->options['width'] =           array('type'     => 'size',
6717935713eSJames Collins                                                          'default'  => '');
6727935713eSJames Collins            }
6737935713eSJames Collins
6747935713eSJames Collins            if(strcasecmp($type, 'height') == 0) {
6757935713eSJames Collins                $this->options['height'] =          array('type'     => 'size',
6767935713eSJames Collins                                                          'default'  => '');
6777935713eSJames Collins            }
6787935713eSJames Collins
67918e323fdSJames Collins            if(strcasecmp($type, 'text-color') == 0) {
68018e323fdSJames Collins                $this->options['text-color'] =          array('type'      => 'color',
68118e323fdSJames Collins                                                          'default'  => '');
68218e323fdSJames Collins            }
68318e323fdSJames Collins
6847935713eSJames Collins            if(strcasecmp($type, 'type') == 0) {
685*358ba801SJames Collins                $this->options['type'] =            array('type'     => 'text',
686*358ba801SJames Collins                                                          // 'data'     => array('primary', 'secondary', 'success', 'danger', 'warning', 'info', 'light', 'dark'),
6877935713eSJames Collins                                                          'default'  => '',
6887935713eSJames Collins                                                          'class'    => true);
6897935713eSJames Collins            }
6907935713eSJames Collins
6917935713eSJames Collins            if(strcasecmp($type, 'text-align') == 0) {
6927935713eSJames Collins                $this->options['text-align'] =      array('type'     => 'choice',
6937935713eSJames Collins                                                          'data'     => array('left' => array('text-left'), 'center' => array('text-center'), 'right' => array('text-right')),
6947935713eSJames Collins                                                          'default'  => '',
6957935713eSJames Collins                                                          'class'    => true);
6967935713eSJames Collins            }
6977935713eSJames Collins
6987935713eSJames Collins            if(strcasecmp($type, 'align') == 0) {
6997935713eSJames Collins                $this->options['align'] =           array('type'     => 'choice',
7007935713eSJames Collins                                                          'data'     => array('left' => array('align-left'), 'center' => array('align-center'), 'right' => array('align-right')),
7017935713eSJames Collins                                                          'default'  => '',
7027935713eSJames Collins                                                          'class'    => true);
7037935713eSJames Collins            }
7042f5b9ce6SJames Collins
7052f5b9ce6SJames Collins            if(strcasecmp($type, 'tooltip') == 0) {
7062f5b9ce6SJames Collins                $this->options['tooltip'] =         array('type'     => 'text',
7072f5b9ce6SJames Collins                                                          'default'  => '',
7082f5b9ce6SJames Collins                                                          'class'    => true,
7092f5b9ce6SJames Collins                                                          'classNoSuffix'   => true);
7102f5b9ce6SJames Collins            }
71118e323fdSJames Collins
71218e323fdSJames Collins            if(strcasecmp($type, 'vertical-align') == 0) {
71318e323fdSJames Collins                $this->options['vertical-align'] =  array('type'    => 'choice',
71418e323fdSJames Collins                                                          'data'    => array('top' => array('align-top'), 'middle' => array('align-middle'), 'bottom' => array('align-bottom')),
71518e323fdSJames Collins                                                          'default' => '',
71618e323fdSJames Collins                                                          'class'   => true);
71718e323fdSJames Collins            }
71818e323fdSJames Collins
71918e323fdSJames Collins            if(strcasecmp($type, 'links-match') == 0) {
72018e323fdSJames Collins                $this->options['links-match'] =     array('type'    => 'boolean',
72118e323fdSJames Collins                                                          'default' => 'false',
72218e323fdSJames Collins                                                          'class'   => true);
72318e323fdSJames Collins            }
72418e323fdSJames Collins
7257935713eSJames Collins        }
7267935713eSJames Collins    }
7277935713eSJames Collins
7287935713eSJames Collins
7297935713eSJames Collins    /*
7307935713eSJames Collins    * Find HTML tags in string. Parse tags options. Used in parsing subtags
7317935713eSJames Collins    *
7327935713eSJames Collins    * @param $tagName       tagName to search for. Name is exclusive
7337935713eSJames Collins    * @param $content       search within content
7347935713eSJames Collins    * @param $options       parse options similar to syntax element options
735f0df6cccSJames Collins    * @param $hasEndTag     tagName search also looks for an end tag
7367935713eSJames Collins    * @return               array of tags containing 'options' => array of 'name' => 'value', 'content' => content inside the tag
7377935713eSJames Collins    */
738f0df6cccSJames Collins    protected function findTags($tagName, $content, $options, $hasEndTag = true) {
7397935713eSJames Collins        $items = array();
740f0df6cccSJames Collins        $search = '/<(?i:' . $tagName . ')(.*?)>(.*?)<\/(?i:' . $tagName . ')>/s';
7417935713eSJames Collins
742f0df6cccSJames Collins        if(!$hasEndTag) {
743f0df6cccSJames Collins            $search = '/<(?i:' . $tagName . ')(.*?)>/s';
744f0df6cccSJames Collins        }
745f0df6cccSJames Collins
746f0df6cccSJames Collins        if(preg_match_all($search, $content, $match)) {
7477935713eSJames Collins            if(count($match) >= 2) {
7487935713eSJames Collins                for($i = 0; $i < count($match[1]); $i++) {
7497935713eSJames Collins                    $item = array('options' => array(), 'content' => $this->render_text($match[2][$i]));
7507935713eSJames Collins
7517935713eSJames Collins                    $optionlist = preg_split('/\s(?=([^"]*"[^"]*")*[^"]*$)/', trim($match[1][$i]));
7527935713eSJames Collins
7537935713eSJames Collins                    foreach ($optionlist as $option) {
7547935713eSJames Collins                        $j = strpos($option, '=');
7557935713eSJames Collins                        if ($j !== false) {
7567935713eSJames Collins                            $value = substr($option, $j + 1);
7577935713eSJames Collins
7587935713eSJames Collins                            if (substr($value, 0, 1) == '"') $value = substr($value, 1);
7597935713eSJames Collins                            if (substr($value, -1) == '"') $value = substr($value, 0, -1);
7607935713eSJames Collins
7617935713eSJames Collins                            $item['options'][substr($option, 0, $j)] = $value;
7627935713eSJames Collins                        } else {
7637935713eSJames Collins                            $item['options'][$option] = true;
7647935713eSJames Collins                        }
7657935713eSJames Collins                    }
7667935713eSJames Collins
7673cbf07a0SJames Collins                    $item['options'] = $this->cleanOptions($item['options'], $options);
7687935713eSJames Collins
7697935713eSJames Collins                    $items[] = $item;
7707935713eSJames Collins                }
7717935713eSJames Collins            }
7727935713eSJames Collins        }
7737935713eSJames Collins
7747935713eSJames Collins        return $items;
7757935713eSJames Collins    }
77631359b6fSJames Collins}