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