1 <?php
2 /**
3 * Part of the Joomla Framework Input Package
4 *
5 * @copyright Copyright (C) 2005 - 2016 Open Source Matters, Inc. All rights reserved.
6 * @license GNU General Public License version 2 or later; see LICENSE
7 */
8
9 namespace Joomla\Input;
10
11 use Joomla\Filter;
12
13 /**
14 * Joomla! Input Base Class
15 *
16 * This is an abstracted input class used to manage retrieving data from the application environment.
17 *
18 * @since 1.0
19 *
20 * @property-read Input $get
21 * @property-read Input $post
22 * @property-read Input $request
23 * @property-read Input $server
24 * @property-read Files $files
25 * @property-read Cookie $cookie
26 *
27 * @method integer getInt($name, $default = null) Get a signed integer.
28 * @method integer getUint($name, $default = null) Get an unsigned integer.
29 * @method float getFloat($name, $default = null) Get a floating-point number.
30 * @method boolean getBool($name, $default = null) Get a boolean value.
31 * @method string getWord($name, $default = null) Get a word.
32 * @method string getAlnum($name, $default = null) Get an alphanumeric string.
33 * @method string getCmd($name, $default = null) Get a CMD filtered string.
34 * @method string getBase64($name, $default = null) Get a base64 encoded string.
35 * @method string getString($name, $default = null) Get a string.
36 * @method string getHtml($name, $default = null) Get a HTML string.
37 * @method string getPath($name, $default = null) Get a file path.
38 * @method string getUsername($name, $default = null) Get a username.
39 */
40 class Input implements \Serializable, \Countable
41 {
42 /**
43 * Options array for the Input instance.
44 *
45 * @var array
46 * @since 1.0
47 */
48 protected $options = array();
49
50 /**
51 * Filter object to use.
52 *
53 * @var Filter\InputFilter
54 * @since 1.0
55 */
56 protected $filter = null;
57
58 /**
59 * Input data.
60 *
61 * @var array
62 * @since 1.0
63 */
64 protected $data = array();
65
66 /**
67 * Input objects
68 *
69 * @var Input[]
70 * @since 1.0
71 */
72 protected $inputs = array();
73
74 /**
75 * Is all GLOBAL added
76 *
77 * @var boolean
78 * @since 1.1.4
79 */
80 protected static $loaded = false;
81
82 /**
83 * Constructor.
84 *
85 * @param array $source Optional source data. If omitted, a copy of the server variable '_REQUEST' is used.
86 * @param array $options An optional associative array of configuration parameters:
87 * filter: An instance of Filter\Input. If omitted, a default filter is initialised.
88 *
89 * @since 1.0
90 */
91 public function __construct($source = null, array $options = array())
92 {
93 if (isset($options['filter']))
94 {
95 $this->filter = $options['filter'];
96 }
97 else
98 {
99 $this->filter = new Filter\InputFilter;
100 }
101
102 if (is_null($source))
103 {
104 $this->data = &$_REQUEST;
105 }
106 else
107 {
108 $this->data = $source;
109 }
110
111 // Set the options for the class.
112 $this->options = $options;
113 }
114
115 /**
116 * Magic method to get an input object
117 *
118 * @param mixed $name Name of the input object to retrieve.
119 *
120 * @return Input The request input object
121 *
122 * @since 1.0
123 */
124 public function __get($name)
125 {
126 if (isset($this->inputs[$name]))
127 {
128 return $this->inputs[$name];
129 }
130
131 $className = '\\Joomla\\Input\\' . ucfirst($name);
132
133 if (class_exists($className))
134 {
135 $this->inputs[$name] = new $className(null, $this->options);
136
137 return $this->inputs[$name];
138 }
139
140 $superGlobal = '_' . strtoupper($name);
141
142 if (isset($GLOBALS[$superGlobal]))
143 {
144 $this->inputs[$name] = new Input($GLOBALS[$superGlobal], $this->options);
145
146 return $this->inputs[$name];
147 }
148
149 // TODO throw an exception
150 }
151
152 /**
153 * Get the number of variables.
154 *
155 * @return integer The number of variables in the input.
156 *
157 * @since 1.0
158 * @see Countable::count()
159 */
160 public function count()
161 {
162 return count($this->data);
163 }
164
165 /**
166 * Gets a value from the input data.
167 *
168 * @param string $name Name of the value to get.
169 * @param mixed $default Default value to return if variable does not exist.
170 * @param string $filter Filter to apply to the value.
171 *
172 * @return mixed The filtered input value.
173 *
174 * @see \Joomla\Filter\InputFilter::clean()
175 * @since 1.0
176 */
177 public function get($name, $default = null, $filter = 'cmd')
178 {
179 if (isset($this->data[$name]))
180 {
181 return $this->filter->clean($this->data[$name], $filter);
182 }
183
184 return $default;
185 }
186
187 /**
188 * Gets an array of values from the request.
189 *
190 * @param array $vars Associative array of keys and filter types to apply.
191 * If empty and datasource is null, all the input data will be returned
192 * but filtered using the default case in JFilterInput::clean.
193 * @param mixed $datasource Array to retrieve data from, or null
194 *
195 * @return mixed The filtered input data.
196 *
197 * @since 1.0
198 */
199 public function getArray(array $vars = array(), $datasource = null)
200 {
201 if (empty($vars) && is_null($datasource))
202 {
203 $vars = $this->data;
204 }
205
206 $results = array();
207
208 foreach ($vars as $k => $v)
209 {
210 if (is_array($v))
211 {
212 if (is_null($datasource))
213 {
214 $results[$k] = $this->getArray($v, $this->get($k, null, 'array'));
215 }
216 else
217 {
218 $results[$k] = $this->getArray($v, $datasource[$k]);
219 }
220 }
221 else
222 {
223 if (is_null($datasource))
224 {
225 $results[$k] = $this->get($k, null, $v);
226 }
227 elseif (isset($datasource[$k]))
228 {
229 $results[$k] = $this->filter->clean($datasource[$k], $v);
230 }
231 else
232 {
233 $results[$k] = $this->filter->clean(null, $v);
234 }
235 }
236 }
237
238 return $results;
239 }
240
241 /**
242 * Sets a value
243 *
244 * @param string $name Name of the value to set.
245 * @param mixed $value Value to assign to the input.
246 *
247 * @return void
248 *
249 * @since 1.0
250 */
251 public function set($name, $value)
252 {
253 $this->data[$name] = $value;
254 }
255
256 /**
257 * Define a value. The value will only be set if there's no value for the name or if it is null.
258 *
259 * @param string $name Name of the value to define.
260 * @param mixed $value Value to assign to the input.
261 *
262 * @return void
263 *
264 * @since 1.0
265 */
266 public function def($name, $value)
267 {
268 if (isset($this->data[$name]))
269 {
270 return;
271 }
272
273 $this->data[$name] = $value;
274 }
275
276 /**
277 * Check if a value name exists.
278 *
279 * @param string $path Value name
280 *
281 * @return boolean
282 *
283 * @since 1.2.0
284 */
285 public function exists($name)
286 {
287 return isset($this->data[$name]);
288 }
289
290 /**
291 * Magic method to get filtered input data.
292 *
293 * @param string $name Name of the filter type prefixed with 'get'.
294 * @param array $arguments [0] The name of the variable [1] The default value.
295 *
296 * @return mixed The filtered input value.
297 *
298 * @since 1.0
299 */
300 public function __call($name, $arguments)
301 {
302 if (substr($name, 0, 3) == 'get')
303 {
304 $filter = substr($name, 3);
305
306 $default = null;
307
308 if (isset($arguments[1]))
309 {
310 $default = $arguments[1];
311 }
312
313 return $this->get($arguments[0], $default, $filter);
314 }
315 }
316
317 /**
318 * Gets the request method.
319 *
320 * @return string The request method.
321 *
322 * @since 1.0
323 */
324 public function getMethod()
325 {
326 $method = strtoupper($_SERVER['REQUEST_METHOD']);
327
328 return $method;
329 }
330
331 /**
332 * Method to serialize the input.
333 *
334 * @return string The serialized input.
335 *
336 * @since 1.0
337 */
338 public function serialize()
339 {
340 // Load all of the inputs.
341 $this->loadAllInputs();
342
343 // Remove $_ENV and $_SERVER from the inputs.
344 $inputs = $this->inputs;
345 unset($inputs['env']);
346 unset($inputs['server']);
347
348 // Serialize the options, data, and inputs.
349 return serialize(array($this->options, $this->data, $inputs));
350 }
351
352 /**
353 * Method to unserialize the input.
354 *
355 * @param string $input The serialized input.
356 *
357 * @return Input The input object.
358 *
359 * @since 1.0
360 */
361 public function unserialize($input)
362 {
363 // Unserialize the options, data, and inputs.
364 list($this->options, $this->data, $this->inputs) = unserialize($input);
365
366 // Load the filter.
367 if (isset($this->options['filter']))
368 {
369 $this->filter = $this->options['filter'];
370 }
371 else
372 {
373 $this->filter = new Filter\InputFilter;
374 }
375 }
376
377 /**
378 * Method to load all of the global inputs.
379 *
380 * @return void
381 *
382 * @since 1.0
383 */
384 protected function loadAllInputs()
385 {
386 if (!self::$loaded)
387 {
388 // Load up all the globals.
389 foreach ($GLOBALS as $global => $data)
390 {
391 // Check if the global starts with an underscore.
392 if (strpos($global, '_') === 0)
393 {
394 // Convert global name to input name.
395 $global = strtolower($global);
396 $global = substr($global, 1);
397
398 // Get the input.
399 $this->$global;
400 }
401 }
402
403 self::$loaded = true;
404 }
405 }
406 }
407