<?php

class WP_Request extends ArrayObject {
	public function __construct($storage = array(), $slashed = 'slashed') {
		parent::setFlags(parent::ARRAY_AS_PROPS);
		$this->load($storage, $slashed);
	}
	private function populate_props($array = null) {
		if ( empty($array) )
			$array =& static::$storage;
		foreach ( $array as $key => $value )
			$this->$key = $value;
	}
	public function load($storage, $slashed = 'slashed') {
		if ( 'slashed' == $slashed )
			$storage = stripslashes_deep($storage);
		self::set($storage);
	}
	public function set($key, $value = null) {
		if ( is_scalar($key) && is_null($value) ) {
			unset( static::$storage[ $key ] );
			if ( isset($this->$key) )
				unset($this->$key);
			return true;
		}

		if ( is_scalar($key) )
			$key = array( $key => $value );
		static::$storage = array_merge( static::$storage, $key);
		if ( isset($this) )
			self::populate_props($key);
		return true;
	}
	public function get($key, $default = null) {
		if ( is_array($key) ) {
			$_result = array();
			foreach ( $key as $k )
				$_result[ $k ] = self::get($k, isset($default[$k]) ? $default[$k] : null );
			return $_result;
		}
		if ( isset(static::$storage[ $key ]) )
			return static::$storage[ $key ];
		return $default;
	}
	public function __get($key) {
		return self::get($key);
	}
	public function __set($key, $value) {
		return self::set($key, $value);
	}
	public function __isset($key) {
		return isset(static::$storage[$key]);
	}
	public function __unset($key) {
		return self::set($key, null);
	}

	
}

// Seperate classes for static class access and individual $storage
class GET extends WP_Request {
	static $storage = array();
}
class POST extends WP_Request {
	static $storage = array();
}
class REQUEST extends WP_Request {
	static $storage = array();
}

GET::load($_GET, 'slashed');
POST::load($_POST, 'slashed');
REQUEST::load($_REQUEST, 'slashed');

add_action('template_redirect', function() {
	// Lets assume ?key=GET1&key3=>GET3 is used
	
	var_dump( GET::get('key', 'default') ); // GET1
	var_dump( GET::get('key2', 'default') ); // default
	var_dump( POST::get('key', 'default') ); // default
	var_dump( GET::get( array('key', 'key2') ) ); // key2
	
	$g = new GET();
	var_dump(
			$g->get('key'), // Works
			$g->key, // Works
			$g['key'] // Works
			);
	var_dump(
			$g->get('key2'), // Works, returns null
			$g->key2, // Notices undefined
			$g['key2'] // Notices undefined
			);
	var_dump( (array)$g ); // Array of unslashed data

	var_dump( GET::get( array('key', 'key2', 'key3', 'key4' ), array( 'key4' => 'VAL4') ) );
	/* returns:
		array
		  'key' => string 'GET' (length=3)
		  'key2' => null  // It's unset
		  'key3' => string 'GET3' (length=4)
		  'key4' => string 'VAL4' (length=4) //From the defaults
	  */

	// Iterates over unslashed data
	foreach ( $g as $key => $value )
		var_dump( "$key => $value" );
		
	$g->set('test', '123'); // set ?$query&test=123
	var_dump(GET::get('test')); // Works: 123
	var_dump(REQUEST::get('test')); // Works: Returns null - GET/POST doesnt affect REQUEST after it's initialized.
	var_dump($_GET['test']); // Notices: Unset, class doesn't fill affect SuperGlobals yet.
	
});