Skip to content

Commit

Permalink
Merge pull request #4823 from cakephp/issue-4796
Browse files Browse the repository at this point in the history
Add Model.initialize event and rework how Component::initialize() works
  • Loading branch information
ADmad committed Oct 10, 2014
2 parents 187e37c + 6595628 commit 060a41c
Show file tree
Hide file tree
Showing 9 changed files with 193 additions and 135 deletions.
25 changes: 22 additions & 3 deletions src/Controller/Component.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,19 @@
* controller logic that can be composed into a controller. Components also
* provide request life-cycle callbacks for injecting logic at specific points.
*
* ## Initialize hook
*
* Like Controller and Table, this class has an initialize() hook that you can use
* to add custom 'constructor' logic. It is important to remember that each request
* (and sub-request) will only make one instance of any given component.
*
* ## Life cycle callbacks
*
* Components can provide several callbacks that are fired at various stages of the request
* cycle. The available callbacks are:
*
* - `initialize(Event $event)`
* Called before the controller's beforeFilter method.
* - `beforeFilter(Event $event)`
* Called before the controller's beforeFilter method by default.
* - `startup(Event $event)`
* Called after the controller's beforeFilter method, and before the
* controller action is called.
Expand Down Expand Up @@ -99,6 +105,19 @@ public function __construct(ComponentRegistry $registry, array $config = []) {
if (!empty($this->components)) {
$this->_componentMap = $registry->normalizeArray($this->components);
}
$this->initialize($config);
}

/**
* Constructor hook method.
*
* Implement this method to avoid having to overwrite
* the constructor and call parent.
*
* @param array $config The configuration array this component is using.
* @return void
*/
public function initialize(array $config) {
}

