xref: /dokuwiki/inc/Input/Input.php (revision a469bafbb7a66014d980252c016b21d803046f1a)
1ccc4c71cSAndreas Gohr<?php
2ccc4c71cSAndreas Gohr
3ccc4c71cSAndreas Gohrnamespace dokuwiki\Input;
4ccc4c71cSAndreas Gohr
5ccc4c71cSAndreas Gohr/**
6ccc4c71cSAndreas Gohr * Encapsulates access to the $_REQUEST array, making sure used parameters are initialized and
7ccc4c71cSAndreas Gohr * have the correct type.
8ccc4c71cSAndreas Gohr *
9ccc4c71cSAndreas Gohr * All function access the $_REQUEST array by default, if you want to access $_POST or $_GET
10ccc4c71cSAndreas Gohr * explicitly use the $post and $get members.
11ccc4c71cSAndreas Gohr *
12ccc4c71cSAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org>
13ccc4c71cSAndreas Gohr */
14ccc4c71cSAndreas Gohrclass Input
15ccc4c71cSAndreas Gohr{
16ccc4c71cSAndreas Gohr
17ccc4c71cSAndreas Gohr    /** @var Post Access $_POST parameters */
18ccc4c71cSAndreas Gohr    public $post;
19ccc4c71cSAndreas Gohr    /** @var Get Access $_GET parameters */
20ccc4c71cSAndreas Gohr    public $get;
21ccc4c71cSAndreas Gohr    /** @var Server Access $_SERVER parameters */
22ccc4c71cSAndreas Gohr    public $server;
23ccc4c71cSAndreas Gohr
24ccc4c71cSAndreas Gohr    protected $access;
25ccc4c71cSAndreas Gohr
26ccc4c71cSAndreas Gohr    /**
27ccc4c71cSAndreas Gohr     * @var Callable
28ccc4c71cSAndreas Gohr     */
29ccc4c71cSAndreas Gohr    protected $filter;
30ccc4c71cSAndreas Gohr
31ccc4c71cSAndreas Gohr    /**
32ccc4c71cSAndreas Gohr     * Intilizes the dokuwiki\Input\Input class and it subcomponents
33ccc4c71cSAndreas Gohr     */
34ccc4c71cSAndreas Gohr    public function __construct()
35ccc4c71cSAndreas Gohr    {
36ccc4c71cSAndreas Gohr        $this->access = &$_REQUEST;
37ccc4c71cSAndreas Gohr        $this->post = new Post();
38ccc4c71cSAndreas Gohr        $this->get = new Get();
39ccc4c71cSAndreas Gohr        $this->server = new Server();
40ccc4c71cSAndreas Gohr    }
41ccc4c71cSAndreas Gohr
42ccc4c71cSAndreas Gohr    /**
43ccc4c71cSAndreas Gohr     * Apply the set filter to the given value
44ccc4c71cSAndreas Gohr     *
45ccc4c71cSAndreas Gohr     * @param string $data
46ccc4c71cSAndreas Gohr     * @return string
47ccc4c71cSAndreas Gohr     */
48ccc4c71cSAndreas Gohr    protected function applyfilter($data)
49ccc4c71cSAndreas Gohr    {
50ccc4c71cSAndreas Gohr        if (!$this->filter) return $data;
51ccc4c71cSAndreas Gohr        return call_user_func($this->filter, $data);
52ccc4c71cSAndreas Gohr    }
53ccc4c71cSAndreas Gohr
54ccc4c71cSAndreas Gohr    /**
55ccc4c71cSAndreas Gohr     * Return a filtered copy of the input object
56ccc4c71cSAndreas Gohr     *
57ccc4c71cSAndreas Gohr     * Expects a callable that accepts one string parameter and returns a filtered string
58ccc4c71cSAndreas Gohr     *
59ccc4c71cSAndreas Gohr     * @param Callable|string $filter
60ccc4c71cSAndreas Gohr     * @return Input
61ccc4c71cSAndreas Gohr     */
62ccc4c71cSAndreas Gohr    public function filter($filter = 'stripctl')
63ccc4c71cSAndreas Gohr    {
64ccc4c71cSAndreas Gohr        $this->filter = $filter;
65ccc4c71cSAndreas Gohr        $clone = clone $this;
66ccc4c71cSAndreas Gohr        $this->filter = '';
67ccc4c71cSAndreas Gohr        return $clone;
68ccc4c71cSAndreas Gohr    }
69ccc4c71cSAndreas Gohr
70ccc4c71cSAndreas Gohr    /**
71ccc4c71cSAndreas Gohr     * Check if a parameter was set
72ccc4c71cSAndreas Gohr     *
73ccc4c71cSAndreas Gohr     * Basically a wrapper around isset. When called on the $post and $get subclasses,
74ccc4c71cSAndreas Gohr     * the parameter is set to $_POST or $_GET and to $_REQUEST
75ccc4c71cSAndreas Gohr     *
76ccc4c71cSAndreas Gohr     * @see isset
77ccc4c71cSAndreas Gohr     * @param string $name Parameter name
78ccc4c71cSAndreas Gohr     * @return bool
79ccc4c71cSAndreas Gohr     */
80ccc4c71cSAndreas Gohr    public function has($name)
81ccc4c71cSAndreas Gohr    {
82ccc4c71cSAndreas Gohr        return isset($this->access[$name]);
83ccc4c71cSAndreas Gohr    }
84ccc4c71cSAndreas Gohr
85ccc4c71cSAndreas Gohr    /**
86ccc4c71cSAndreas Gohr     * Remove a parameter from the superglobals
87ccc4c71cSAndreas Gohr     *
88ccc4c71cSAndreas Gohr     * Basically a wrapper around unset. When NOT called on the $post and $get subclasses,
89ccc4c71cSAndreas Gohr     * the parameter will also be removed from $_POST or $_GET
90ccc4c71cSAndreas Gohr     *
91ccc4c71cSAndreas Gohr     * @see isset
92ccc4c71cSAndreas Gohr     * @param string $name Parameter name
93ccc4c71cSAndreas Gohr     */
94ccc4c71cSAndreas Gohr    public function remove($name)
95ccc4c71cSAndreas Gohr    {
96ccc4c71cSAndreas Gohr        if (isset($this->access[$name])) {
97ccc4c71cSAndreas Gohr            unset($this->access[$name]);
98ccc4c71cSAndreas Gohr        }
99ccc4c71cSAndreas Gohr        // also remove from sub classes
100ccc4c71cSAndreas Gohr        if (isset($this->post) && isset($_POST[$name])) {
101ccc4c71cSAndreas Gohr            unset($_POST[$name]);
102ccc4c71cSAndreas Gohr        }
103ccc4c71cSAndreas Gohr        if (isset($this->get) && isset($_GET[$name])) {
104ccc4c71cSAndreas Gohr            unset($_GET[$name]);
105ccc4c71cSAndreas Gohr        }
106ccc4c71cSAndreas Gohr    }
107ccc4c71cSAndreas Gohr
108ccc4c71cSAndreas Gohr    /**
109ccc4c71cSAndreas Gohr     * Access a request parameter without any type conversion
110ccc4c71cSAndreas Gohr     *
111ccc4c71cSAndreas Gohr     * @param string $name Parameter name
112ccc4c71cSAndreas Gohr     * @param mixed $default Default to return if parameter isn't set
113ccc4c71cSAndreas Gohr     * @param bool $nonempty Return $default if parameter is set but empty()
114ccc4c71cSAndreas Gohr     * @return mixed
115ccc4c71cSAndreas Gohr     */
116ccc4c71cSAndreas Gohr    public function param($name, $default = null, $nonempty = false)
117ccc4c71cSAndreas Gohr    {
118ccc4c71cSAndreas Gohr        if (!isset($this->access[$name])) return $default;
119ccc4c71cSAndreas Gohr        $value = $this->applyfilter($this->access[$name]);
120ccc4c71cSAndreas Gohr        if ($nonempty && empty($value)) return $default;
121ccc4c71cSAndreas Gohr        return $value;
122ccc4c71cSAndreas Gohr    }
123ccc4c71cSAndreas Gohr
124ccc4c71cSAndreas Gohr    /**
125ccc4c71cSAndreas Gohr     * Sets a parameter
126ccc4c71cSAndreas Gohr     *
127ccc4c71cSAndreas Gohr     * @param string $name Parameter name
128ccc4c71cSAndreas Gohr     * @param mixed $value Value to set
129ccc4c71cSAndreas Gohr     */
130ccc4c71cSAndreas Gohr    public function set($name, $value)
131ccc4c71cSAndreas Gohr    {
132ccc4c71cSAndreas Gohr        $this->access[$name] = $value;
133ccc4c71cSAndreas Gohr    }
134ccc4c71cSAndreas Gohr
135ccc4c71cSAndreas Gohr    /**
136ccc4c71cSAndreas Gohr     * Get a reference to a request parameter
137ccc4c71cSAndreas Gohr     *
138ccc4c71cSAndreas Gohr     * This avoids copying data in memory, when the parameter is not set it will be created
139ccc4c71cSAndreas Gohr     * and intialized with the given $default value before a reference is returned
140ccc4c71cSAndreas Gohr     *
141ccc4c71cSAndreas Gohr     * @param string $name Parameter name
142ccc4c71cSAndreas Gohr     * @param mixed $default If parameter is not set, initialize with this value
143ccc4c71cSAndreas Gohr     * @param bool $nonempty Init with $default if parameter is set but empty()
144ccc4c71cSAndreas Gohr     * @return mixed (reference)
145ccc4c71cSAndreas Gohr     */
146ccc4c71cSAndreas Gohr    public function &ref($name, $default = '', $nonempty = false)
147ccc4c71cSAndreas Gohr    {
148ccc4c71cSAndreas Gohr        if (!isset($this->access[$name]) || ($nonempty && empty($this->access[$name]))) {
149ccc4c71cSAndreas Gohr            $this->set($name, $default);
150ccc4c71cSAndreas Gohr        }
151ccc4c71cSAndreas Gohr
152ccc4c71cSAndreas Gohr        return $this->access[$name];
153ccc4c71cSAndreas Gohr    }
154ccc4c71cSAndreas Gohr
155ccc4c71cSAndreas Gohr    /**
156ccc4c71cSAndreas Gohr     * Access a request parameter as int
157ccc4c71cSAndreas Gohr     *
158ccc4c71cSAndreas Gohr     * @param string $name Parameter name
159ccc4c71cSAndreas Gohr     * @param int $default Default to return if parameter isn't set or is an array
160ccc4c71cSAndreas Gohr     * @param bool $nonempty Return $default if parameter is set but empty()
161ccc4c71cSAndreas Gohr     * @return int
162ccc4c71cSAndreas Gohr     */
163ccc4c71cSAndreas Gohr    public function int($name, $default = 0, $nonempty = false)
164ccc4c71cSAndreas Gohr    {
165ccc4c71cSAndreas Gohr        if (!isset($this->access[$name])) return $default;
166ccc4c71cSAndreas Gohr        if (is_array($this->access[$name])) return $default;
167ccc4c71cSAndreas Gohr        $value = $this->applyfilter($this->access[$name]);
168ccc4c71cSAndreas Gohr        if ($value === '') return $default;
169ccc4c71cSAndreas Gohr        if ($nonempty && empty($value)) return $default;
170ccc4c71cSAndreas Gohr
171ccc4c71cSAndreas Gohr        return (int)$value;
172ccc4c71cSAndreas Gohr    }
173ccc4c71cSAndreas Gohr
174ccc4c71cSAndreas Gohr    /**
175ccc4c71cSAndreas Gohr     * Access a request parameter as string
176ccc4c71cSAndreas Gohr     *
177ccc4c71cSAndreas Gohr     * @param string $name Parameter name
178ccc4c71cSAndreas Gohr     * @param string $default Default to return if parameter isn't set or is an array
179ccc4c71cSAndreas Gohr     * @param bool $nonempty Return $default if parameter is set but empty()
180ccc4c71cSAndreas Gohr     * @return string
181ccc4c71cSAndreas Gohr     */
182ccc4c71cSAndreas Gohr    public function str($name, $default = '', $nonempty = false)
183ccc4c71cSAndreas Gohr    {
184ccc4c71cSAndreas Gohr        if (!isset($this->access[$name])) return $default;
185ccc4c71cSAndreas Gohr        if (is_array($this->access[$name])) return $default;
186ccc4c71cSAndreas Gohr        $value = $this->applyfilter($this->access[$name]);
187ccc4c71cSAndreas Gohr        if ($nonempty && empty($value)) return $default;
188ccc4c71cSAndreas Gohr
189ccc4c71cSAndreas Gohr        return (string)$value;
190ccc4c71cSAndreas Gohr    }
191ccc4c71cSAndreas Gohr
192ccc4c71cSAndreas Gohr    /**
193ccc4c71cSAndreas Gohr     * Access a request parameter and make sure it is has a valid value
194ccc4c71cSAndreas Gohr     *
195ccc4c71cSAndreas Gohr     * Please note that comparisons to the valid values are not done typesafe (request vars
196ccc4c71cSAndreas Gohr     * are always strings) however the function will return the correct type from the $valids
197ccc4c71cSAndreas Gohr     * array when an match was found.
198ccc4c71cSAndreas Gohr     *
199ccc4c71cSAndreas Gohr     * @param string $name Parameter name
200ccc4c71cSAndreas Gohr     * @param array $valids Array of valid values
201ccc4c71cSAndreas Gohr     * @param mixed $default Default to return if parameter isn't set or not valid
202ccc4c71cSAndreas Gohr     * @return null|mixed
203ccc4c71cSAndreas Gohr     */
204ccc4c71cSAndreas Gohr    public function valid($name, $valids, $default = null)
205ccc4c71cSAndreas Gohr    {
206ccc4c71cSAndreas Gohr        if (!isset($this->access[$name])) return $default;
207ccc4c71cSAndreas Gohr        if (is_array($this->access[$name])) return $default; // we don't allow arrays
208ccc4c71cSAndreas Gohr        $value = $this->applyfilter($this->access[$name]);
209ccc4c71cSAndreas Gohr        $found = array_search($value, $valids);
210ccc4c71cSAndreas Gohr        if ($found !== false) return $valids[$found]; // return the valid value for type safety
211ccc4c71cSAndreas Gohr        return $default;
212ccc4c71cSAndreas Gohr    }
213ccc4c71cSAndreas Gohr
214ccc4c71cSAndreas Gohr    /**
215ccc4c71cSAndreas Gohr     * Access a request parameter as bool
216ccc4c71cSAndreas Gohr     *
217ccc4c71cSAndreas Gohr     * Note: $nonempty is here for interface consistency and makes not much sense for booleans
218ccc4c71cSAndreas Gohr     *
219ccc4c71cSAndreas Gohr     * @param string $name Parameter name
220ccc4c71cSAndreas Gohr     * @param mixed $default Default to return if parameter isn't set
221ccc4c71cSAndreas Gohr     * @param bool $nonempty Return $default if parameter is set but empty()
222ccc4c71cSAndreas Gohr     * @return bool
223ccc4c71cSAndreas Gohr     */
224ccc4c71cSAndreas Gohr    public function bool($name, $default = false, $nonempty = false)
225ccc4c71cSAndreas Gohr    {
226ccc4c71cSAndreas Gohr        if (!isset($this->access[$name])) return $default;
227ccc4c71cSAndreas Gohr        if (is_array($this->access[$name])) return $default;
228ccc4c71cSAndreas Gohr        $value = $this->applyfilter($this->access[$name]);
229ccc4c71cSAndreas Gohr        if ($value === '') return $default;
230ccc4c71cSAndreas Gohr        if ($nonempty && empty($value)) return $default;
231ccc4c71cSAndreas Gohr
232ccc4c71cSAndreas Gohr        return (bool)$value;
233ccc4c71cSAndreas Gohr    }
234ccc4c71cSAndreas Gohr
235ccc4c71cSAndreas Gohr    /**
236ccc4c71cSAndreas Gohr     * Access a request parameter as array
237ccc4c71cSAndreas Gohr     *
238ccc4c71cSAndreas Gohr     * @param string $name Parameter name
239ccc4c71cSAndreas Gohr     * @param mixed $default Default to return if parameter isn't set
240ccc4c71cSAndreas Gohr     * @param bool $nonempty Return $default if parameter is set but empty()
241ccc4c71cSAndreas Gohr     * @return array
242ccc4c71cSAndreas Gohr     */
243*a469bafbSAndreas Gohr    public function arr($name, $default = [], $nonempty = false)
244ccc4c71cSAndreas Gohr    {
245ccc4c71cSAndreas Gohr        if (!isset($this->access[$name])) return $default;
246ccc4c71cSAndreas Gohr        if (!is_array($this->access[$name])) return $default;
247ccc4c71cSAndreas Gohr        if ($nonempty && empty($this->access[$name])) return $default;
248ccc4c71cSAndreas Gohr
249*a469bafbSAndreas Gohr        return $this->access[$name];
250ccc4c71cSAndreas Gohr    }
251ccc4c71cSAndreas Gohr
252ccc4c71cSAndreas Gohr    /**
253ccc4c71cSAndreas Gohr     * Create a simple key from an array key
254ccc4c71cSAndreas Gohr     *
255ccc4c71cSAndreas Gohr     * This is useful to access keys where the information is given as an array key or as a single array value.
256ccc4c71cSAndreas Gohr     * For example when the information was submitted as the name of a submit button.
257ccc4c71cSAndreas Gohr     *
258ccc4c71cSAndreas Gohr     * This function directly changes the access array.
259ccc4c71cSAndreas Gohr     *
260ccc4c71cSAndreas Gohr     * Eg. $_REQUEST['do']['save']='Speichern' becomes $_REQUEST['do'] = 'save'
261ccc4c71cSAndreas Gohr     *
262ccc4c71cSAndreas Gohr     * This function returns the $INPUT object itself for easy chaining
263ccc4c71cSAndreas Gohr     *
264ccc4c71cSAndreas Gohr     * @param string $name
265ccc4c71cSAndreas Gohr     * @return Input
266ccc4c71cSAndreas Gohr     */
267ccc4c71cSAndreas Gohr    public function extract($name)
268ccc4c71cSAndreas Gohr    {
269ccc4c71cSAndreas Gohr        if (!isset($this->access[$name])) return $this;
270ccc4c71cSAndreas Gohr        if (!is_array($this->access[$name])) return $this;
271ccc4c71cSAndreas Gohr        $keys = array_keys($this->access[$name]);
272ccc4c71cSAndreas Gohr        if (!$keys) {
273ccc4c71cSAndreas Gohr            // this was an empty array
274ccc4c71cSAndreas Gohr            $this->remove($name);
275ccc4c71cSAndreas Gohr            return $this;
276ccc4c71cSAndreas Gohr        }
277ccc4c71cSAndreas Gohr        // get the first key
278ccc4c71cSAndreas Gohr        $value = array_shift($keys);
279ccc4c71cSAndreas Gohr        if ($value === 0) {
280ccc4c71cSAndreas Gohr            // we had a numeric array, assume the value is not in the key
281ccc4c71cSAndreas Gohr            $value = array_shift($this->access[$name]);
282ccc4c71cSAndreas Gohr        }
283ccc4c71cSAndreas Gohr
284ccc4c71cSAndreas Gohr        $this->set($name, $value);
285ccc4c71cSAndreas Gohr        return $this;
286ccc4c71cSAndreas Gohr    }
287ccc4c71cSAndreas Gohr}
288