Page 1 of 1

HTTP Response Children??

Posted: Mon Jun 26, 2006 10:29 pm
by Luke
This code is from Arborint's http response class (which i am using for guidence in building my own framework - hope he doesn't mind me posting it). I am trying to figure out what exactly an http response child could be. I understand what an http response is, and it's role/importance, but what is a response child?

Code: Select all

<?php

class A_Http_ResponseChild {
    var $name = '';
    var $children = array();
    var $renderer = null;
    var $headers = array();
    var $redirect = null;
    var $content = '';
	var $sent = false;

    function A_Http_ResponseChild ($name='') {
    	$this->name = $name;
    }
    
    function setHeader($field, $param=null) {
        if (is_array($param)) {
        	foreach ($param as $prm) {
				$this->headers[$field][] = $prm;
        	}
        } else {
			$this->headers[$field][] = $param;
        }
    }

    function getHeaders() {
        return $this->headers;
    }

    function setRedirect($url) {
        $this->redirect = $url;
    }

    function getRedirect() {
        return $this->redirect;
    }

    function setContent($content) {
        $this->content = $content;
    }

    function getContent() {
        return $this->content;
    }

    function setRenderer(&$renderer) {
        $this->renderer =& $renderer;
    }

    function set($name, $var) {
        $this->children[$name] = $var;
    }

    function addChild(&$child) {
        $this->children[$child->name] =& $child;
    }

	function run(&$locator) {
		if ($this->children) {
			$names = array_keys($this->children);
//get headers and redirect from children if set
			foreach ($names as $name) {
				if (is_a($this->children[$name], 'A_Http_ResponseChild')) {
					if ($this->children[$name]->headers) {
						foreach ($this->children[$name]->headers as $field => $value) {
							$this->setHeaders($field, $value);
						}
					}
					if ($this->children[$name]->redirect) {
						$this->redirect = $this->children[$name]->redirect;
					}
				}
			}
// only render if no content and has render
			if (! $this->content && $this->renderer) {
				foreach ($names as $name) {
					if (is_a($this->children[$name], 'A_Http_ResponseChild')) {
						$this->renderer->set($name, $this->children[$name]->run($locator));
					} else {
						$this->renderer->set($name, $this->children[$name]);
					}
				}
				$this->content = $this->renderer->render();
			}
		}
		if (method_exists($this->renderer, 'render')) {
			$this->content = $this->renderer->render();
		}
		return $this->content;
	}
	
}

class A_Http_Response extends A_Http_ResponseChild {

    function A_Http_Response ($name='') {
    	$this->A_Http_ResponseChild($name);
    }
    
    function render() {
        if ($this->redirect) {
        	$base = $_SERVER['SERVER_NAME'] . dirname($_SERVER['SCRIPT_NAME']);
            if (strpos($this->redirect, $base) === false) {
				if (isset($_SERVER["HTTPS"]) && ($_SERVER["HTTPS"] == 'on')) {
					$protocol = 'https://';
				} else {
					$protocol = 'http://';
				}
	            if (substr($base, -1, 1) != '/') {
	            	$base .= '/';
	            }
	            $this->redirect = $protocol . $base . preg_replace('/^[\/\.]*/', '', $this->redirect);
            }
            header('Location: ' . $this->redirect);
        } else {
	        foreach ($this->headers as $field => $params) {
	            if (! is_null($params)) {
	                header($field . ': ' . implode(', ', $params));
	            }
	        }
	        return $this->content;
        }
    }
    	
    function out() {
    	if(!$this->sent){
			echo $this->render();
			$this->sent = true;
		}
    }
    
}

?>

Posted: Tue Jun 27, 2006 3:07 am
by Christopher
There is an example that comes with the code in the "examples/response/" directory with the code. The ResponseChild class is for hierarchical Views using the component/composite patterns (it should be attach() rather than addChild()). I use hierarchical Views so that's why it exists. You can only use the Response class if you like (it inherits much of it's functionality from The ResponseChild).

Each node either has one of the following:

1. a redirect
2. a renderer object with a render() method
4. content string

In addition each child can contribute headers to the full page. It all gets built as a hierarchical template, but each child can have different template types or just be a string. A template lib only needs to support set() and render() methods so wrappers are easy.

So, for example, the outer site layout template can be a smart PHP template, but the content templates that users can edit are safe HTML templates that uses str_replace().