4
4
*/
5
5
6
6
#include "php_agent.h"
7
+ #include "php_error.h"
7
8
#include "php_execute.h"
8
9
#include "php_user_instrument.h"
9
10
#include "php_wrapper.h"
12
13
#include "util_logging.h"
13
14
#include "util_memory.h"
14
15
15
- nr_framework_classification_t nr_cakephp_special_1 (
16
- const char * filename TSRMLS_DC ) {
17
- NR_UNUSED_TSRMLS ;
18
-
19
- if (nr_strcaseidx (filename , "cake/libs/object.php" ) >= 0 ) {
20
- return FRAMEWORK_IS_SPECIAL ;
21
- }
22
-
23
- return FRAMEWORK_IS_NORMAL ;
24
- }
25
-
26
- nr_framework_classification_t nr_cakephp_special_2 (
27
- const char * filename TSRMLS_DC ) {
28
- NR_UNUSED_TSRMLS ;
29
-
30
- if (nr_strcaseidx (filename , "cake/core/app.php" ) >= 0 ) {
31
- return FRAMEWORK_IS_SPECIAL ;
32
- }
33
-
34
- return FRAMEWORK_IS_NORMAL ;
35
- }
36
-
37
- /*
38
- * For CakePHP 1.2 and 1.3 (and possibly earlier versions too) we hook into
39
- * Component::initialize(). This function takes a controller as a parameter
40
- * and we look into the params array of that controller object, and pick up
41
- * the controller and action out of that array.
42
- *
43
- * CakePHP 1.x is end-of-life and no longer supported by the agent.
44
- * Cake PHP 1.x does not support PHP 8+ and this wrapper is not updated for OAPI
45
- * compatibility.
46
- *
47
- */
48
- NR_PHP_WRAPPER (nr_cakephp_name_the_wt_pre20 ) {
49
- zval * arg1 = 0 ;
50
- zval * params ;
51
- zval * czval ;
52
- zval * azval ;
53
- char * controller = 0 ;
54
- char * action = 0 ;
55
- int clen = 0 ;
56
- int alen = 0 ;
57
- char * name ;
58
-
59
- (void )wraprec ;
60
- NR_UNUSED_SPECIALFN ;
61
-
62
- NR_PHP_WRAPPER_REQUIRE_FRAMEWORK (NR_FW_CAKEPHP );
63
-
64
- arg1 = nr_php_arg_get (1 , NR_EXECUTE_ORIG_ARGS TSRMLS_CC );
65
- if (!nr_php_is_zval_valid_object (arg1 )) {
66
- NR_PHP_WRAPPER_CALL ;
67
- goto end ;
68
- }
69
-
70
- NR_PHP_WRAPPER_CALL ;
71
-
72
- params = nr_php_get_zval_object_property (arg1 , "params" TSRMLS_CC );
73
- if (0 == params ) {
74
- nrl_verbosedebug (NRL_FRAMEWORK , "CakePHP: no params found in component" );
75
- goto end ;
76
- }
77
-
78
- if (IS_ARRAY != Z_TYPE_P (params )) {
79
- nrl_verbosedebug (NRL_FRAMEWORK ,
80
- "CakePHP: component params is not an array" );
81
- goto end ;
82
- }
83
-
84
- czval = nr_php_get_zval_object_property (params , "controller" TSRMLS_CC );
85
- if (0 == czval ) {
86
- nrl_verbosedebug (NRL_FRAMEWORK ,
87
- "CakePHP: no params['controller'] in component" );
88
- } else {
89
- clen = Z_STRLEN_P (czval );
90
- controller = (char * )nr_alloca (clen + 1 );
91
- nr_strxcpy (controller , Z_STRVAL_P (czval ), clen );
92
- }
93
-
94
- azval = nr_php_get_zval_object_property (params , "action" TSRMLS_CC );
95
- if (0 == azval ) {
96
- nrl_verbosedebug (NRL_FRAMEWORK ,
97
- "CakePHP: no params['action'] in component" );
98
- } else {
99
- alen = Z_STRLEN_P (azval );
100
- action = (char * )nr_alloca (alen + 1 );
101
- nr_strxcpy (action , Z_STRVAL_P (azval ), alen );
102
- }
103
-
104
- if ((0 == clen ) && (0 == alen )) {
105
- nrl_verbosedebug (NRL_FRAMEWORK ,
106
- "CakePHP: nothing to call the transaction (yet?)" );
107
- goto end ;
108
- }
109
-
110
- name = (char * )nr_alloca (alen + clen + 2 );
111
- if (clen ) {
112
- nr_strcpy (name , controller );
113
- }
114
- if (alen ) {
115
- if (clen ) {
116
- nr_strcat (name , "/" );
117
- nr_strcat (name , action );
118
- } else {
119
- nr_strcpy (name , action );
120
- }
121
- }
122
-
123
- nr_txn_set_path ("CakePHP" , NRPRG (txn ), name , NR_PATH_TYPE_ACTION ,
124
- NR_NOT_OK_TO_OVERWRITE );
125
-
126
- end :
127
- nr_php_arg_release (& arg1 );
128
- }
129
- NR_PHP_WRAPPER_END
16
+ #define PHP_PACKAGE_NAME "cakephp/cakephp"
130
17
131
18
/*
132
- * For CakePHP 2.0 and on, we do things a little differently as the params
133
- * array doesn't exist in the component any more. Instead we hook the
134
- * Controller's invokeAction method. This gets the request as a parameter
135
- * and we get the action from the params array in that object. The
136
- * controller object ($this) has a name, and that name is used (along
137
- * with the word "Controller" appended which is what the CakePHP code does).
138
- *
139
- * CakePHP 2.x is end-of-life and in maintenance mode (critical bugfixes only).
140
- * As such, functionality added in PHP 7.1+ is not well supported.
19
+ * For CakePHP 4.0 and on, we retrieve the current controller object
20
+ * and are able to extract the controller name from that. We then
21
+ * retrieve the request object from the controller and are able to
22
+ * extract the action name from that. We then concatenate the two
23
+ * strings to form the transaction name.
141
24
*
142
25
* txn naming scheme:
143
26
* In this case, `nr_txn_set_path` is called after `NR_PHP_WRAPPER_CALL` with
@@ -147,17 +30,17 @@ NR_PHP_WRAPPER_END
147
30
* default way of calling the wrapped function in func_end.
148
31
*
149
32
*/
150
- NR_PHP_WRAPPER (nr_cakephp_name_the_wt_2 ) {
151
- zval * arg1 = 0 ;
33
+ NR_PHP_WRAPPER (nr_cakephp_name_the_wt_4 ) {
152
34
zval * this_var = 0 ;
153
35
zval * czval = 0 ;
154
36
char * controller = 0 ;
155
37
char * action = 0 ;
156
38
int clen = 0 ;
157
39
int alen = 0 ;
158
40
char * name = 0 ;
159
- zval * params ;
160
- zval * azval ;
41
+ zval * action_zval = NULL ;
42
+ zval * request = NULL ;
43
+ zval action_param ;
161
44
162
45
(void )wraprec ;
163
46
NR_UNUSED_SPECIALFN ;
@@ -193,37 +76,24 @@ NR_PHP_WRAPPER(nr_cakephp_name_the_wt_2) {
193
76
}
194
77
}
195
78
196
- arg1 = nr_php_arg_get (1 , NR_EXECUTE_ORIG_ARGS TSRMLS_CC );
197
- if (!nr_php_is_zval_valid_object (arg1 )) {
198
- NR_PHP_WRAPPER_CALL ;
199
- goto end ;
200
- }
201
-
202
79
NR_PHP_WRAPPER_CALL ;
203
80
204
- params = nr_php_get_zval_object_property ( arg1 , "params" TSRMLS_CC );
205
- if (0 == params ) {
206
- nrl_verbosedebug (NRL_FRAMEWORK , "CakePHP: no params found in request " );
81
+ request = nr_php_call ( this_var , "getRequest" );
82
+ if (! nr_php_is_zval_valid_object ( request ) ) {
83
+ nrl_verbosedebug (NRL_FRAMEWORK , "CakePHP: no request found in controller " );
207
84
goto end ;
208
85
}
209
86
210
- if (IS_ARRAY != Z_TYPE_P (params )) {
211
- nrl_verbosedebug (NRL_FRAMEWORK , "CakePHP: request params is not an array" );
87
+ nr_php_zval_str (& action_param , "action" );
88
+ action_zval = nr_php_call (request , "getParam" , & action_param );
89
+ zval_dtor (& action_param );
90
+ if (!nr_php_is_zval_non_empty_string (action_zval )) {
91
+ nrl_verbosedebug (NRL_FRAMEWORK , "CakePHP: no action param found in request" );
212
92
goto end ;
213
- }
214
-
215
- azval = nr_php_get_zval_object_property (params , "action" TSRMLS_CC );
216
- if (0 == azval ) {
217
- nrl_verbosedebug (NRL_FRAMEWORK , "CakePHP: no params['action'] in request" );
218
93
} else {
219
- if (!nr_php_is_zval_valid_string (azval )) {
220
- nrl_verbosedebug (NRL_FRAMEWORK ,
221
- "CakePHP: no string-valued params['action'] in request" );
222
- } else {
223
- alen = Z_STRLEN_P (azval );
224
- action = (char * )nr_alloca (alen + 1 );
225
- nr_strxcpy (action , Z_STRVAL_P (azval ), alen );
226
- }
94
+ alen = Z_STRLEN_P (action_zval );
95
+ action = (char * )nr_alloca (alen + 1 );
96
+ nr_strxcpy (action , Z_STRVAL_P (action_zval ), alen );
227
97
}
228
98
229
99
if ((0 == clen ) && (0 == alen )) {
@@ -249,92 +119,64 @@ NR_PHP_WRAPPER(nr_cakephp_name_the_wt_2) {
249
119
NR_NOT_OK_TO_OVERWRITE );
250
120
251
121
end :
252
- nr_php_arg_release (& arg1 );
253
122
nr_php_scope_release (& this_var );
123
+ nr_php_zval_free (& request );
124
+ nr_php_zval_free (& action_zval );
254
125
}
255
126
NR_PHP_WRAPPER_END
256
127
257
128
/*
258
- * CakePHP 1.2, 1.3
259
- *
260
- * Dispatch::cakeError will be called if there is a problem during dispatch
261
- * (action or controller not found).
262
- *
263
- * CakePHP 1.x is end-of-life and no longer supported by the agent.
264
- * Cake PHP 1.x does not support PHP 8+ and this wrapper is not updated for OAPI
265
- * compatibility.
129
+ * CakePHP 4.0+
266
130
*
131
+ * Report errors and exceptions caught by CakePHP's error handler.
267
132
*/
268
- NR_PHP_WRAPPER (nr_cakephp_problem_1 ) {
269
- const char * name = "Dispatcher::cakeError" ;
133
+ NR_PHP_WRAPPER (nr_cakephp_error_handler_wrapper ) {
134
+ zval * exception = NULL ;
135
+ char * request_uri = nr_php_get_server_global ("REQUEST_URI" );
270
136
271
- (void )wraprec ;
272
137
NR_UNUSED_SPECIALFN ;
138
+ (void )wraprec ;
273
139
274
140
NR_PHP_WRAPPER_REQUIRE_FRAMEWORK (NR_FW_CAKEPHP );
275
141
276
- nr_txn_set_path ("CakePHP" , NRPRG (txn ), name , NR_PATH_TYPE_ACTION ,
277
- NR_NOT_OK_TO_OVERWRITE );
278
-
279
- NR_PHP_WRAPPER_CALL ;
280
- }
281
- NR_PHP_WRAPPER_END
282
-
283
- /*
284
- * CakePHP 2.0+
285
- *
286
- * If the action or controller is not found during the dispatch process, the
287
- * appropriate Exception will be created and thrown. We wrap the CakeException
288
- * constructor instead of the Exception handler, since CakePHP allows for the
289
- * handler to be completely replaced.
290
- *
291
- * CakePHP 2.x is end-of-life and in maintenance mode (critical bugfixes only).
292
- * As such, functionality added in PHP 7.1+ is not well supported.
293
- *
294
- * txn naming scheme:
295
- * In this case, `nr_txn_set_path` is called before `NR_PHP_WRAPPER_CALL` with
296
- * `NR_NOT_OK_TO_OVERWRITE` and as this corresponds to calling the wrapped
297
- * function in func_begin it needs to be explicitly set as a before_callback to
298
- * ensure OAPI compatibility. This entails that the first wrapped call gets to
299
- * name the txn.
300
- */
301
- NR_PHP_WRAPPER (nr_cakephp_problem_2 ) {
302
- const char * name = "Exception" ;
303
-
304
- (void )wraprec ;
305
- NR_UNUSED_SPECIALFN ;
142
+ exception = nr_php_arg_get (1 , NR_EXECUTE_ORIG_ARGS );
143
+ if (!nr_php_is_zval_valid_object (exception )) {
144
+ nrl_verbosedebug (NRL_FRAMEWORK , "%s: exception is NULL or not an object" ,
145
+ __func__ );
146
+ goto end ;
147
+ }
306
148
307
- NR_PHP_WRAPPER_REQUIRE_FRAMEWORK (NR_FW_CAKEPHP );
149
+ if (NR_SUCCESS
150
+ != nr_php_error_record_exception (
151
+ NRPRG (txn ), exception , nr_php_error_get_priority (E_ERROR ), true,
152
+ "Uncaught exception " , & NRPRG (exception_filters ))) {
153
+ nrl_verbosedebug (NRL_FRAMEWORK , "%s: unable to record exception" , __func__ );
154
+ }
308
155
309
- nr_txn_set_path ("CakePHP" , NRPRG (txn ), name , NR_PATH_TYPE_ACTION ,
310
- NR_NOT_OK_TO_OVERWRITE );
156
+ if (NULL != request_uri ) {
157
+ nr_txn_set_path ("CakePHP Exception" , NRPRG (txn ), request_uri , NR_PATH_TYPE_URI ,
158
+ NR_OK_TO_OVERWRITE );
159
+ } else {
160
+ nrl_verbosedebug (NRL_FRAMEWORK , "%s: request uri is NULL" , __func__ );
161
+ }
311
162
312
- NR_PHP_WRAPPER_CALL ;
163
+ end :
164
+ nr_php_arg_release (& exception );
165
+ nr_free (request_uri );
313
166
}
314
167
NR_PHP_WRAPPER_END
315
168
316
169
/*
317
- * Enable CakePHP 1.2, 1.3
318
- */
319
- void nr_cakephp_enable_1 (TSRMLS_D ) {
320
- nr_php_wrap_user_function (NR_PSTR ("Component::initialize" ),
321
- nr_cakephp_name_the_wt_pre20 TSRMLS_CC );
322
- nr_php_wrap_user_function (NR_PSTR ("Dispatcher::cakeError" ),
323
- nr_cakephp_problem_1 TSRMLS_CC );
324
- }
325
-
326
- /*
327
- * Enable CakePHP 2.0+
170
+ * Enable CakePHP 4.0+
328
171
*/
329
- void nr_cakephp_enable_2 (TSRMLS_D ) {
330
- nr_php_wrap_user_function (NR_PSTR ("Controller::invokeAction" ),
331
- nr_cakephp_name_the_wt_2 TSRMLS_CC );
332
- #if ZEND_MODULE_API_NO >= ZEND_8_0_X_API_NO \
333
- && !defined OVERWRITE_ZEND_EXECUTE_DATA
334
- nr_php_wrap_user_function_before_after_clean (
335
- NR_PSTR ("CakeException::__construct" ), nr_cakephp_problem_2 , NULL , NULL );
336
- #else
337
- nr_php_wrap_user_function (NR_PSTR ("CakeException::__construct" ),
338
- nr_cakephp_problem_2 TSRMLS_CC );
339
- #endif
172
+ void nr_cakephp_enable (TSRMLS_D ) {
173
+ nr_php_wrap_user_function (
174
+ NR_PSTR ("Cake\\Controller\\Controller::invokeAction" ),
175
+ nr_cakephp_name_the_wt_4 );
176
+ nr_php_wrap_user_function (
177
+ NR_PSTR (
178
+ "Cake\\Error\\Middleware\\ErrorHandlerMiddleware::handleException" ),
179
+ nr_cakephp_error_handler_wrapper );
180
+ nr_txn_suggest_package_supportability_metric (NRPRG (txn ), PHP_PACKAGE_NAME ,
181
+ PHP_PACKAGE_VERSION_UNKNOWN );
340
182
}
0 commit comments