Skip to content

ModelAndView as HttpResponse #194

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions main/Base/AbstractCollection.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
* *
***************************************************************************/

abstract class AbstractCollection implements Collection
abstract class AbstractCollection implements Collection, IteratorAggregate
{
protected $items = array();

Expand Down Expand Up @@ -49,7 +49,7 @@ public function isEmpty()
{
return (count($this->items) == 0);
}

public function size()
{
return count($this->items);
Expand Down Expand Up @@ -94,5 +94,10 @@ public function has($name)
{
return isset($this->items[$name]);
}

public function getIterator()
{
return new ArrayIterator($this->items);
}
}
?>
55 changes: 55 additions & 0 deletions main/Flow/HttpController.class.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php
/***************************************************************************
* Copyright (C) 2013 by Nikita V. Konstantinov *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation; either version 3 of the *
* License, or (at your option) any later version. *
* *
***************************************************************************/

/**
* @ingroup Flow
**/
abstract class HttpController implements Controller
{
/**
* @return ModelAndView
**/
protected function redirect($url, $status = HttpStatus::CODE_302)
{
return
RedirectResponse::create()->
setUrl($url)->
setStatus(new HttpStatus($status))
;
}

/**
* @return ModelAndView
**/
protected function createNotFoundResponse()
{
return
ModelAndView::create()->
setStatus(
new HttpStatus(HttpStatus::CODE_404)
)
;
}

/**
* @return ModelAndView
**/
protected function createForbiddenResponse()
{
return
ModelAndView::create()->
setStatus(
new HttpStatus(HttpStatus::CODE_403)
)
;
}
}
?>
80 changes: 80 additions & 0 deletions main/Flow/HttpFrontController.class.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?php
/***************************************************************************
* Copyright (C) 2013 by Nikita V. Konstantinov *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation; either version 3 of the *
* License, or (at your option) any later version. *
* *
***************************************************************************/

/**
* @ingroup Flow
**/
abstract class HttpFrontController
{
/**
* @var HttpRequest
*/
protected $request = null;

/**
* @var Controller
*/
protected $controller = null;

/**
* @var ModelAndView
*/
protected $response = null;

/**
* @var ViewResolver
*/
protected $resolver = null;

/**
* @return Controller
*/
abstract protected function getController();

public function __construct(ViewResolver $resolver)
{
$this->resolver = $resolver;
}

public function handleRequest(HttpRequest $request)
{
$this->request = $request;
$this->response = $this->getController()->handleRequest($request);

$this->render()->terminateRequest();

return $this;
}

protected function render()
{
if (is_string($this->response->getView())) {
$this->response->setView(
$this->resolver->resolveViewName(
$this->response->getView()
)
);
}

$this->response->render();

return $this;
}

protected function terminateRequest()
{
if (function_exists('fastcgi_finish_request'))
fastcgi_finish_request();

return $this;
}
}
?>
184 changes: 176 additions & 8 deletions main/Flow/ModelAndView.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,52 @@
/**
* @ingroup Flow
**/
class ModelAndView
class ModelAndView implements HttpResponse
{
private $model = null;

private $view = null;

/**
* @var Model
**/
private $model = null;

/**
* @var View|string
**/
private $view = null;

/**
* @var HttpStatus
**/
private $status = null;

/**
* @var HttpHeaderCollection
**/
private $headerCollection = null;

/**
* @var CookieCollection
**/
private $cookieCollection = null;

/**
* @var bool
**/
private $enabledContentLength = false;

/**
* @return ModelAndView
**/
public static function create()
{
return new self;
return new static();
}

public function __construct()
{
$this->model = new Model();
$this->status = new HttpStatus(HttpStatus::CODE_200);
$this->headerCollection = new HttpHeaderCollection();
$this->cookieCollection = new CookieCollection();
}

/**
Expand Down Expand Up @@ -68,7 +97,10 @@ public function setView($view)

return $this;
}


/**
* @deprecated
**/
public function viewIsRedirect()
{
return
Expand All @@ -78,13 +110,149 @@ public function viewIsRedirect()
&& strpos($this->view, 'redirect') === 0
);
}


/**
* @deprecated
**/
public function viewIsNormal()
{
return (
!$this->viewIsRedirect()
&& $this->view !== View::ERROR_VIEW
);
}

/**
* @return HttpHeaderCollection
**/
public function getHeaderCollection()
{
return $this->headerCollection;
}

/**
* @return CookieCollection
**/
public function getCookieCollection()
{
return $this->cookieCollection;
}

public function enableContentLength()
{
$this->enabledContentLength = true;

return $this;
}

public function disableContentLength()
{
$this->enabledContentLength = false;

return $this;
}

public function setStatus(HttpStatus $status)
{
$this->status = $status;

return $this;
}

/**
* @return HttpStatus
**/
public function getStatus()
{
return $this->status;
}

public function getReasonPhrase()
{
return $this->status->getName();
}

public function getHeaders()
{
return $this->headerCollection->getAll();
}

public function hasHeader($name)
{
return $this->headerCollection->has($name);
}

public function getHeader($name)
{
return $this->headerCollection->get($name);
}

/**
* @throws RuntimeException
**/
public function getBody()
{
if (!$this->view)
return null;

if (is_string($this->view)) {
throw new RuntimeException(
sprintf('View "%s" must be resolved', $this->view)
);
}

ob_start();

try {
$this->view->render($this->model);
} catch (Exception $e) {
ob_end_clean();

throw new RuntimeException(
'Error while rendering view',
(int) $e->getCode(),
$e
);
}

return ob_get_clean();
}

public function render()
{
if ($this->enabledContentLength) {
$content = $this->getBody();
$this->headerCollection->set('Content-Length', strlen($content));
$this->sendHeaders();

echo $content;
} else {
Assert::isInstance($this->view, 'View');

$this->sendHeaders();
$this->view->render($this->model);
}

return $this;
}

public function sendHeaders()
{
if (headers_sent($file, $line)) {
throw new LogicException(
sprintf('Headers are gone at %s:%d', $file, $line)
);
}

header($this->status->toString());

foreach ($this->headerCollection as $name => $valueList)
foreach ($valueList as $value)
header($name.': '.$value, true);

$this->cookieCollection->httpSetAll();

return $this;
}
}
?>
Loading