1<?php
2/**
3 * DokuWiki Plugin dwtimeline (Syntax Component)
4 *
5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
6 * @author  saggi <saggi@gmx.de>
7 */
8
9class syntax_plugin_dwtimeline_dwtimeline extends \dokuwiki\Extension\SyntaxPlugin
10{
11    /**
12     * Global direction memory
13     * @var
14     */
15    protected static $direction;
16    protected static $align;
17
18    /** @inheritDoc */
19    public function getType()
20    {
21        return 'substition';
22    }
23
24    /** @inheritDoc */
25    public function getPType()
26    {
27        return 'stack';
28    }
29
30    /** @inheritDoc */
31    public function getSort()
32    {
33        return 400;
34    }
35
36    /**
37     * Change the current content of $direction String (left,right)
38     * @param string $direction
39     * @return string
40     */
41    public function ChangeDirection(string $direction): string {
42        if($direction === 'tl-right'){
43            $direction = 'tl-left';
44        }
45        else {
46            $direction = 'tl-right';
47        }
48        return $direction;
49    }
50
51    public function GetDirection()
52    {
53        if (!self::$direction) {self::$direction = 'tl-'.$this->getConf('direction');}
54        return self::$direction;
55    }
56
57    /**
58     * Handle the match
59     * @param string $match The match of the syntax
60     * @param int $state The state of the handler
61     * @param int $pos The position in the document
62     * @param Doku_Handler $handler The handler
63     * @return array Data for the renderer
64     */
65    public function handle($match, $state, $pos, Doku_Handler $handler)
66    {
67        return array();
68    }
69
70    /**
71     * Create output
72     *
73     * @param string $mode string     output format being rendered
74     * @param Doku_Renderer $renderer the current renderer object
75     * @param array $data data created by handler()
76     * @return  boolean                 rendered correctly?
77     */
78    public function render($mode, Doku_Renderer $renderer, $data)
79    {
80        return false;
81    }
82
83    /**
84     * Match the options of a entity e.g. <dwtimeline opt1="value1" opt2="value2">
85     * @param string $match the cleaned option String: 'opt1="value1" opt2="value2"'
86     * @return array
87     */
88    public function getTitleMatches(string $match): array
89    {
90        $data[] = array();
91        $titles[] = array();
92        $data['align'] = self::$align; // Set Standard Alignment
93        $data['data'] = '';
94        $data['style'] = ' style="';
95        preg_match_all('/(?<title>\w+?\b=".*?")/',$match,$titles);
96        foreach ($titles['title'] as $title) {
97            $opttitle = explode('=',$title,2);
98            switch(trim($opttitle[0]))
99            {
100                case 'link':
101                    $data['link'] = self::getLink(trim($opttitle[1],' "'));
102                    break;
103                case 'data':
104                    $datapoint = hsc(substr(trim($opttitle[1],' "'),0,4));
105                    $data[$opttitle[0]] = ' data-point="' . $datapoint .  '" ';
106                    // Check if more than 2 signs present, if so set style for elliptic timeline marker
107                    if (strlen($datapoint) > 2) {
108                        $data['style'] .= '--4sizewidth: 50px; --4sizeright: -29px; --4sizesmallleft40: 60px; --4sizesmallleft50: 70px; --4sizesmallleft4: -10px; --4sizewidthhorz: 50px; --4sizerighthorz: -29px; ';
109                    }
110                    break;
111                case 'align':
112                    $data[$opttitle[0]] = self::checkValues(hsc(trim($opttitle[1],' "')),array('horz', 'vert') , self::$align);
113                    break;
114                case 'backcolor':
115                    if(!self::isValidColor(hsc(trim($opttitle[1],' "')))) { break;}
116                    $data['style'] .= 'background-color:' . self::isValidColor(hsc(trim($opttitle[1],' "'))) . '; ';
117                    break;
118                case 'style':
119                    // do not accept custom styles at the moment
120                    break;
121                default:
122                    $data[$opttitle[0]] = hsc(trim($opttitle[1],' "'));
123                    break;
124            }
125        }
126        // Clear $data['style'] if no special style needed
127        if ($data['style'] == ' style="') {
128            $data['style'] = '';
129        } else {
130            $data['style'] .= '"';
131        }
132        return $data;
133    }
134
135    /**
136     * Check and get the link from given DokuWiki Link
137     * @param string $linkToCheck
138     * @return string
139     */
140    public function getLink(string $linkToCheck): string
141    {
142        $pattern = '/\[\[(?<link>.+?)\]\]/';
143        $links = [];
144        preg_match_all($pattern, $linkToCheck,$links);
145        foreach ($links['link'] as $link) {
146            return hsc(substr($link,0,strpos($link,'|')));
147        }
148        return '';
149    }
150
151    public function checkValues($toCheck,$allowed,$standard)
152    {
153        if (in_array($toCheck, $allowed, true)) {
154            return $toCheck;
155        } else {
156            return $standard;
157        }
158    }
159
160    /**
161     * Validate color value $color
162     * this is cut price validation - only to ensure the basic format is correct and there is nothing harmful
163     * three basic formats  "colorname", "#fff[fff]", "rgb(255[%],255[%],255[%])"
164     */
165    Public function isValidColor($color)
166    {
167        $color = trim($color);
168        $color_names = array(
169            "AliceBlue",
170            "AntiqueWhite",
171            "Aqua",
172            "Aquamarine",
173            "Azure",
174            "Beige",
175            "Bisque",
176            "Black",
177            "BlanchedAlmond",
178            "Blue",
179            "BlueViolet",
180            "Brown",
181            "BurlyWood",
182            "CadetBlue",
183            "Chartreuse",
184            "Chocolate",
185            "Coral",
186            "CornflowerBlue",
187            "Cornsilk",
188            "Crimson",
189            "Cyan",
190            "DarkBlue",
191            "DarkCyan",
192            "DarkGoldenRod",
193            "DarkGray",
194            "DarkGrey",
195            "DarkGreen",
196            "DarkKhaki",
197            "DarkMagenta",
198            "DarkOliveGreen",
199            "DarkOrange",
200            "DarkOrchid",
201            "DarkRed",
202            "DarkSalmon",
203            "DarkSeaGreen",
204            "DarkSlateBlue",
205            "DarkSlateGray",
206            "DarkSlateGrey",
207            "DarkTurquoise",
208            "DarkViolet",
209            "DeepPink",
210            "DeepSkyBlue",
211            "DimGray",
212            "DimGrey",
213            "DodgerBlue",
214            "FireBrick",
215            "FloralWhite",
216            "ForestGreen",
217            "Fuchsia",
218            "Gainsboro",
219            "GhostWhite",
220            "Gold",
221            "GoldenRod",
222            "Gray",
223            "Grey",
224            "Green",
225            "GreenYellow",
226            "HoneyDew",
227            "HotPink",
228            "IndianRed",
229            "Indigo",
230            "Ivory",
231            "Khaki",
232            "Lavender",
233            "LavenderBlush",
234            "LawnGreen",
235            "LemonChiffon",
236            "LightBlue",
237            "LightCoral",
238            "LightCyan",
239            "LightGoldenRodYellow",
240            "LightGray",
241            "LightGrey",
242            "LightGreen",
243            "LightPink",
244            "LightSalmon",
245            "LightSeaGreen",
246            "LightSkyBlue",
247            "LightSlateGray",
248            "LightSlateGrey",
249            "LightSteelBlue",
250            "LightYellow",
251            "Lime",
252            "LimeGreen",
253            "Linen",
254            "Magenta",
255            "Maroon",
256            "MediumAquaMarine",
257            "MediumBlue",
258            "MediumOrchid",
259            "MediumPurple",
260            "MediumSeaGreen",
261            "MediumSlateBlue",
262            "MediumSpringGreen",
263            "MediumTurquoise",
264            "MediumVioletRed",
265            "MidnightBlue",
266            "MintCream",
267            "MistyRose",
268            "Moccasin",
269            "NavajoWhite",
270            "Navy",
271            "OldLace",
272            "Olive",
273            "OliveDrab",
274            "Orange",
275            "OrangeRed",
276            "Orchid",
277            "PaleGoldenRod",
278            "PaleGreen",
279            "PaleTurquoise",
280            "PaleVioletRed",
281            "PapayaWhip",
282            "PeachPuff",
283            "Peru",
284            "Pink",
285            "Plum",
286            "PowderBlue",
287            "Purple",
288            "RebeccaPurple",
289            "Red",
290            "RosyBrown",
291            "RoyalBlue",
292            "SaddleBrown",
293            "Salmon",
294            "SandyBrown",
295            "SeaGreen",
296            "SeaShell",
297            "Sienna",
298            "Silver",
299            "SkyBlue",
300            "SlateBlue",
301            "SlateGray",
302            "SlateGrey",
303            "Snow",
304            "SpringGreen",
305            "SteelBlue",
306            "Tan",
307            "Teal",
308            "Thistle",
309            "Tomato",
310            "Turquoise",
311            "Violet",
312            "Wheat",
313            "White",
314            "WhiteSmoke",
315            "Yellow",
316            "YellowGreen"
317        );
318
319        if (in_array(strtolower($color), array_map('strtolower',$color_names))) {
320            return trim($color);
321        }
322
323        $pattern = "/^\s*(
324            (\#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}))|        #colorvalue
325            (rgb\(([0-9]{1,3}%?,){2}[0-9]{1,3}%?\))     #rgb triplet
326            )\s*$/x";
327
328        if (preg_match($pattern, $color)) {
329            return trim($color);
330        }
331
332        return false;
333    }
334
335}
336
337