Browse Source

Merge pull request #548 from cebe/action-response

implementation of Response tied to actions
tags/2.0.0-beta
Qiang Xue 11 years ago
parent
commit
9d7597d61a
  1. 4
      apps/advanced/backend/controllers/SiteController.php
  2. 6
      apps/advanced/frontend/controllers/SiteController.php
  3. 6
      apps/basic/controllers/SiteController.php
  4. 27
      framework/yii/base/Action.php
  5. 1
      framework/yii/base/Application.php
  6. 23
      framework/yii/base/Controller.php
  7. 8
      framework/yii/base/ErrorHandler.php
  8. 6
      framework/yii/base/Module.php
  9. 37
      framework/yii/console/Application.php
  10. 10
      framework/yii/console/Controller.php
  11. 23
      framework/yii/web/Application.php
  12. 2
      framework/yii/web/CaptchaAction.php
  13. 11
      framework/yii/web/Controller.php
  14. 9
      framework/yii/web/HttpCache.php
  15. 2
      framework/yii/web/Request.php
  16. 9
      framework/yii/web/User.php
  17. 2
      framework/yii/web/VerbFilter.php
  18. 3
      tests/unit/framework/helpers/HtmlTest.php

4
apps/advanced/backend/controllers/SiteController.php

@ -17,7 +17,7 @@ class SiteController extends Controller
{ {
$model = new LoginForm(); $model = new LoginForm();
if ($this->populate($_POST, $model) && $model->login()) { if ($this->populate($_POST, $model) && $model->login()) {
return Yii::$app->response->redirect(array('site/index')); return $this->response->redirect(array('site/index'));
} else { } else {
return $this->render('login', array( return $this->render('login', array(
'model' => $model, 'model' => $model,
@ -28,6 +28,6 @@ class SiteController extends Controller
public function actionLogout() public function actionLogout()
{ {
Yii::$app->user->logout(); Yii::$app->user->logout();
return Yii::$app->response->redirect(array('site/index')); return $this->response->redirect(array('site/index'));
} }
} }

6
apps/advanced/frontend/controllers/SiteController.php

@ -27,7 +27,7 @@ class SiteController extends Controller
{ {
$model = new LoginForm(); $model = new LoginForm();
if ($this->populate($_POST, $model) && $model->login()) { if ($this->populate($_POST, $model) && $model->login()) {
return Yii::$app->response->redirect(array('site/index')); return $this->response->redirect(array('site/index'));
} else { } else {
return $this->render('login', array( return $this->render('login', array(
'model' => $model, 'model' => $model,
@ -38,7 +38,7 @@ class SiteController extends Controller
public function actionLogout() public function actionLogout()
{ {
Yii::$app->user->logout(); Yii::$app->user->logout();
return Yii::$app->response->redirect(array('site/index')); return $this->response->redirect(array('site/index'));
} }
public function actionContact() public function actionContact()
@ -46,7 +46,7 @@ class SiteController extends Controller
$model = new ContactForm; $model = new ContactForm;
if ($this->populate($_POST, $model) && $model->contact(Yii::$app->params['adminEmail'])) { if ($this->populate($_POST, $model) && $model->contact(Yii::$app->params['adminEmail'])) {
Yii::$app->session->setFlash('contactFormSubmitted'); Yii::$app->session->setFlash('contactFormSubmitted');
return Yii::$app->response->refresh(); return $this->response->refresh();
} else { } else {
return $this->render('contact', array( return $this->render('contact', array(
'model' => $model, 'model' => $model,

6
apps/basic/controllers/SiteController.php

@ -27,7 +27,7 @@ class SiteController extends Controller
{ {
$model = new LoginForm(); $model = new LoginForm();
if ($this->populate($_POST, $model) && $model->login()) { if ($this->populate($_POST, $model) && $model->login()) {
return Yii::$app->response->redirect(array('site/index')); return $this->response->redirect(array('site/index'));
} else { } else {
return $this->render('login', array( return $this->render('login', array(
'model' => $model, 'model' => $model,
@ -38,7 +38,7 @@ class SiteController extends Controller
public function actionLogout() public function actionLogout()
{ {
Yii::$app->user->logout(); Yii::$app->user->logout();
return Yii::$app->response->redirect(array('site/index')); return $this->response->redirect(array('site/index'));
} }
public function actionContact() public function actionContact()
@ -46,7 +46,7 @@ class SiteController extends Controller
$model = new ContactForm; $model = new ContactForm;
if ($this->populate($_POST, $model) && $model->contact(Yii::$app->params['adminEmail'])) { if ($this->populate($_POST, $model) && $model->contact(Yii::$app->params['adminEmail'])) {
Yii::$app->session->setFlash('contactFormSubmitted'); Yii::$app->session->setFlash('contactFormSubmitted');
return Yii::$app->response->refresh(); return $this->response->refresh();
} else { } else {
return $this->render('contact', array( return $this->render('contact', array(
'model' => $model, 'model' => $model,

27
framework/yii/base/Action.php

@ -7,6 +7,8 @@
namespace yii\base; namespace yii\base;
use Yii;
/** /**
* Action is the base class for all controller action classes. * Action is the base class for all controller action classes.
* *
@ -39,6 +41,31 @@ class Action extends Component
* @var Controller the controller that owns this action * @var Controller the controller that owns this action
*/ */
public $controller; public $controller;
/**
* @var Response
*/
private $_response;
/**
* @return Response|\yii\console\Response|\yii\web\Response
*/
public function getResponse()
{
if ($this->_response === null) {
// TODO use applications response factory here
//$this->_response = new Response();
}
return $this->_response;
}
/**
* @param Response $response
*/
public function setResponse($response)
{
$this->_response = $response;
}
/** /**
* Constructor. * Constructor.

1
framework/yii/base/Application.php

@ -155,7 +155,6 @@ abstract class Application extends Module
*/ */
abstract public function handleRequest($request); abstract public function handleRequest($request);
private $_runtimePath; private $_runtimePath;
/** /**

23
framework/yii/base/Controller.php

@ -15,7 +15,7 @@ use Yii;
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0 * @since 2.0
*/ */
class Controller extends Component abstract class Controller extends Component
{ {
/** /**
* @event ActionEvent an event raised right before executing a controller action. * @event ActionEvent an event raised right before executing a controller action.
@ -110,22 +110,39 @@ class Controller extends Component
if ($action !== null) { if ($action !== null) {
$oldAction = $this->action; $oldAction = $this->action;
$this->action = $action; $this->action = $action;
$result = null;
if ($this->module->beforeAction($action)) { if ($this->module->beforeAction($action)) {
if ($this->beforeAction($action)) { if ($this->beforeAction($action)) {
$result = $action->runWithParams($params); $result = $action->runWithParams($params);
if ($result !== null) {
$this->handleActionResult($result, $action);
}
$this->afterAction($action); $this->afterAction($action);
} }
$this->module->afterAction($action); $this->module->afterAction($action);
} }
$this->action = $oldAction; $this->action = $oldAction;
return $result; return $action->getResponse();
} else { } else {
throw new InvalidRouteException('Unable to resolve the request: ' . $this->getUniqueId() . '/' . $id); throw new InvalidRouteException('Unable to resolve the request: ' . $this->getUniqueId() . '/' . $id);
} }
} }
/** /**
* Handles the return value of an action
* @param mixed $result
* @param Action $action
*/
protected abstract function handleActionResult(&$result, $action);
/**
* @return Response the response object of the current action. null if no action is running
*/
public function getResponse()
{
return $this->action !== null ? $this->action->getResponse() : null;
}
/**
* Runs a request specified in terms of a route. * Runs a request specified in terms of a route.
* The route can be either an ID of an action within this controller or a complete route consisting * The route can be either an ID of an action within this controller or a complete route consisting
* of module IDs, controller ID and action ID. If the route starts with a slash '/', the parsing of * of module IDs, controller ID and action ID. If the route starts with a slash '/', the parsing of

8
framework/yii/base/ErrorHandler.php

@ -9,6 +9,7 @@ namespace yii\base;
use Yii; use Yii;
use yii\web\HttpException; use yii\web\HttpException;
use yii\web\Response;
/** /**
* ErrorHandler handles uncaught PHP errors and exceptions. * ErrorHandler handles uncaught PHP errors and exceptions.
@ -89,8 +90,13 @@ class ErrorHandler extends Component
$useErrorView = !YII_DEBUG || $exception instanceof UserException; $useErrorView = !YII_DEBUG || $exception instanceof UserException;
$response = Yii::$app->getResponse(); if (Yii::$app->controller !== null) {
$response = Yii::$app->controller->getResponse();
$response->getHeaders()->removeAll(); $response->getHeaders()->removeAll();
}
if (empty($response)) {
$response = new Response();
}
if ($useErrorView && $this->errorAction !== null) { if ($useErrorView && $this->errorAction !== null) {
$result = Yii::$app->runAction($this->errorAction); $result = Yii::$app->runAction($this->errorAction);

6
framework/yii/base/Module.php

@ -571,7 +571,7 @@ abstract class Module extends Component
* If the route is empty, the method will use [[defaultRoute]]. * If the route is empty, the method will use [[defaultRoute]].
* @param string $route the route that specifies the action. * @param string $route the route that specifies the action.
* @param array $params the parameters to be passed to the action * @param array $params the parameters to be passed to the action
* @return mixed the result of the action. * @return Response the resulting response of the action.
* @throws InvalidRouteException if the requested route cannot be resolved into an action successfully * @throws InvalidRouteException if the requested route cannot be resolved into an action successfully
*/ */
public function runAction($route, $params = array()) public function runAction($route, $params = array())
@ -582,9 +582,9 @@ abstract class Module extends Component
list($controller, $actionID) = $parts; list($controller, $actionID) = $parts;
$oldController = Yii::$app->controller; $oldController = Yii::$app->controller;
Yii::$app->controller = $controller; Yii::$app->controller = $controller;
$result = $controller->runAction($actionID, $params); $response = $controller->runAction($actionID, $params);
Yii::$app->controller = $oldController; Yii::$app->controller = $oldController;
return $result; return $response;
} else { } else {
throw new InvalidRouteException('Unable to resolve the request "' . trim($this->getUniqueId() . '/' . $route, '/') . '".'); throw new InvalidRouteException('Unable to resolve the request "' . trim($this->getUniqueId() . '/' . $route, '/') . '".');
} }

37
framework/yii/console/Application.php

@ -88,43 +88,13 @@ class Application extends \yii\base\Application
* Handles the specified request. * Handles the specified request.
* @param Request $request the request to be handled * @param Request $request the request to be handled
* @return Response the resulting response * @return Response the resulting response
* @throws Exception if the route is invalid
*/ */
public function handleRequest($request) public function handleRequest($request)
{ {
list ($route, $params) = $request->resolve(); list ($route, $params) = $request->resolve();
$result = $this->runAction($route, $params);
if ($result instanceof Response) {
return $result;
} else {
$response = $this->getResponse();
$response->exitStatus = (int)$result;
return $response;
}
}
/**
* Returns the response component.
* @return Response the response component
*/
public function getResponse()
{
return $this->getComponent('response');
}
/**
* Runs a controller action specified by a route.
* This method parses the specified route and creates the corresponding child module(s), controller and action
* instances. It then calls [[Controller::runAction()]] to run the action with the given parameters.
* If the route is empty, the method will use [[defaultRoute]].
* @param string $route the route that specifies the action.
* @param array $params the parameters to be passed to the action
* @return integer the status code returned by the action execution. 0 means normal, and other values mean abnormal.
* @throws Exception if the route is invalid
*/
public function runAction($route, $params = array())
{
try { try {
return parent::runAction($route, $params); return $this->runAction($route, $params);
} catch (InvalidRouteException $e) { } catch (InvalidRouteException $e) {
throw new Exception(\Yii::t('yii', 'Unknown command "{command}".', array('{command}' => $route)), 0, $e); throw new Exception(\Yii::t('yii', 'Unknown command "{command}".', array('{command}' => $route)), 0, $e);
} }
@ -156,9 +126,6 @@ class Application extends \yii\base\Application
'request' => array( 'request' => array(
'class' => 'yii\console\Request', 'class' => 'yii\console\Request',
), ),
'response' => array(
'class' => 'yii\console\Response',
),
)); ));
} }
} }

10
framework/yii/console/Controller.php

@ -135,6 +135,16 @@ class Controller extends \yii\base\Controller
} }
/** /**
* Handles the return value of an action
* @param mixed $result
* @param Action $action
*/
protected function handleActionResult(&$result, $action)
{
$action->getResponse()->exitStatus = (int)$result;
}
/**
* Formats a string with ANSI codes * Formats a string with ANSI codes
* *
* You may pass additional parameters using the constants defined in [[yii\helpers\base\Console]]. * You may pass additional parameters using the constants defined in [[yii\helpers\base\Console]].

23
framework/yii/web/Application.php

@ -65,16 +65,7 @@ class Application extends \yii\base\Application
$params = array_splice($this->catchAll, 1); $params = array_splice($this->catchAll, 1);
} }
try { try {
$result = $this->runAction($route, $params); return $this->runAction($route, $params);
if ($result instanceof Response) {
return $result;
} else {
$response = $this->getResponse();
if ($result !== null) {
$response->setContent($result);
}
return $response;
}
} catch (InvalidRouteException $e) { } catch (InvalidRouteException $e) {
throw new HttpException(404, $e->getMessage(), $e->getCode(), $e); throw new HttpException(404, $e->getMessage(), $e->getCode(), $e);
} }
@ -116,15 +107,6 @@ class Application extends \yii\base\Application
} }
/** /**
* Returns the response component.
* @return Response the response component
*/
public function getResponse()
{
return $this->getComponent('response');
}
/**
* Returns the session component. * Returns the session component.
* @return Session the session component * @return Session the session component
*/ */
@ -162,9 +144,6 @@ class Application extends \yii\base\Application
'request' => array( 'request' => array(
'class' => 'yii\web\Request', 'class' => 'yii\web\Request',
), ),
'response' => array(
'class' => 'yii\web\Response',
),
'session' => array( 'session' => array(
'class' => 'yii\web\Session', 'class' => 'yii\web\Session',
), ),

2
framework/yii/web/CaptchaAction.php

@ -325,7 +325,7 @@ class CaptchaAction extends Action
*/ */
protected function setHttpHeaders() protected function setHttpHeaders()
{ {
Yii::$app->getResponse()->getHeaders() $this->getResponse()->getHeaders()
->set('Pragma', 'public') ->set('Pragma', 'public')
->set('Expires', '0') ->set('Expires', '0')
->set('Cache-Control', 'must-revalidate, post-check=0, pre-check=0') ->set('Cache-Control', 'must-revalidate, post-check=0, pre-check=0')

11
framework/yii/web/Controller.php

@ -8,6 +8,7 @@
namespace yii\web; namespace yii\web;
use Yii; use Yii;
use yii\base\Action;
use yii\base\InlineAction; use yii\base\InlineAction;
/** /**
@ -62,6 +63,16 @@ class Controller extends \yii\base\Controller
} }
/** /**
* Handles the return value of an action
* @param mixed $result
* @param Action $action
*/
protected function handleActionResult(&$result, $action)
{
$action->getResponse()->setContent($result);
}
/**
* Creates a URL using the given route and parameters. * Creates a URL using the given route and parameters.
* *
* This method enhances [[UrlManager::createUrl()]] by supporting relative routes. * This method enhances [[UrlManager::createUrl()]] by supporting relative routes.

9
framework/yii/web/HttpCache.php

@ -74,8 +74,8 @@ class HttpCache extends ActionFilter
$etag = $this->generateEtag($seed); $etag = $this->generateEtag($seed);
} }
$this->sendCacheControlHeader(); $response = $action->getResponse();
$response = Yii::$app->getResponse(); $this->sendCacheControlHeader($response);
if ($etag !== null) { if ($etag !== null) {
$response->getHeaders()->set('Etag', $etag); $response->getHeaders()->set('Etag', $etag);
} }
@ -109,12 +109,13 @@ class HttpCache extends ActionFilter
/** /**
* Sends the cache control header to the client * Sends the cache control header to the client
* @param Response $response
* @see cacheControl * @see cacheControl
*/ */
protected function sendCacheControlHeader() protected function sendCacheControlHeader($response)
{ {
session_cache_limiter('public'); session_cache_limiter('public');
$headers = Yii::$app->getResponse()->getHeaders(); $headers = $response->getHeaders();
$headers->set('Pragma'); $headers->set('Pragma');
if ($this->cacheControlHeader !== null) { if ($this->cacheControlHeader !== null) {
$headers->set('Cache-Control', $this->cacheControlHeader); $headers->set('Cache-Control', $this->cacheControlHeader);

2
framework/yii/web/Request.php

@ -788,7 +788,7 @@ class Request extends \yii\base\Request
$this->_csrfCookie = $this->getCookies()->get($this->csrfTokenName); $this->_csrfCookie = $this->getCookies()->get($this->csrfTokenName);
if ($this->_csrfCookie === null) { if ($this->_csrfCookie === null) {
$this->_csrfCookie = $this->createCsrfCookie(); $this->_csrfCookie = $this->createCsrfCookie();
Yii::$app->getResponse()->getCookies()->add($this->_csrfCookie); Yii::$app->controller->getResponse()->getCookies()->add($this->_csrfCookie);
} }
} }

9
framework/yii/web/User.php

@ -283,8 +283,7 @@ class User extends Component
$this->setReturnUrl($request->getUrl()); $this->setReturnUrl($request->getUrl());
} }
if ($this->loginUrl !== null) { if ($this->loginUrl !== null) {
$response = Yii::$app->getResponse(); Yii::$app->controller->getResponse()->redirect($this->loginUrl)->send();
$response->redirect($this->loginUrl)->send();
exit(); exit();
} else { } else {
throw new HttpException(403, Yii::t('yii', 'Login Required')); throw new HttpException(403, Yii::t('yii', 'Login Required'));
@ -372,7 +371,7 @@ class User extends Component
$cookie = new Cookie($this->identityCookie); $cookie = new Cookie($this->identityCookie);
$cookie->value = $value; $cookie->value = $value;
$cookie->expire = time() + (int)$data[2]; $cookie->expire = time() + (int)$data[2];
Yii::$app->getResponse()->getCookies()->add($cookie); Yii::$app->controller->getResponse()->getCookies()->add($cookie);
} }
} }
} }
@ -395,7 +394,7 @@ class User extends Component
$duration, $duration,
)); ));
$cookie->expire = time() + $duration; $cookie->expire = time() + $duration;
Yii::$app->getResponse()->getCookies()->add($cookie); Yii::$app->controller->getResponse()->getCookies()->add($cookie);
} }
/** /**
@ -429,7 +428,7 @@ class User extends Component
$this->sendIdentityCookie($identity, $duration); $this->sendIdentityCookie($identity, $duration);
} }
} elseif ($this->enableAutoLogin) { } elseif ($this->enableAutoLogin) {
Yii::$app->getResponse()->getCookies()->remove(new Cookie($this->identityCookie)); Yii::$app->controller->getResponse()->getCookies()->remove(new Cookie($this->identityCookie));
} }
} }

2
framework/yii/web/VerbFilter.php

@ -80,7 +80,7 @@ class VerbFilter extends Behavior
if (!in_array($verb, $allowed)) { if (!in_array($verb, $allowed)) {
$event->isValid = false; $event->isValid = false;
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.7 // http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.7
Yii::$app->getResponse()->getHeaders()->set('Allow', implode(', ', $allowed)); $event->action->getResponse()->getHeaders()->set('Allow', implode(', ', $allowed));
throw new HttpException(405, 'Method Not Allowed. This url can only handle the following request methods: ' . implode(', ', $allowed)); throw new HttpException(405, 'Method Not Allowed. This url can only handle the following request methods: ' . implode(', ', $allowed));
} }
} }

3
tests/unit/framework/helpers/HtmlTest.php

@ -17,9 +17,6 @@ class HtmlTest extends TestCase
'class' => 'yii\web\Request', 'class' => 'yii\web\Request',
'url' => '/test', 'url' => '/test',
), ),
'response' => array(
'class' => 'yii\web\Response',
),
), ),
)); ));
} }

Loading…
Cancel
Save