1<?php
2/**
3 * Plugin nspages : Displays nicely a list of the pages of a namespace
4 *
5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
6 * @author  Guillaume Turri <guillaume.turri@gmail.com>
7 */
8
9use dokuwiki\Utf8\PhpString;
10
11if(!defined('DOKU_INC')) die();
12
13class optionParser {
14
15    static function checkRegEx(&$match, $pattern, &$arrayAffected) {
16        optionParser::preg_match_all_wrapper($pattern, $match, $found);
17        foreach($found as $regex) {
18            $arrayAffected[] = $regex[1];
19            $match           = optionParser::_removeFromMatch($regex[0], $match);
20        }
21    }
22
23    /**
24     * Check if a given option has been given, and remove it from the initial string
25     *
26     * @param string $match The string match by the plugin
27     * @param string $pattern The pattern which activate the option
28     * @param mixed  $varAffected The variable which will memorise the option
29     * @param mixed  $valIfFound the value affected to the previous variable if the option is found
30     */
31    static function checkOption(&$match, $pattern, &$varAffected, $valIfFound) {
32        if(optionParser::preg_match_wrapper($pattern, $match, $found)) {
33            $varAffected = $valIfFound;
34            $match       = optionParser::_removeFromMatch($found[0], $match);
35        }
36    }
37
38    static function checkRecurse(&$match, &$varAffected){
39        if(optionParser::preg_match_wrapper('r *=? *\"?([[:digit:]]*)\"?', $match, $found)) {
40            if($found[1] != '') {
41                $varAffected = (int) $found[1];
42            } else {
43                $varAffected = 0; //no limit
44            }
45            $match = optionParser::_removeFromMatch($found[0], $match);
46        }
47    }
48
49    static function checkNbColumns(&$match, &$varAffected){
50        if(optionParser::preg_match_wrapper("nb?Cols? *=? *\"?([[:digit:]]*)\"?", $match, $found)) {
51            if($found[1] != '') {
52                $varAffected = max((int) $found[1], 1);
53            }
54            $match = optionParser::_removeFromMatch($found[0], $match);
55        }
56    }
57
58    static function checkNbItemsMax(&$match, &$varAffected){
59        if(optionParser::preg_match_wrapper("nb?Items?Max *=? *\"?([[:digit:]]*)\"?", $match, $found)) {
60            if($found[1] != '') {
61                $varAffected = max((int) $found[1], 1);
62            }
63            $match = optionParser::_removeFromMatch($found[0], $match);
64        }
65    }
66
67    static function checkAnchorName(&$match, &$varAffected){
68        if(optionParser::preg_match_wrapper("anchorName *=? *\"?([[:alnum:]]+)\"?", $match, $found)) {
69            $varAffected = $found[1];
70            $match = optionParser::_removeFromMatch($found[0], $match);
71        }
72    }
73
74    static function checkSimpleStringArgument(&$match, &$varAffected, $plugin, $argumentName){
75        if(optionParser::preg_match_wrapper($argumentName . " *= *\"([^\"]*)\"", $match, $found)) {
76            $varAffected = $found[1];
77            $match       = optionParser::_removeFromMatch($found[0], $match);
78        } else {
79            $varAffected = null;
80        }
81    }
82
83    static function checkDictOrder(&$match, &$varAffected, $plugin){
84        if(optionParser::preg_match_wrapper("dict(?:ionary)?Order *= *\"([^\"]*)\"", $match, $found)) {
85            $varAffected = $found[1];
86            $match       = optionParser::_removeFromMatch($found[0], $match);
87        } else {
88            $varAffected = null;
89        }
90    }
91
92    static function checkExclude(&$match, &$excludedPages, &$excludedNs, &$excludeSelfPage){
93        //--Looking if the syntax -exclude[item1 item2] has been used
94        if(optionParser::preg_match_wrapper("exclude:\[(.*)\]", $match, $found)) {
95            $match = optionParser::_removeFromMatch($found[0], $match);
96            self::_addListOfItemsToExclude(explode(' ', $found[1]), $excludedPages, $excludedNs);
97        }
98
99        //--Checking if specified subnamespaces have to be excluded
100        optionParser::preg_match_all_wrapper("exclude:([^[ <>]*):", $match, $found);
101        foreach($found as $subns) {
102            $excludedNs[] = $subns[1];
103            $match        = optionParser::_removeFromMatch($subns[0], $match);
104        }
105
106        //--Checking if specified pages have to be excluded
107        optionParser::preg_match_all_wrapper("exclude:([^[ <>]*)", $match, $found);
108        foreach($found as $page) {
109            $excludedPages[] = $page[1];
110            $match           = optionParser::_removeFromMatch($page[0], $match);
111        }
112
113        //--Looking if the current page has to be excluded
114        if(optionParser::preg_match_wrapper("exclude", $match, $found)) {
115            $excludeSelfPage = true;
116            $match           = optionParser::_removeFromMatch($found[0], $match);
117        }
118    }
119
120    static function checkGlobalExclude($globalExclude, &$excludedPages, &$excludedNs) {
121        if(!empty($globalExclude)) {
122          self::_addListOfItemsToExclude(explode(',', $globalExclude), $excludedPages, $excludedNs);
123        }
124    }
125
126    private static function _addListOfItemsToExclude($excludeList, &$excludedPages, &$excludedNs) {
127        foreach($excludeList as $exclude) {
128            $exclude = trim($exclude);
129            if ($exclude === "") {
130                return;
131            }
132            if($exclude[-1] === ':') {
133                $excludedNs[] = PhpString::substr($exclude, 0, -1);
134            } else {
135                $excludedPages[] = $exclude;
136            }
137       }
138    }
139
140    static function checkActualTitle(&$match, &$varAffected){
141        $foundOption = false;
142        if ( optionParser::preg_match_wrapper("actualTitle *= *([[:digit:]])", $match, $found) ){
143            $varAffected = $found[1];
144            $foundOption = true;
145        } else if ( optionParser::preg_match_wrapper("actualTitle", $match, $found) ){
146            $varAffected = 2;
147            $foundOption = true;
148        }
149
150        if ($foundOption) {
151            $match = optionParser::_removeFromMatch($found[0], $match);
152        }
153    }
154
155    static private function preg_match_wrapper($pattern, $subject, &$matches){
156        return preg_match('/\s-' . $pattern . '/i', $subject, $matches);
157    }
158
159    static private function preg_match_all_wrapper($pattern, $subject, &$matches){
160        return preg_match_all('/\s-' . $pattern . '/i', $subject, $matches, PREG_SET_ORDER);
161    }
162
163    static private function _removeFromMatch($matched, $match){
164        $matched = trim($matched); // to handle the case of the option "-r" which already matches an extra whitespace
165        // Matched option including any leading and at least one trailing whitespace
166        $regex = '/\s*' . preg_quote($matched, '/') . '\s+/';
167        return preg_replace($regex, ' ', $match);
168    }
169}
170