public function to($env, $data, $key = null, $array = false)
	{
		$this->validateEnvironment($env);

		if (!is_array($data) && empty($data) && $data !== false) {
			return null;
		}

		// Handle arrays by recursion
		if ($array) {
			$map = function ($data) use ($env, $key) {
				return $this->to($env, $data, $key);
			};

			return array_map($map, $data);
		}

		// Handle keys
		if (!is_null($key)) {
			if (!$def = $this->getDefinition($env, $key)) {
				throw new \InvalidArgumentException('Unknown key: ' . $key);
			}

			return $this->parseDefinitionValue($def, $data);
		}

		// Transform a data set
		$method_before = 'before' . ucfirst($env);
		$method_after  = 'after' . ucfirst($env);
		$ret           = [];

		$data = $this->$method_before($data);
		foreach ($data as $key => $value) {
			if ($def = $this->getDefinition($env, $key)) {
				$ret[$def[self::DEFINITION_KEY]] = $this->parseDefinitionValue($def, $value);
			} elseif (array_key_exists($key, $this->virtual_fields)) {
				$ret[$key] = $value;
			}
		}
		$ret = $this->$method_after($ret);

		return $ret;
	}