/
RequestActionTrait.php
154 lines (146 loc) · 4.71 KB
/
RequestActionTrait.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
<?php
/**
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @since 3.0.0
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Cake\Routing;
use Cake\Core\Configure;
use Cake\Network\Request;
use Cake\Network\Response;
use Cake\Network\Session;
use Cake\Routing\DispatcherFactory;
use Cake\Routing\Router;
/**
* Provides the requestAction() method for doing sub-requests
*
*/
trait RequestActionTrait {
/**
* Calls a controller's method from any location. Can be used to connect controllers together
* or tie plugins into a main application. requestAction can be used to return rendered views
* or fetch the return value from controller actions.
*
* Under the hood this method uses Router::reverse() to convert the $url parameter into a string
* URL. You should use URL formats that are compatible with Router::reverse()
*
* ### Examples
*
* A basic example getting the return value of the controller action:
*
* {{{
* $variables = $this->requestAction('/articles/popular');
* }}}
*
* A basic example of request action to fetch a rendered page without the layout.
*
* {{{
* $viewHtml = $this->requestAction('/articles/popular', ['return']);
* }}}
*
* You can also pass the URL as an array:
*
* {{{
* $vars = $this->requestAction(['controller' => 'articles', 'action' => 'popular']);
* }}}
*
* ### Passing other request data
*
* You can pass POST, GET, COOKIE and other data into the request using the apporpriate keys.
* Cookies can be passed using the `cookies` key. Get parameters can be set with `query` and post
* data can be sent using the `post` key.
*
* {{{
* $vars = $this->requestAction('/articles/popular', [
* 'query' => ['page' = > 1],
* 'cookies' => ['remember_me' => 1],
* ]);
* }}}
*
* ### Sending environment or header values
*
* By default actions dispatched with this method will use the global $_SERVER and $_ENV
* values. If you want to override those values for a request action, you can specify the values:
*
* {{{
* $vars = $this->requestAction('/articles/popular', [
* 'environment' => ['CONTENT_TYPE' => 'application/json']
* ]);
* }}}
*
* ### Transmitting the session
*
* By default actions dispatched with this method will use the standard session object.
* If you want a particular session instance to be used, you need to specify it.
*
* {{{
* $vars = $this->requestAction('/articles/popular', [
* 'session' => new Session($someSessionConfig)
* ]);
* }}}
*
* @param string|array $url String or array-based url. Unlike other url arrays in CakePHP, this
* url will not automatically handle passed arguments in the $url parameter.
* @param array $extra if array includes the key "return" it sets the autoRender to true. Can
* also be used to submit GET/POST data, and passed arguments.
* @return mixed Boolean true or false on success/failure, or contents
* of rendered action if 'return' is set in $extra.
*/
public function requestAction($url, array $extra = array()) {
if (empty($url)) {
return false;
}
if (($index = array_search('return', $extra)) !== false) {
$extra['return'] = 0;
$extra['autoRender'] = 1;
unset($extra[$index]);
}
$extra = array_merge(
['autoRender' => 0, 'return' => 1, 'bare' => 1, 'requested' => 1],
$extra
);
$baseUrl = Configure::read('App.fullBaseUrl');
if (is_string($url) && strpos($url, $baseUrl) === 0) {
$url = Router::normalize(str_replace($baseUrl, '', $url));
}
if (is_string($url)) {
$params = [
'url' => $url
];
} elseif (is_array($url)) {
$params = [
'params' => $url,
'base' => false,
'url' => Router::reverse($url)
];
if (empty($params['params']['pass'])) {
$params['params']['pass'] = [];
}
}
$params['post'] = $params['query'] = [];
if (isset($extra['post'])) {
$params['post'] = $extra['post'];
}
if (isset($extra['query'])) {
$params['query'] = $extra['query'];
}
if (isset($extra['environment'])) {
$params['environment'] = $extra['environment'] + $_SERVER + $_ENV;
}
unset($extra['environment'], $extra['post'], $extra['query']);
$params['session'] = isset($extra['session']) ? $extra['session'] : new Session();
$request = new Request($params);
$request->addParams($extra);
$dispatcher = DispatcherFactory::create();
$result = $dispatcher->dispatch($request, new Response());
Router::popRequest();
return $result;
}
}