808 lines
25 KiB
PHP
Executable File
808 lines
25 KiB
PHP
Executable File
<?php
|
|
namespace Rails\ActionController;
|
|
|
|
use stdClass;
|
|
use Closure;
|
|
use ReflectionClass;
|
|
use ReflectionMethod;
|
|
use ReflectionException;
|
|
use ApplicationController;
|
|
use Rails;
|
|
use Rails\ActionController\ActionController;
|
|
use Rails\ActionController\ExceptionHandler;
|
|
use Rails\ActionView;
|
|
use Rails\Routing\Traits\NamedPathAwareTrait;
|
|
use Rails\Routing\UrlFor;
|
|
|
|
/**
|
|
* This class is expected to be extended by the ApplicationController
|
|
* class, and that one is expected to be extended by the current controller's class.
|
|
* There can't be other extensions for now as they might cause
|
|
* unexpected results.
|
|
*
|
|
* ApplicationController class will be instantiated so its _init()
|
|
* method is called, because it is supposed to be called always, regardless
|
|
* the actual controller.
|
|
*/
|
|
abstract class Base extends ActionController
|
|
{
|
|
use NamedPathAwareTrait;
|
|
|
|
const CONTENT_TYPE_JSON = 'application/json';
|
|
|
|
const CONTENT_TYPE_XML = 'application/xml';
|
|
|
|
const DEFAULT_REDIRECT_STATUS = 302;
|
|
|
|
const APP_CONTROLLER_CLASS = 'ApplicationController';
|
|
|
|
static private $RENDER_OPTIONS = [
|
|
'action','template', 'lambda', 'partial', 'json', 'xml', 'text', 'inline', 'file', 'nothing'
|
|
];
|
|
|
|
/**
|
|
* @see respondWith()
|
|
*/
|
|
private $respondTo = [];
|
|
|
|
private $layout;
|
|
|
|
private $actionRan = false;
|
|
|
|
# Must not include charset.
|
|
private $contentType;
|
|
|
|
private $charset;
|
|
|
|
private $status = 200;
|
|
|
|
private
|
|
/**
|
|
* Variables set to the controller itself will be stored
|
|
* here through __set(), and will be passed to the view.
|
|
*
|
|
* @var stdClass
|
|
* @see vars()
|
|
*/
|
|
$locals,
|
|
|
|
$_array_names = [],
|
|
|
|
/**
|
|
* Extra actions to run according to request format.
|
|
*
|
|
* This accepts the following params:
|
|
* Null: Nothing has been set (default).
|
|
* True: Can respond to format, no action needed.
|
|
* Closure: Can respond to format, run Closure.
|
|
* False: Can't respond to format. Render Nothing with 406.
|
|
*/
|
|
$_respond_action,
|
|
|
|
/**
|
|
* Default variable to respond with.
|
|
*
|
|
* @see respond_with()
|
|
*/
|
|
$_respond_with = [],
|
|
|
|
/**
|
|
* Stores the render parameters.
|
|
*
|
|
* @see render_params()
|
|
* @see _render()
|
|
* @see _redirect_to()
|
|
* @see _set_response_params()
|
|
*/
|
|
$_response_params = [],
|
|
|
|
$redirect_params,
|
|
$render_params,
|
|
|
|
$_response_extra_params = [];
|
|
|
|
/**
|
|
* ReflectionClass for ApplicationController.
|
|
*/
|
|
private $appControllerRefls = [];
|
|
|
|
private $selfRefl;
|
|
|
|
/**
|
|
* Children classes shouldn't override __construct(),
|
|
* they should override init() instead.
|
|
*
|
|
* The classes "ApplicationController" are practically abstract classes.
|
|
* Some methods declared on them (init() and filters()) will be bound to the
|
|
* actual controller class and executed.
|
|
* This will happen with any class called "ApplicationController"
|
|
* under any namespace.
|
|
*/
|
|
public function __construct()
|
|
{
|
|
$class = get_called_class();
|
|
|
|
if (!$this->isAppController($class)) {
|
|
$this->locals = new stdClass();
|
|
$this->selfRefl = new ReflectionClass($class);
|
|
|
|
if (!$this instanceof ExceptionHandler) {
|
|
$this->_set_default_layout();
|
|
$reflection = $this->selfRefl;
|
|
|
|
while (true) {
|
|
$parent = $reflection->getParentClass();
|
|
if ($this->isAppController($parent->getName())) {
|
|
$this->appControllerRefls[] = $parent;
|
|
} elseif ($parent->getName() == __CLASS__) {
|
|
break;
|
|
}
|
|
$reflection = $parent;
|
|
}
|
|
$this->appControllerRefls = array_reverse($this->appControllerRefls);
|
|
$this->run_initializers();
|
|
}
|
|
}
|
|
}
|
|
|
|
public function __set($prop, $val)
|
|
{
|
|
$this->setLocal($prop, $val);
|
|
}
|
|
|
|
public function __get($prop)
|
|
{
|
|
if (!array_key_exists($prop, (array)$this->locals)) {
|
|
throw new Exception\RuntimeException(
|
|
sprintf("Trying to get undefined local '%s'", $prop)
|
|
);
|
|
}
|
|
return $this->locals->$prop;
|
|
}
|
|
|
|
public function __call($method, $params)
|
|
{
|
|
if ($this->isNamedPathMethod($method)) {
|
|
return $this->getNamedPath($method, $params);
|
|
}
|
|
|
|
throw new Exception\BadMethodCallException(
|
|
sprintf("Called to unknown method: %s", $method)
|
|
);
|
|
}
|
|
|
|
public function response_params()
|
|
{
|
|
return $this->_response_params;
|
|
}
|
|
|
|
public function responded()
|
|
{
|
|
return $this->render_params || $this->redirect_params;
|
|
}
|
|
|
|
public function setLocal($name, $value)
|
|
{
|
|
if (is_array($value)) {
|
|
$this->_array_names[] = $name;
|
|
$this->$name = $value;
|
|
} else {
|
|
$this->locals->$name = $value;
|
|
}
|
|
return $this;
|
|
}
|
|
|
|
public function locals()
|
|
{
|
|
foreach ($this->_array_names as $prop_name)
|
|
$this->locals->$prop_name = $this->$prop_name;
|
|
return $this->locals;
|
|
}
|
|
|
|
public function vars()
|
|
{
|
|
return $this->locals();
|
|
}
|
|
|
|
/**
|
|
* Shortcut
|
|
*/
|
|
public function I18n()
|
|
{
|
|
return Rails::services()->get('i18n');
|
|
}
|
|
|
|
public function action_name()
|
|
{
|
|
return Rails::services()->get('inflector')->camelize(Rails::application()->dispatcher()->router()->route()->action, true);
|
|
}
|
|
|
|
public function run_request_action()
|
|
{
|
|
$action = $this->action_name();
|
|
|
|
if (!$this->_action_method_exists($action) && !$this->_view_file_exists()) {
|
|
throw new Exception\UnknownActionException(
|
|
sprintf("The action '%s' could not be found for %s", $action, get_called_class())
|
|
);
|
|
}
|
|
|
|
$this->runFilters('before');
|
|
/**
|
|
* Check if response params where set by the
|
|
* before filters.
|
|
*/
|
|
if (!$this->responded()) {
|
|
if ($this->_action_method_exists($action)) {
|
|
$this->actionRan = true;
|
|
$this->runAction($action);
|
|
}
|
|
$this->runFilters('after');
|
|
}
|
|
|
|
if ($this->redirect_params) {
|
|
$this->_set_redirection();
|
|
} else {
|
|
$this->_parse_response_params();
|
|
$this->_create_response_body();
|
|
}
|
|
}
|
|
|
|
public function actionRan()
|
|
{
|
|
return $this->actionRan;
|
|
}
|
|
|
|
public function status()
|
|
{
|
|
return $this->status;
|
|
}
|
|
|
|
/**
|
|
* This method was created so it can be extended in
|
|
* the controllers with the solely purpose of
|
|
* customizing the handle of Exceptions.
|
|
*/
|
|
protected function runAction($action)
|
|
{
|
|
$this->$action();
|
|
}
|
|
|
|
protected function init()
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Adds view helpers to the load list.
|
|
* Accepts one or many strings.
|
|
*/
|
|
public function helper()
|
|
{
|
|
ActionView\ViewHelpers::addAppHelpers(func_get_args());
|
|
}
|
|
|
|
/**
|
|
* Respond to format
|
|
*
|
|
* Sets to which formats the action will respond.
|
|
* It accepts a list of methods that will be called if the
|
|
* request matches the format.
|
|
*
|
|
* Example:
|
|
* $this->respondTo(array(
|
|
* 'html',
|
|
* 'xml' => array(
|
|
* '_some_method' => array($param_1, $param_2),
|
|
* '_render' => array(array('xml' => $obj), array('status' => 403))
|
|
* )
|
|
* ));
|
|
*
|
|
* Note: The way this function receives its parameters is because we can't use Closures,
|
|
* due to the protected visibility of the methods such as _render().
|
|
*
|
|
* In the case above, it's stated that the action is able to respond to html and xml.
|
|
* In the case of an html request, no further action is needed to respond; therefore,
|
|
* we just list the 'html' format there.
|
|
* In the case of an xml request, the controller will call _some_method($param_1, $param_2)
|
|
* then it will call the _render() method, giving it the variable with which it will respond
|
|
* (an ActiveRecord_Base object, an array, etc), and setting the status to 403.
|
|
* Any request with a format not specified here will be responded with a 406 HTTP status code.
|
|
*
|
|
* By default all requests respond to xml, json and html. If the action receives a json
|
|
* request for example, but no data is set to respond with, the dispatcher will look for
|
|
* the .$format.php file in the views (in this case, .json.php). If the file is missing,
|
|
* which actually is expected to happen, a Dispatcher_TemplateMissing exception will be
|
|
* thrown.
|
|
*
|
|
* @see respond_with()
|
|
*/
|
|
public function respondTo($responses)
|
|
{
|
|
$format = $this->request()->format();
|
|
|
|
foreach ($responses as $fmt => $action) {
|
|
if (is_int($fmt)) {
|
|
$fmt = $action;
|
|
$action = null;
|
|
}
|
|
|
|
if ($fmt !== $format)
|
|
continue;
|
|
|
|
if ($action) {
|
|
if (!$action instanceof Closure) {
|
|
throw new Exception\InvalidArgumentException(sprinft('Only closure can be passed to respondTo, %s passed', gettype($action)));
|
|
}
|
|
$action();
|
|
} else {
|
|
$action = true;
|
|
}
|
|
|
|
$this->_respond_action = $action;
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* The request format is not acceptable.
|
|
* Set to render nothing with 406 status.
|
|
*/
|
|
Rails::log()->message("406 Not Acceptable");
|
|
$this->render(array('nothing' => true), array('status' => 406));
|
|
}
|
|
|
|
public function respondWith($var)
|
|
{
|
|
$format = $this->request()->format();
|
|
|
|
if (!in_array($format, $this->respondTo)) {
|
|
/**
|
|
* The request format is not acceptable.
|
|
* Set to render nothing with 406 status.
|
|
*/
|
|
$this->render(array('nothing' => true), array('status' => 406));
|
|
} else {
|
|
$responses = [];
|
|
foreach ($this->respondTo as $format) {
|
|
if ($format == 'html') {
|
|
$responses[] = 'html';
|
|
} else {
|
|
$responses[$format] = function() use ($var, $format) {
|
|
$this->render([$format => $var]);
|
|
};
|
|
}
|
|
}
|
|
$this->respondTo($responses);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sets layout value.
|
|
*/
|
|
public function layout($value = null)
|
|
{
|
|
if (null === $value)
|
|
return $this->layout;
|
|
else
|
|
$this->layout = $value;
|
|
}
|
|
|
|
public function setLayout($value)
|
|
{
|
|
$this->layout = $value;
|
|
}
|
|
|
|
protected function setRespondTo(array $respondTo)
|
|
{
|
|
$this->respondTo = $respondTo;
|
|
}
|
|
|
|
/**
|
|
* @return array
|
|
*/
|
|
protected function filters()
|
|
{
|
|
return [];
|
|
}
|
|
|
|
protected function render($render_params)
|
|
{
|
|
if ($this->responded()) {
|
|
throw new Exception\DoubleRenderException('Can only render or redirect once per action.');
|
|
}
|
|
|
|
$this->render_params = $render_params;
|
|
}
|
|
|
|
/**
|
|
* Sets a redirection.
|
|
* Accepts ['status' => $http_status] among the $redirect_params.
|
|
*/
|
|
protected function redirectTo($redirect_params)
|
|
{
|
|
if ($this->responded()) {
|
|
throw new Exception\DoubleRenderException('Can only render or redirect once per action.');
|
|
}
|
|
|
|
$this->redirect_params = $redirect_params;
|
|
}
|
|
|
|
/**
|
|
* For now we're only expecting one controller that extends ApplicationController,
|
|
* that extends ActionController_Base.
|
|
* This could change in the future (using Reflections) so there could be more classes
|
|
* extending down to ApplicationController > ActionController_Base
|
|
*/
|
|
protected function runFilters($type)
|
|
{
|
|
$closures = $this->getAppControllersMethod('filters');
|
|
|
|
if ($closures) {
|
|
$filters = [];
|
|
foreach ($closures as $closure) {
|
|
$filters = array_merge_recursive($closure(), $filters);
|
|
}
|
|
$filters = array_merge_recursive($filters, $this->filters());
|
|
} else {
|
|
$filters = $this->filters();
|
|
}
|
|
|
|
if (isset($filters[$type])) {
|
|
/**
|
|
* We have to filter duped methods. We can't use array_unique
|
|
* because the the methods could be like 'method_name' => [ 'only' => [ actions ... ] ]
|
|
* and that will generate "Array to string conversion" error.
|
|
*/
|
|
$ranMethods = [];
|
|
|
|
foreach ($filters[$type] as $methodName => $params) {
|
|
if (!is_array($params)) {
|
|
$methodName = $params;
|
|
$params = [];
|
|
}
|
|
|
|
if ($this->canRunFilterMethod($params, $type) && !in_array($methodName, $ranMethods)) {
|
|
$this->$methodName();
|
|
/**
|
|
* Before-filters may set response params. Running filters stop if one of them does.
|
|
*/
|
|
if ($type == 'before' && $this->responded()) {
|
|
break;
|
|
}
|
|
$ranMethods[] = $methodName;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
protected function setStatus($status)
|
|
{
|
|
$this->status = $status;
|
|
}
|
|
|
|
private function _action_method_exists($action)
|
|
{
|
|
$method_exists = false;
|
|
$called_class = get_called_class();
|
|
$refl = new ReflectionClass($called_class);
|
|
|
|
if ($refl->hasMethod($action)) {
|
|
$method = $refl->getMethod($action);
|
|
if ($method->getDeclaringClass()->getName() == $called_class && $method->isPublic())
|
|
$method_exists = true;
|
|
}
|
|
|
|
return $method_exists;
|
|
}
|
|
|
|
public function urlFor($params)
|
|
{
|
|
$urlfor = new UrlFor($params);
|
|
return $urlfor->url();
|
|
}
|
|
|
|
/**
|
|
* If the method for the requested action doesn't exist in
|
|
* the controller, it's checked if the view file exists.
|
|
*/
|
|
private function _view_file_exists()
|
|
{
|
|
$route = Rails::application()->dispatcher()->router()->route();
|
|
/**
|
|
* Build a simple path for the view file, as there's no support for
|
|
* stuff like modules.
|
|
* Note that the extension is PHP, there's no support for different
|
|
* request formats.
|
|
*/
|
|
$base_path = Rails::config()->paths->views;
|
|
$view_path = $base_path . '/' . $route->path() . '.php';
|
|
return is_file($view_path);
|
|
}
|
|
|
|
private function _set_default_layout()
|
|
{
|
|
$this->layout(Rails::application()->config()->action_view->layout);
|
|
}
|
|
|
|
private function canRunFilterMethod(array $params = [], $filter_type)
|
|
{
|
|
$action = Rails::services()->get('inflector')->camelize($this->request()->action(), false);
|
|
|
|
if (isset($params['only']) && !in_array($action, $params['only'])) {
|
|
return false;
|
|
} elseif (isset($params['except']) && in_array($action, $params['except'])) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private function _parse_response_params()
|
|
{
|
|
if ($this->render_params) {
|
|
if (is_string($this->render_params)) {
|
|
$this->render_params = [ $this->render_params ];
|
|
}
|
|
|
|
if (isset($this->render_params[0])) {
|
|
$param = $this->render_params[0];
|
|
unset($this->render_params[0]);
|
|
|
|
if ($param == 'nothing') {
|
|
$this->render_params['nothing'] = true;
|
|
} elseif (is_int(($pos = strpos($param, '/'))) && $pos > 0) {
|
|
$this->render_params['template'] = $param;
|
|
} elseif ($pos === 0 || strpos($param, ':') === 1) {
|
|
$this->render_params['file'] = $param;
|
|
if (!isset($this->render_params['layout'])) {
|
|
$this->render_params['layout'] = false;
|
|
}
|
|
} else {
|
|
$this->render_params['action'] = $param;
|
|
}
|
|
}
|
|
// else {
|
|
|
|
// }
|
|
}
|
|
// else {
|
|
// $route = Rails::application()->dispatcher()->router()->route();
|
|
// $this->render_params = ['action' => $route->action];
|
|
// }
|
|
}
|
|
|
|
/*
|
|
* Protected so it can be accessed by ExceptionHandler
|
|
*/
|
|
protected function _create_response_body()
|
|
{
|
|
$route = Rails::application()->dispatcher()->router()->route();
|
|
$render_type = false;
|
|
|
|
foreach (self::$RENDER_OPTIONS as $option) {
|
|
if (isset($this->render_params[$option])) {
|
|
$render_type = $option;
|
|
$main_param = $this->render_params[$option];
|
|
unset($this->render_params[$option]);
|
|
}
|
|
}
|
|
|
|
if (!$render_type) {
|
|
$render_type = 'action';
|
|
$main_param = $route->action;
|
|
}
|
|
|
|
// $render_type = key($this->render_params);
|
|
// $main_param = array_shift($this->render_params);
|
|
|
|
|
|
if (isset($this->render_params['status']))
|
|
$this->status = $this->render_params['status'];
|
|
|
|
$class = null;
|
|
|
|
switch ($render_type) {
|
|
case 'action':
|
|
# Cut the 'Controller' part of the class name.
|
|
$path = Rails::services()->get('inflector')->underscore(substr(get_called_class(), 0, -10)) . '/' . $main_param . '.php';
|
|
|
|
// if ($route->namespaces())
|
|
// $path = implode('/', $route->namespaces()) . '/' . $path;
|
|
|
|
$main_param = $path;
|
|
# Fallthrough
|
|
|
|
case 'template':
|
|
$layout = !empty($this->render_params['layout']) ? $this->render_params['layout'] : $this->layout;
|
|
|
|
$ext = pathinfo($main_param, PATHINFO_EXTENSION);
|
|
|
|
if (!$ext) {
|
|
$template_name = $main_param;
|
|
|
|
if ($this->request()->format() == 'html') {
|
|
$ext = 'php';
|
|
} else {
|
|
if ($this->request()->format() == 'xml')
|
|
$this->_response_params['is_xml'] = true;
|
|
$ext = [$this->request()->format(), 'php'];
|
|
|
|
$this->response()->headers()->contentType($this->request()->format());
|
|
}
|
|
} else {
|
|
$pinfo = pathinfo($main_param);
|
|
if ($sub_ext = pathinfo($pinfo['filename'], PATHINFO_EXTENSION)) {
|
|
$pinfo['filename'] = substr($pinfo['filename'], 0, -1 * (1 + strlen($pinfo['filename'])));
|
|
$ext = [$sub_ext, $ext];
|
|
} else {
|
|
|
|
}
|
|
|
|
$template_name = $pinfo['dirname'] . '/' . $pinfo['filename'];
|
|
}
|
|
|
|
$this->_response_params = [
|
|
'layout' => $layout,
|
|
'template_name' => $template_name,
|
|
'extension' => $ext
|
|
];
|
|
|
|
# Here we could choose a different responder according to extensions(?).
|
|
$class = 'Rails\ActionController\Response\Template';
|
|
break;
|
|
|
|
case 'lambda':
|
|
$class = 'Rails\ActionController\Response\Lambda';
|
|
$this->_response_params['lambda'] = $main_param;
|
|
break;
|
|
|
|
case 'partial':
|
|
$class = 'Rails\ActionController\Response\Partial';
|
|
$this->_response_params['partial'] = $main_param;
|
|
break;
|
|
|
|
case 'json':
|
|
$this->contentType = self::CONTENT_TYPE_JSON;
|
|
$this->_response_params = $main_param;
|
|
$class = "Rails\ActionController\Response\Json";
|
|
break;
|
|
|
|
case 'xml':
|
|
$this->contentType = self::CONTENT_TYPE_XML;
|
|
array_unshift($this->_response_params, $main_param);
|
|
$class = "Rails\ActionController\Response\Xml";
|
|
break;
|
|
|
|
case 'text':
|
|
$this->response()->body($main_param);
|
|
break;
|
|
|
|
case 'inline':
|
|
$this->_response_params['code'] = $main_param;
|
|
$this->_response_params['layout'] = $this->layout;
|
|
$class = "Rails\ActionController\Response\Inline";
|
|
break;
|
|
|
|
case 'file':
|
|
$this->_response_params['file'] = $main_param;
|
|
$this->_response_params['layout'] = $this->layout ?: false;
|
|
$class = "Rails\ActionController\Response\File";
|
|
break;
|
|
|
|
case 'nothing':
|
|
break;
|
|
|
|
default:
|
|
throw new Exception\RuntimeException(sprintf("Invalid action render type '%s'", $render_type));
|
|
break;
|
|
}
|
|
|
|
if ($class) {
|
|
$responder = new $class($this->_response_params);
|
|
$responder->render_view();
|
|
$this->response()->body($responder->get_contents());
|
|
}
|
|
|
|
$this->setHeaders();
|
|
}
|
|
|
|
private function _set_redirection()
|
|
{
|
|
$redirect_params = $this->redirect_params;
|
|
|
|
if (!is_array($redirect_params))
|
|
$redirect_params = [$redirect_params];
|
|
|
|
if (!empty($redirect_params['status'])) {
|
|
$status = $redirect_params['status'];
|
|
unset($redirect_params['status']);
|
|
} else {
|
|
$status = self::DEFAULT_REDIRECT_STATUS;
|
|
}
|
|
|
|
$url = Rails::application()->router()->urlFor($redirect_params);
|
|
|
|
$this->response()->headers()->location($url);
|
|
$this->response()->headers()->status($status);
|
|
}
|
|
|
|
/**
|
|
* Runs initializers for both the actual controller class
|
|
* and it's parent ApplicationController, if any.
|
|
*/
|
|
private function run_initializers()
|
|
{
|
|
$method_name = 'init';
|
|
$cn = get_called_class();
|
|
|
|
# Run ApplicationController's init method.
|
|
if ($inits = $this->getAppControllersMethod($method_name)) {
|
|
foreach ($inits as $init) {
|
|
$init = $init->bindTo($this);
|
|
$init();
|
|
}
|
|
}
|
|
|
|
$method = $this->selfRefl->getMethod($method_name);
|
|
if ($method->getDeclaringClass()->getName() == $cn) {
|
|
$this->$method_name();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Searches through all the ApplicationControllers classes for a method,
|
|
* and returns them all.
|
|
*
|
|
* @return array
|
|
*/
|
|
private function getAppControllersMethod($methodName, $scope = '')
|
|
{
|
|
if ($this->appControllerRefls) {
|
|
$methods = [];
|
|
foreach ($this->appControllerRefls as $appRefl) {
|
|
if ($appRefl->hasMethod($methodName)) {
|
|
$method = $appRefl->getMethod($methodName);
|
|
|
|
if ($this->isAppController($method->getDeclaringClass()->getName())) {
|
|
if ($scope) {
|
|
$isScope = 'is' . ucfirst($scope);
|
|
if (!$method->$isScope()) {
|
|
continue;
|
|
}
|
|
}
|
|
$methods[] = $method->getClosure($this);
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($methods) {
|
|
return $methods;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private function setHeaders()
|
|
{
|
|
$headers = $this->response()->headers();
|
|
if (null === $this->charset)
|
|
$this->charset = Rails::application()->config()->action_controller->base->default_charset;
|
|
|
|
if (!$headers->contentType()) {
|
|
if (null === $this->contentType) {
|
|
$this->contentType = 'text/html';
|
|
}
|
|
$contentType = $this->contentType;
|
|
if ($this->charset)
|
|
$contentType .= '; charset=' . $this->charset;
|
|
|
|
$headers->setContentType($contentType);
|
|
}
|
|
|
|
$this->response()->headers()->status($this->status);
|
|
}
|
|
|
|
private function isAppController($class)
|
|
{
|
|
return strpos($class, self::APP_CONTROLLER_CLASS) === (strlen($class) - strlen(self::APP_CONTROLLER_CLASS));
|
|
}
|
|
} |