Get rid of some random stuff in the Http response class, and add more from the
authorChuck Hagenbuch <chuck@horde.org>
Thu, 29 Oct 2009 22:41:14 +0000 (18:41 -0400)
committerChuck Hagenbuch <chuck@horde.org>
Fri, 30 Oct 2009 00:11:54 +0000 (20:11 -0400)
Mad version.

framework/Controller/lib/Horde/Controller/Response/Http.php

index abd4f11..2a99301 100644 (file)
 class Horde_Controller_Response_Http extends Horde_Controller_Response_Base
 {
     /**
-     * Adds the specified cookie to the response.
-     *
-     * This method can be called multiple times to set more than one cookie or
-     * to modify an already set one. Returns true if the adding was successful,
-     * false otherwise.
+     * Cookies sent with response
+     * @var array
+     */
+    protected $_cookie = array();
+
+    /**
+     * Stored session data
+     * @var array
+     */
+    protected $_session = array();
+
+    /**
+     * The url to redirect the request to
+     * @var string
+     */
+    protected $_redirectUrl = null;
+
+    /**
+     * The http status code. Default to OK
+     * @var string
+     */
+    protected $_status = '200 OK';
+
+    /**
+     * HTTP headers to send
+     * @var array
+     */
+    protected $_headers = array();
+
+    /**
+     * prevent cached content (ie)
+     * @var array
+     */
+    protected $_preventCache = true;
+
+    /**
+     * Body of the rendered page
+     * @var string
+     */
+    protected $_body = null;
+
+
+    /*##########################################################################
+    # Construct
+    ##########################################################################*/
+
+    /**
+     * Construct response
+     */
+    public function __construct(){}
+
+
+    /*##########################################################################
+    # Instance methods
+    ##########################################################################*/
+
+    /**
+     * Set the url for redirection
      *
-     * @param    Ismo_Core_Cookie   $cookie   the cookie object to add
-     * @return   boolean                true if the adding was successful,
-     *                                  false otherwise
-     * @access   public
+     * @param   string  $toUrl
      */
-    function addCookie($cookie)
+    public function redirect($toUrl)
     {
-        if (get_class($cookie) == 'ismo_core_cookie' ||
-            get_parent_class($cookie) == 'ismo_core_cookie') {
-            $secure = 0;
-            if ($cookie->isSecure()) {
-                $secure = 1;
-            }
+        /* Alternate 301 branch - should allow choosing status:
+           $this->_status = '301 Moved Permanently';
+           $this->_redirectUrl = $toUrl;
+           $this->_headers["Location: $toUrl"] = true;
+           $this->_headers["Connection: close"] = true;
+        */
 
-            setcookie(  $cookie->getName(),
-                        $cookie->getValue(),
-                        $cookie->getExpire(),
-                        $cookie->getPath(),
-                        $cookie->getDomain(),
-                        $secure );
-
-            return true;
-        }
+        $this->_status = '302 Found';
+        $this->_redirectUrl = $toUrl;
+        $this->_headers["Location: $toUrl"] = true;
+    }
 
-        return false;
+    /**
+     * Page was not found
+     */
+    public function pageNotFound()
+    {
+        $this->_status = '404 Page Not Found';
     }
 
     /**
-     * Deletes the specified cookie from the response.
+     * Send content to the browser.
      *
-     * @param    IsmoCookie   $cookie  the cookie object to delete
-     * @access   public
+     * After the body content has been sent, terminates the execution of the
+     * PHP script.
      */
-    function deleteCookie($cookie)
+    public function send()
     {
-        if (get_class($cookie) == 'ismo_core_cookie' ||
-            get_parent_class($cookie) == 'ismo_core_cookie') {
-            $secure = 0;
-            if ($cookie->isSecure()) {
-                $secure = 1;
-            }
+        // send all headers
+        foreach ($this->getHeaders() as $header => $replace) {
+            header($header, $replace);
+        }
 
-            // set the expiration date to one hour ago
-            $cookie->setExpire(time() - 3600);
+        // set cookies
+        foreach ($this->_cookie as $name => $options) {
+            setcookie($name, $options['value'], $options['expiration'], $options['path']);
+        }
 
-            setcookie(  $cookie->getName(),
-                        $cookie->getValue(),
-                        $cookie->getExpire(),
-                        $cookie->getPath(),
-                        $cookie->getDomain(),
-                        $secure );
+        // set session data
+        foreach ($this->_session as $name => $value) {
+            $_SESSION[$name] = $value;
         }
+
+        // send body
+        print $this->getBody();
     }
 
+
+    /*##########################################################################
+    # Accessors
+    ##########################################################################*/
+
     /**
-     * Adds a response header with the given name and value.
+     * Set a cookie
      *
-     * This method allows response headers to have multiple values. Returns true
-     * if the header could be added, false otherwise. False will be returned
-     * f.g. when the headers have already been sent.  The replace parameter
-     * indicates if an already existing header with the same name should be
-     * replaced or not.
-     *
-     * @param    string  $name      the name of the header
-     * @param    string  $value     the value of the header
-     * @param    boolean $replace   should the header be replaced or not
-     * @return   boolean            true if the header could be set, false
-     *                              otherwise
-     * @access   public
+     * @param   string  $name
+     * @param   string  $value
+     * @param   int     $expiration
+     * @param   string  $path
      */
-    function addHeader($name, $value, $replace)
+    public function setCookie($name, $value, $expiration=0, $path=null)
     {
-        if (headers_sent()) {
-            return false;
-        }
-
-        header("$name: $value", $replace);
-        return true;
+        // only set cookies for this matter by default
+        $this->_cookie[$name] = array('value'      => $value,
+                                      'expiration' => $expiration,
+                                      'path' => isset($path) ? $path : '/');
     }
 
     /**
-     * Sends an error response to the client using the specified status code.
+     * Set a session variable OR all session variables (by array).
      *
-     * Sends an error response to the client using the specified status code.
-     * This will create a page that looks like an HTML-formatted server error
-     * page containing the specifed message (if any), setting the content type
-     * to "text/html", leaving cookies and other headers unmodified.
+     * <code>
+     *  // set single session var
+     *  $this->setSession('NAME', 'my session');
      *
-     * If the headers have already been sent this method returns <b>false</b>
-     * otherwise <b>true</b>. After this method the response should be
-     * considered commited, i.e.  both headers and data have been sent to the
-     * client.
+     *  // set all session vars (overwrites previous single sessions set)
+     *  $this->setSession(array('NAME 1' => 'my session 1',
+     *                          'NAME 2' => 'my session 2'));
+     * </code>
      *
-     * @todo                    decide what the error page should look like
-     * @param    string  $code  the status code to use
-     * @param    string  $msg   the message to show
-     * @return   boolean        <b>true</b> if the error response could be
-     *                          send, <b>false</b> otherwise (if the headers
-     *                          have already been sent)
-     * @access   public
+     * @param   mixed   $name
+     * @param   mixed   $value
      */
-    function sendError($code, $msg = NULL)
+    public function setSession($name, $value=null)
     {
-        if (headers_sent()) {
-            return false;
+        // Set by name or all at once
+        if (is_string($name)) {
+            $this->_session[$name] = $value;
+        } elseif (is_array($name)) {
+            $this->_session = $name;
         }
+    }
 
-        header('HTTP/1.0 '.$code);
-
-        // @todo what kind of HTML page should it be?
-        ?>
-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
-<html><head>
-<title><?php echo $code ?></title>
-</head><body>
-<h1><?php echo $code ?></h1>
-<?php
-    if ($msg != NULL)
+    /**
+     * Add header information
+     *
+     * @param   string  $header
+     * @param   boolean $replace
+     */
+    public function setHeader($header, $replace=true)
     {
-        echo $msg;
+        $this->_headers[$header] = $replace;
     }
-?>
-<hr>
-</body></html>
-<?php
 
-        return true;
+    /**
+     * Set the body of the response
+     *
+     * @param   string  $body
+     */
+    public function setBody($body)
+    {
+        $this->_body = $body;
     }
 
     /**
-     * Sends a temporary redirect respones to the client using the specifed
-     * redirect URL.
+     * Set the HTTP status code
      *
-     * If the headers have already been sent this method returns <b>false</b>
-     * otherwise <b>true</b>. After this method the response should be
-     * considered commited.
+     * @param   string  $status
+     */
+    public function setStatus($status)
+    {
+        $this->_status = $status;
+    }
+
+    /**
+     * Get the headers of the response
      *
-     * Examples:
-     * <code>
-     *   $u = new Ismo_Core_Url("http://a.b.c");
-     *   $response->sendRedirect($u);
-     * </code>
-     * Redirects the browser to http://a.b.c using an Ismo_Core_Url instance.
+     * @return  array
+     */
+    public function getHeaders()
+    {
+        $headers["HTTP/1.1 $this->_status"] = true;
+
+        if ($this->_status == '200 OK') {
+            $headers["Connection: close"] = true;
+            $headers["Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"] = true;
+
+            // Try to keep browser from caching any screen to ensure current data.
+            if ($this->_preventCache && !isset($this->_headers["Expires: 0"])) {
+                $headers["Expires: Mon, 26 Jul 1997 05:00:00 GMT"]             = true;
+                $headers["Cache-Control: no-store, no-cache, must-revalidate"] = true;
+                $headers["Pragma: no-cache"]                                   = true;
+            }
+        }
+        return array_merge($this->_headers, $headers);
+    }
+
+    /**
+     * Get the body of the response
      *
-     * <code>
-     *   $response->sendRedirect("http://d.e.f");
-     * </code>
-     * Redirects the browser to http://d.e.f using a string.
+     * @return  string
+     */
+    public function getBody()
+    {
+        return $this->_body;
+    }
+
+    /**
+     * Get the HTTP status of the response
      *
-     * @param    mixed   $location  url to redirect to, this can either be an
-     *                              Ismo_Core_Url instance or a string
-     * @return   boolean            <b>false</b> if the headers have already
-     *                              been sent, <b>true</b> otherwise
-     * @access   public
+     * @return  string
      */
-    function sendRedirect($location)
+    public function getStatus()
     {
-        if (headers_sent()) {
-            return false;
-        }
+        return $this->_status;
+    }
 
-        if (get_class($location) == 'ismo_core_url') {
-            $location = $location->toString(false);
-        }
+    /**
+     * Get  3 digit http code from the status
+     *
+     * @return  int
+     */
+    public function getStatusCode()
+    {
+        preg_match("/(\d\d\d)/", $this->_status, $matches);
+        return isset($matches[1]) ? (int) $matches[1] : 0;
+    }
 
-        /* so that it works correctly for IE */
-        header('HTTP/1.1 301 Moved Permanently');
-        header('Location: ' . $location);
-        header('Connection: close');
+    /**
+     * @todo charset
+     */
+    public function setContentType($mimeType)
+    {
+        $this->setHeader("Content-Type: $mimeType", $replace=true);
+    }
 
-        return true;
+    /**
+     * Get if the response is a 200 OK
+     *
+     * @return  boolean
+     */
+    public function isOk()
+    {
+        return substr($this->_status, 0, 1) == '2';
     }
 
     /**
-     * Sets the status code for this request.
+     * Get if the response is a redirection
      *
-     * Sets the status code for this response. This method is used to set the
-     * return status code when there is no error (for example, for the status
-     * codes SC_OK or SC_MOVED_TEMPORARILY). If there is an error, and the
-     * caller wishes to provide a message for the response, the sendError()
-     * method should be used instead.
+     * @return  boolean
+     */
+    public function isRedirect()
+    {
+        return substr($this->_status, 0, 1) == '3';
+    }
+
+    /**
+     * Get where the page is redirecting to
      *
-     * @param    string $code    the status code to set
-     * @access   public
-     * @see      sendError()
+     * @return  string
      */
-    function setStatus($code)
+    public function getRedirectUrl()
     {
-        header('HTTP/1.0 ' . $code);
+        return $this->_redirectUrl;
     }
 }