/**
Expand Down Expand Up @@ -131,7 +150,7 @@ public function __get($name) {
*/
public function implementedEvents() {
$eventMap = [
'Controller.initialize' => 'initialize',
'Controller.initialize' => 'beforeFilter',
'Controller.startup' => 'startup',
'Controller.beforeRender' => 'beforeRender',
'Controller.beforeRedirect' => 'beforeRedirect',
Expand Down
104 changes: 60 additions & 44 deletions src/Controller/Component/RequestHandlerComponent.php
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,6 @@ class RequestHandlerComponent extends Component {
public function __construct(ComponentRegistry $registry, array $config = array()) {
parent::__construct($registry, $config);
$this->addInputType('xml', array(array($this, 'convertXml')));

$Controller = $registry->getController();
$this->request = $Controller->request;
$this->response = $Controller->response;
}

/**
Expand All @@ -133,7 +129,6 @@ public function __construct(ComponentRegistry $registry, array $config = array()
*/
public function implementedEvents() {
return [
'Controller.initialize' => 'initialize',
'Controller.startup' => 'startup',
'Controller.beforeRender' => 'beforeRender',
'Controller.beforeRedirect' => 'beforeRedirect',
Expand All @@ -147,24 +142,27 @@ public function implementedEvents() {
* of an ajax request indicated using the second header based method above, the type must have
* been configured in {@link Cake\Routing\Router}.
*
* @param Event $event The initialize event that was fired.
* @param array $config The config data.
* @return void
* @see Router::extensions()
*/
public function initialize(Event $event) {
if (isset($this->request->params['_ext'])) {
$this->ext = $this->request->params['_ext'];
public function initialize(array $config) {
$controller = $this->_registry->getController();
$request = $this->request = $controller->request;
$response = $this->response = $controller->response;

if (isset($request->params['_ext'])) {
$this->ext = $request->params['_ext'];
}
if (empty($this->ext) || in_array($this->ext, array('html', 'htm'))) {
$this->_setExtension();
$this->_setExtension($request, $this->response);
}
if (empty($this->ext) && $this->request->is('ajax')) {
if (empty($this->ext) && $request->is('ajax')) {
$this->ext = 'ajax';
}

$classMap = $this->_config['viewClassMap'];
if ($classMap) {
$this->viewClassMap($classMap);
if ($this->_config['viewClassMap']) {
$this->viewClassMap($this->_config['viewClassMap']);
}
}

Expand All @@ -179,15 +177,17 @@ public function initialize(Event $event) {
* If html is one of the preferred types, no content type will be set, this
* is to avoid issues with browsers that prefer html and several other content types.
*
* @param \Cake\Network\Request $request The request instance.
* @param \Cake\Network\Response $response The response instance.
* @return void
*/
protected function _setExtension() {
$accept = $this->request->parseAccept();
protected function _setExtension($request, $response) {
$accept = $request->parseAccept();
if (empty($accept)) {
return;
}

$accepts = $this->response->mapType($accept);
$accepts = $response->mapType($accept);
$preferedTypes = current($accepts);
if (array_intersect($preferedTypes, array('html', 'xhtml'))) {
return;
Expand Down Expand Up @@ -267,29 +267,31 @@ public function convertXml($xml) {

/**
* Handles (fakes) redirects for Ajax requests using requestAction()
* Modifies the $_POST and $_SERVER['REQUEST_METHOD'] to simulate a new GET request.
*
* @param Event $event The Controller.beforeRedirect event.
* @param string|array $url A string or array containing the redirect location
* @param \Cake\Network\Response $response The response object.
* @return void
*/
public function beforeRedirect(Event $event, $url, Response $response) {
if (!$this->request->is('ajax')) {
$request = $this->request;
if (!$request->is('ajax')) {
return;
}
if (empty($url)) {
return;
}
$_SERVER['REQUEST_METHOD'] = 'GET';
foreach ($_POST as $key => $val) {
unset($_POST[$key]);
}
if (is_array($url)) {
$url = Router::url($url + array('base' => false));
}
$controller = $event->subject();
$response->body($controller->requestAction($url, array('return', 'bare' => false)));
$response->body($controller->requestAction($url, [
'return',
'bare' => false,
'environment' => [
'REQUEST_METHOD' => 'GET'
]
]));
$response->send();
$response->stop();
}
Expand All @@ -304,7 +306,9 @@ public function beforeRedirect(Event $event, $url, Response $response) {
* @return bool false if the render process should be aborted
*/
public function beforeRender(Event $event) {
if ($this->_config['checkHttpCache'] && $this->response->checkNotModified($this->request)) {
$response = $this->response;
$request = $this->request;
if ($this->_config['checkHttpCache'] && $response->checkNotModified($request)) {
return false;
}
}
Expand Down Expand Up @@ -343,7 +347,8 @@ public function isAtom() {
* @return bool True if user agent is a mobile web browser
*/
public function isMobile() {
return $this->request->is('mobile') || $this->accepts('wap');
$request = $this->request;
return $request->is('mobile') || $this->accepts('wap');
}

/**
Expand Down Expand Up @@ -378,10 +383,12 @@ public function isWap() {
* if the client accepts one or more elements in the array.
*/
public function accepts($type = null) {
$accepted = $this->request->accepts();
$request = $this->request;
$response = $this->response;
$accepted = $request->accepts();

if (!$type) {
return $this->response->mapType($accepted);
return $response->mapType($accepted);
}
if (is_array($type)) {
foreach ($type as $t) {
Expand All @@ -407,9 +414,10 @@ public function accepts($type = null) {
* in the request content type will be returned.
*/
public function requestedWith($type = null) {
if (!$this->request->is('post') &&
!$this->request->is('put') &&
!$this->request->is('delete')
$request = $this->request;
if (!$request->is('post') &&
!$request->is('put') &&
!$request->is('delete')
) {
return null;
}
Expand All @@ -422,15 +430,16 @@ public function requestedWith($type = null) {
return false;
}

list($contentType) = explode(';', $this->request->env('CONTENT_TYPE'));
list($contentType) = explode(';', $request->env('CONTENT_TYPE'));
if ($contentType === '') {
list($contentType) = explode(';', $this->request->header('CONTENT_TYPE'));
list($contentType) = explode(';', $request->header('CONTENT_TYPE'));
}
$response = $this->response;
if (!$type) {
return $this->response->mapType($contentType);
return $response->mapType($contentType);
}
if (is_string($type)) {
return ($type === $this->response->mapType($contentType));
return ($type === $response->mapType($contentType));
}
}

Expand All @@ -451,12 +460,14 @@ public function requestedWith($type = null) {
* If no type is provided the first preferred type is returned.
*/
public function prefers($type = null) {
$acceptRaw = $this->request->parseAccept();
$request = $this->request;
$response = $this->response;
$acceptRaw = $request->parseAccept();

if (empty($acceptRaw)) {
return $this->ext;
}
$accepts = $this->response->mapType(array_shift($acceptRaw));
$accepts = $response->mapType(array_shift($acceptRaw));

if (!$type) {
if (empty($this->ext) && !empty($accepts)) {
Expand Down Expand Up @@ -535,7 +546,8 @@ public function renderAs(Controller $controller, $type, array $options = array()
$controller->layoutPath = $type;
}

if ($this->response->getMimeType($type)) {
$response = $this->response;
if ($response->getMimeType($type)) {
$this->respondAs($type, $options);
}

Expand Down Expand Up @@ -566,8 +578,10 @@ public function respondAs($type, array $options = array()) {
$options += $defaults;

$cType = $type;
$request = $this->request;
$response = $this->response;
if (strpos($type, '/') === false) {
$cType = $this->response->getMimeType($type);
$cType = $response->getMimeType($type);
}
if (is_array($cType)) {
if (isset($cType[$options['index']])) {
Expand All @@ -585,13 +599,13 @@ public function respondAs($type, array $options = array()) {
return false;
}
if (empty($this->request->params['requested'])) {
$this->response->type($cType);
$response->type($cType);
}
if (!empty($options['charset'])) {
$this->response->charset($options['charset']);
$response->charset($options['charset']);
}
if (!empty($options['attachment'])) {
$this->response->download($options['attachment']);
$response->download($options['attachment']);
}
return true;
}
Expand All @@ -603,7 +617,8 @@ public function respondAs($type, array $options = array()) {
* otherwise null
*/
public function responseType() {
return $this->response->mapType($this->response->type());
$response = $this->response;
return $response->mapType($response->type());
}

/**
Expand All @@ -617,7 +632,8 @@ public function mapAlias($alias) {
if (is_array($alias)) {
return array_map(array($this, 'mapAlias'), $alias);
}
$type = $this->response->getMimeType($alias);
$response = $this->response;
$type = $response->getMimeType($alias);
if ($type) {
if (is_array($type)) {
return $type[0];
Expand Down
12 changes: 8 additions & 4 deletions src/Controller/Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -261,12 +261,16 @@ public function __construct(Request $request = null, Response $response = null,
$this->viewPath = $viewPath;
}

if ($request instanceof Request) {
$this->setRequest($request);
if (!($request instanceof Request)) {
$request = new Request();
}
if ($response instanceof Response) {
$this->response = $response;
$this->setRequest($request);

if (!($response instanceof Response)) {
$response = new Response();
}
$this->response = $response;

if ($eventManager) {
$this->eventManager($eventManager);
}
Expand Down
1 change: 1 addition & 0 deletions src/ORM/Table.php
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ public function __construct(array $config = []) {

$this->initialize($config);
$this->_eventManager->attach($this);
$this->dispatchEvent('Model.initialize');
}

/**
Expand Down

0 comments on commit 060a41c

Please sign in to comment.