xref: /dokuwiki/_test/core/TestRequest.php (revision ec34bb300b254ecd0dba0fac22d8115635141cc5)
1f8369d7dSTobias Sarnowski<?php
2f8369d7dSTobias Sarnowski/**
3f8369d7dSTobias Sarnowski * Simulates a full DokuWiki HTTP Request and allows
4f8369d7dSTobias Sarnowski * runtime inspection.
5f8369d7dSTobias Sarnowski */
6f8369d7dSTobias Sarnowski
7ccc4c71cSAndreas Gohruse dokuwiki\Input\Input;
8ccc4c71cSAndreas Gohr
9f8369d7dSTobias Sarnowski/**
10f8369d7dSTobias Sarnowski * Helper class to execute a fake request
11f8369d7dSTobias Sarnowski */
12f8369d7dSTobias Sarnowskiclass TestRequest {
13f8369d7dSTobias Sarnowski
141ada9e0aSAndreas Gohr    protected $valid_scripts = array('/doku.php', '/lib/exe/fetch.php', '/lib/exe/detail.php', '/lib/exe/ajax.php');
151ada9e0aSAndreas Gohr    protected $script;
169894e7afSChristopher Smith
171ada9e0aSAndreas Gohr    protected $server = array();
181ada9e0aSAndreas Gohr    protected $session = array();
191ada9e0aSAndreas Gohr    protected $get = array();
201ada9e0aSAndreas Gohr    protected $post = array();
2127c0c399SAndreas Gohr    protected $data = array();
22f8369d7dSTobias Sarnowski
23444d58a8SAndreas Gohr    /** @var string stores the output buffer, even when it's flushed */
24444d58a8SAndreas Gohr    protected $output_buffer = '';
25444d58a8SAndreas Gohr
26444d58a8SAndreas Gohr    /** @var null|TestRequest the currently running request */
27444d58a8SAndreas Gohr    static protected $running = null;
28444d58a8SAndreas Gohr
291ada9e0aSAndreas Gohr    /**
301ada9e0aSAndreas Gohr     * Get a $_SERVER var
311ada9e0aSAndreas Gohr     *
321ada9e0aSAndreas Gohr     * @param string $key
331ada9e0aSAndreas Gohr     * @return mixed
341ada9e0aSAndreas Gohr     */
351ada9e0aSAndreas Gohr    public function getServer($key) {
361ada9e0aSAndreas Gohr        return $this->server[$key];
371ada9e0aSAndreas Gohr    }
38f8369d7dSTobias Sarnowski
391ada9e0aSAndreas Gohr    /**
401ada9e0aSAndreas Gohr     * Get a $_SESSION var
411ada9e0aSAndreas Gohr     *
421ada9e0aSAndreas Gohr     * @param string $key
431ada9e0aSAndreas Gohr     * @return mixed
441ada9e0aSAndreas Gohr     */
451ada9e0aSAndreas Gohr    public function getSession($key) {
461ada9e0aSAndreas Gohr        return $this->session[$key];
471ada9e0aSAndreas Gohr    }
481ada9e0aSAndreas Gohr
491ada9e0aSAndreas Gohr    /**
501ada9e0aSAndreas Gohr     * Get a $_GET var
511ada9e0aSAndreas Gohr     *
521ada9e0aSAndreas Gohr     * @param string $key
531ada9e0aSAndreas Gohr     * @return mixed
541ada9e0aSAndreas Gohr     */
551ada9e0aSAndreas Gohr    public function getGet($key) {
561ada9e0aSAndreas Gohr        return $this->get[$key];
571ada9e0aSAndreas Gohr    }
581ada9e0aSAndreas Gohr
591ada9e0aSAndreas Gohr    /**
601ada9e0aSAndreas Gohr     * Get a $_POST var
611ada9e0aSAndreas Gohr     *
621ada9e0aSAndreas Gohr     * @param string $key
631ada9e0aSAndreas Gohr     * @return mixed
641ada9e0aSAndreas Gohr     */
651ada9e0aSAndreas Gohr    public function getPost($key) {
661ada9e0aSAndreas Gohr        return $this->post[$key];
671ada9e0aSAndreas Gohr    }
681ada9e0aSAndreas Gohr
691ada9e0aSAndreas Gohr    /**
701ada9e0aSAndreas Gohr     * Get the script that will execute the request
711ada9e0aSAndreas Gohr     *
721ada9e0aSAndreas Gohr     * @return string
731ada9e0aSAndreas Gohr     */
741ada9e0aSAndreas Gohr    public function getScript() {
751ada9e0aSAndreas Gohr        return $this->script;
761ada9e0aSAndreas Gohr    }
771ada9e0aSAndreas Gohr
781ada9e0aSAndreas Gohr    /**
791ada9e0aSAndreas Gohr     * Set a $_SERVER var
801ada9e0aSAndreas Gohr     *
811ada9e0aSAndreas Gohr     * @param string $key
821ada9e0aSAndreas Gohr     * @param mixed $value
831ada9e0aSAndreas Gohr     */
841ada9e0aSAndreas Gohr    public function setServer($key, $value) {
851ada9e0aSAndreas Gohr        $this->server[$key] = $value;
861ada9e0aSAndreas Gohr    }
871ada9e0aSAndreas Gohr
881ada9e0aSAndreas Gohr    /**
891ada9e0aSAndreas Gohr     * Set a $_SESSION var
901ada9e0aSAndreas Gohr     *
911ada9e0aSAndreas Gohr     * @param string $key
921ada9e0aSAndreas Gohr     * @param mixed $value
931ada9e0aSAndreas Gohr     */
941ada9e0aSAndreas Gohr    public function setSession($key, $value) {
951ada9e0aSAndreas Gohr        $this->session[$key] = $value;
961ada9e0aSAndreas Gohr    }
971ada9e0aSAndreas Gohr
981ada9e0aSAndreas Gohr    /**
991ada9e0aSAndreas Gohr     * Set a $_GET var
1001ada9e0aSAndreas Gohr     *
1011ada9e0aSAndreas Gohr     * @param string $key
1021ada9e0aSAndreas Gohr     * @param mixed $value
1031ada9e0aSAndreas Gohr     */
1041ada9e0aSAndreas Gohr    public function setGet($key, $value) {
1051ada9e0aSAndreas Gohr        $this->get[$key] = $value;
1061ada9e0aSAndreas Gohr    }
1071ada9e0aSAndreas Gohr
1081ada9e0aSAndreas Gohr    /**
1091ada9e0aSAndreas Gohr     * Set a $_POST var
1101ada9e0aSAndreas Gohr     *
1111ada9e0aSAndreas Gohr     * @param string $key
1121ada9e0aSAndreas Gohr     * @param mixed $value
1131ada9e0aSAndreas Gohr     */
1141ada9e0aSAndreas Gohr    public function setPost($key, $value) {
1151ada9e0aSAndreas Gohr        $this->post[$key] = $value;
1161ada9e0aSAndreas Gohr    }
117f8369d7dSTobias Sarnowski
118f8369d7dSTobias Sarnowski    /**
119f8369d7dSTobias Sarnowski     * Executes the request
120f8369d7dSTobias Sarnowski     *
1211ada9e0aSAndreas Gohr     * @param string $uri end URL to simulate, needs to be one of the testable scripts
122f8369d7dSTobias Sarnowski     * @return TestResponse the resulting output of the request
123f8369d7dSTobias Sarnowski     */
1244d053d04SAndreas Gohr    public function execute($uri = '/doku.php') {
125fe717f57Slisps        global $INPUT;
126fe717f57Slisps
127f8369d7dSTobias Sarnowski        // save old environment
128f8369d7dSTobias Sarnowski        $server = $_SERVER;
129f8369d7dSTobias Sarnowski        $session = $_SESSION;
130f8369d7dSTobias Sarnowski        $get = $_GET;
131f8369d7dSTobias Sarnowski        $post = $_POST;
132f8369d7dSTobias Sarnowski        $request = $_REQUEST;
133fe717f57Slisps        $input = $INPUT;
134f8369d7dSTobias Sarnowski
1354d053d04SAndreas Gohr        // prepare the right URI
1364d053d04SAndreas Gohr        $this->setUri($uri);
1374d053d04SAndreas Gohr
1380189bd86SAndreas Gohr        // import all defined globals into the function scope
1390189bd86SAndreas Gohr        foreach(array_keys($GLOBALS) as $glb) {
1400189bd86SAndreas Gohr            global $$glb;
1410189bd86SAndreas Gohr        }
1420189bd86SAndreas Gohr
143f8369d7dSTobias Sarnowski        // fake environment
144f8369d7dSTobias Sarnowski        global $default_server_vars;
145f8369d7dSTobias Sarnowski        $_SERVER = array_merge($default_server_vars, $this->server);
146f8369d7dSTobias Sarnowski        $_SESSION = $this->session;
147f8369d7dSTobias Sarnowski        $_GET = $this->get;
148f8369d7dSTobias Sarnowski        $_POST = $this->post;
149f8369d7dSTobias Sarnowski        $_REQUEST = array_merge($_GET, $_POST);
150f8369d7dSTobias Sarnowski
151f8369d7dSTobias Sarnowski        // reset output buffer
152444d58a8SAndreas Gohr        $this->output_buffer = '';
153f8369d7dSTobias Sarnowski
154f8369d7dSTobias Sarnowski        // now execute dokuwiki and grep the output
155444d58a8SAndreas Gohr        self::$running = $this;
156f8369d7dSTobias Sarnowski        header_remove();
157444d58a8SAndreas Gohr        ob_start(array($this, 'ob_start_callback'));
158fe717f57Slisps        $INPUT = new Input();
1599894e7afSChristopher Smith        include(DOKU_INC . $this->script);
160f8369d7dSTobias Sarnowski        ob_end_flush();
161444d58a8SAndreas Gohr        self::$running = null;
162f8369d7dSTobias Sarnowski
163f8369d7dSTobias Sarnowski        // create the response object
164f8369d7dSTobias Sarnowski        $response = new TestResponse(
165444d58a8SAndreas Gohr            $this->output_buffer,
16627c0c399SAndreas Gohr            // cli sapi doesn't do headers, prefer xdebug_get_headers() which works under cli
16727c0c399SAndreas Gohr            (function_exists('xdebug_get_headers') ? xdebug_get_headers() : headers_list()),
16827c0c399SAndreas Gohr            $this->data
169f8369d7dSTobias Sarnowski        );
170f8369d7dSTobias Sarnowski
171f8369d7dSTobias Sarnowski        // reset environment
172f8369d7dSTobias Sarnowski        $_SERVER = $server;
173f8369d7dSTobias Sarnowski        $_SESSION = $session;
174f8369d7dSTobias Sarnowski        $_GET = $get;
175f8369d7dSTobias Sarnowski        $_POST = $post;
176f8369d7dSTobias Sarnowski        $_REQUEST = $request;
177fe717f57Slisps        $INPUT = $input;
178f8369d7dSTobias Sarnowski
179f8369d7dSTobias Sarnowski        return $response;
180f8369d7dSTobias Sarnowski    }
1819e777ceeSAndreas Gohr
1829e777ceeSAndreas Gohr    /**
1839e777ceeSAndreas Gohr     * Set the virtual URI the request works against
1849e777ceeSAndreas Gohr     *
1859e777ceeSAndreas Gohr     * This parses the given URI and sets any contained GET variables
1869e777ceeSAndreas Gohr     * but will not overwrite any previously set ones (eg. set via setGet()).
1879e777ceeSAndreas Gohr     *
1889e777ceeSAndreas Gohr     * It initializes the $_SERVER['REQUEST_URI'] and $_SERVER['QUERY_STRING']
1899e777ceeSAndreas Gohr     * with all set GET variables.
1909e777ceeSAndreas Gohr     *
1911ada9e0aSAndreas Gohr     * @param string $uri end URL to simulate
1921ada9e0aSAndreas Gohr     * @throws Exception when an invalid script is passed
1939e777ceeSAndreas Gohr     */
1944d053d04SAndreas Gohr    protected function setUri($uri) {
1959894e7afSChristopher Smith        if(!preg_match('#^(' . join('|', $this->valid_scripts) . ')#', $uri)) {
1969894e7afSChristopher Smith            throw new Exception("$uri \n--- only " . join(', ', $this->valid_scripts) . " are supported currently");
1979e777ceeSAndreas Gohr        }
1989e777ceeSAndreas Gohr
1999e777ceeSAndreas Gohr        $params = array();
200*ec34bb30SAndreas Gohr        list($uri, $query) = sexplode('?', $uri, 2);
2019e777ceeSAndreas Gohr        if($query) parse_str($query, $params);
2029e777ceeSAndreas Gohr
2039894e7afSChristopher Smith        $this->script = substr($uri, 1);
2049e777ceeSAndreas Gohr        $this->get = array_merge($params, $this->get);
2059e777ceeSAndreas Gohr        if(count($this->get)) {
2069e777ceeSAndreas Gohr            $query = '?' . http_build_query($this->get, '', '&');
2079e777ceeSAndreas Gohr            $query = str_replace(
2089e777ceeSAndreas Gohr                array('%3A', '%5B', '%5D'),
2099e777ceeSAndreas Gohr                array(':', '[', ']'),
2109e777ceeSAndreas Gohr                $query
2119e777ceeSAndreas Gohr            );
2129e777ceeSAndreas Gohr            $uri = $uri . $query;
2139e777ceeSAndreas Gohr        }
2149e777ceeSAndreas Gohr
2159e777ceeSAndreas Gohr        $this->setServer('QUERY_STRING', $query);
2169e777ceeSAndreas Gohr        $this->setServer('REQUEST_URI', $uri);
2179e777ceeSAndreas Gohr    }
2189e777ceeSAndreas Gohr
2199e777ceeSAndreas Gohr    /**
2209e777ceeSAndreas Gohr     * Simulate a POST request with the given variables
2219e777ceeSAndreas Gohr     *
2229e777ceeSAndreas Gohr     * @param array $post all the POST parameters to use
2231ada9e0aSAndreas Gohr     * @param string $uri end URL to simulate
2241ada9e0aSAndreas Gohr     * @return TestResponse
2259e777ceeSAndreas Gohr     */
2269e777ceeSAndreas Gohr    public function post($post = array(), $uri = '/doku.php') {
2279e777ceeSAndreas Gohr        $this->post = array_merge($this->post, $post);
2289e777ceeSAndreas Gohr        $this->setServer('REQUEST_METHOD', 'POST');
2294d053d04SAndreas Gohr        return $this->execute($uri);
2309e777ceeSAndreas Gohr    }
2319e777ceeSAndreas Gohr
2329e777ceeSAndreas Gohr    /**
2339e777ceeSAndreas Gohr     * Simulate a GET request with the given variables
2349e777ceeSAndreas Gohr     *
2351ada9e0aSAndreas Gohr     * @param array $get all the GET parameters to use
2361ada9e0aSAndreas Gohr     * @param string $uri end URL to simulate
2371ada9e0aSAndreas Gohr     * @return TestResponse
2389e777ceeSAndreas Gohr     */
2399e777ceeSAndreas Gohr    public function get($get = array(), $uri = '/doku.php') {
2409e777ceeSAndreas Gohr        $this->get = array_merge($this->get, $get);
2419e777ceeSAndreas Gohr        $this->setServer('REQUEST_METHOD', 'GET');
2424d053d04SAndreas Gohr        return $this->execute($uri);
2439e777ceeSAndreas Gohr    }
2449e777ceeSAndreas Gohr
245572dc222SLarsDW223    /**
246444d58a8SAndreas Gohr     * Callback for ob_start
247444d58a8SAndreas Gohr     *
248444d58a8SAndreas Gohr     * This continues to fill our own buffer, even when some part
249444d58a8SAndreas Gohr     * of the code askes for flushing the buffers
250444d58a8SAndreas Gohr     *
251444d58a8SAndreas Gohr     * @param string $buffer
252444d58a8SAndreas Gohr     */
253444d58a8SAndreas Gohr    public function ob_start_callback($buffer) {
254444d58a8SAndreas Gohr        $this->output_buffer .= $buffer;
255444d58a8SAndreas Gohr    }
256444d58a8SAndreas Gohr
257444d58a8SAndreas Gohr    /**
25827c0c399SAndreas Gohr     * Access the TestRequest from the executed code
25927c0c399SAndreas Gohr     *
26027c0c399SAndreas Gohr     * This allows certain functions to access the TestRequest that is accessing them
26127c0c399SAndreas Gohr     * to add additional info.
26227c0c399SAndreas Gohr     *
26327c0c399SAndreas Gohr     * @return null|TestRequest the currently executed request if any
264572dc222SLarsDW223     */
26527c0c399SAndreas Gohr    public static function getRunning() {
26627c0c399SAndreas Gohr        return self::$running;
26727c0c399SAndreas Gohr    }
26827c0c399SAndreas Gohr
26927c0c399SAndreas Gohr    /**
27027c0c399SAndreas Gohr     * Store data to be read in the response later
27127c0c399SAndreas Gohr     *
27227c0c399SAndreas Gohr     * When called multiple times with the same key, the data is appended to this
27327c0c399SAndreas Gohr     * key's array
27427c0c399SAndreas Gohr     *
27527c0c399SAndreas Gohr     * @param string $key the identifier for this information
27627c0c399SAndreas Gohr     * @param mixed $value arbitrary data to store
27727c0c399SAndreas Gohr     */
27827c0c399SAndreas Gohr    public function addData($key, $value) {
27927c0c399SAndreas Gohr        if(!isset($this->data[$key])) $this->data[$key] = array();
28027c0c399SAndreas Gohr        $this->data[$key][] = $value;
281572dc222SLarsDW223    }
282f8369d7dSTobias Sarnowski}
283