@@ -932,16 +932,36 @@ static void nr_execute_handle_library(const char* filename,
932
932
}
933
933
}
934
934
935
- static void nr_get_composer_package_information () {
935
+ static bool nr_execute_handle_autoload_composer_is_initialized () {
936
+ zend_class_entry * zce = NULL ;
937
+
938
+ if (NULL == (zce = nr_php_find_class ("composer\\installedversions" ))) {
939
+ nrl_verbosedebug (NRL_INSTRUMENT , "Composer\\InstalledVersions class not found" );
940
+ return false;
941
+ };
942
+
943
+ // the class is found - there's hope!
944
+ if (NULL == nr_php_find_class_method (zce , "getinstalledpackages" ) || NULL == nr_php_find_class_method (zce , "getversion" )) {
945
+ nrl_verbosedebug (NRL_INSTRUMENT , "Composer\\InstalledVersions class found, but methods not found" );
946
+ return false;
947
+ }
948
+
949
+ return true;
950
+ }
951
+
952
+ static int nr_execute_handle_autoload_composer_init (const char * vendor_path ) {
953
+ char * code = NULL ;
936
954
zval retval ;
937
955
int result = -1 ;
938
956
939
- if (NRPRG (txn )-> composer_info .inside_eval_string ) {
940
- return ;
957
+ if (nr_execute_handle_autoload_composer_is_initialized ()) {
958
+ nrl_verbosedebug (NRL_INSTRUMENT , "%s: already initialized" , __func__ );
959
+ return NR_SUCCESS ;
941
960
}
942
961
943
- char * check
944
- = ""
962
+ #if 0
963
+ code
964
+ = nr_formatf (""
945
965
"(function() {"
946
966
" try {"
947
967
" if (class_exists('Composer\\InstalledVersions')) {"
@@ -958,13 +978,38 @@ static void nr_get_composer_package_information() {
958
978
" } catch (Exception $e) {"
959
979
" return NULL;"
960
980
" }"
961
- "})();" ;
981
+ "})();" );
982
+ #else
983
+ code = nr_formatf ("include_once '%s/composer/InstalledVersions.php';" , vendor_path );
984
+ #endif
985
+
986
+ result = zend_eval_string (code , & retval , "newrelic\\init_composer_api" );
987
+ if (result != SUCCESS ) {
988
+ nrl_verbosedebug (NRL_INSTRUMENT , "%s: zend_eval_string(%s) failed, result=%d" , __func__ , code , result );
989
+ return NR_FAILURE ;
990
+ }
991
+
992
+ zval_dtor (& retval );
993
+ nr_free (code );
994
+
995
+ // Make sure runtime API is available after loading Composer\\InstalledVersions class:
996
+ if (!nr_execute_handle_autoload_composer_is_initialized ()) {
997
+ nrl_verbosedebug (NRL_INSTRUMENT , "%s: unable to initialize Composer runtime API" , __func__ );
998
+ return NR_FAILURE ;
999
+ }
1000
+
1001
+ return NR_SUCCESS ;
1002
+ }
1003
+
1004
+ static void nr_execute_handle_autoload_composer_get_packages_information (const char * vendor_path ) {
1005
+ zval retval ;
1006
+ int result = -1 ;
962
1007
963
1008
char * getpackagename =
964
1009
""
965
1010
"(function() {"
966
1011
" try {"
967
- " return Composer\\InstalledVersions::getInstalledPackages();"
1012
+ " return \\ Composer\\InstalledVersions::getInstalledPackages();"
968
1013
" } catch (Exception $e) {"
969
1014
" return NULL;"
970
1015
" }"
@@ -974,36 +1019,22 @@ static void nr_get_composer_package_information() {
974
1019
""
975
1020
"(function() {"
976
1021
" try {"
977
- " return Composer\\InstalledVersions::getVersion(\"%s\");"
1022
+ " return \\ Composer\\InstalledVersions::getVersion(\"%s\");"
978
1023
" } catch (Exception $e) {"
979
1024
" return NULL;"
980
1025
" }"
981
1026
"})();" ;
982
1027
983
- NRPRG (txn )-> composer_info .inside_eval_string = 1 ;
984
- result = zend_eval_string (check , & retval , "check if class and methods exist" TSRMLS_CC );
985
- NRPRG (txn )-> composer_info .inside_eval_string = 0 ;
986
-
987
- if (result == SUCCESS ) {
988
- if (Z_TYPE (retval ) == IS_NULL ) {
989
- if (NULL != NRPRG (txn )) {
990
- NRPRG (txn )-> composer_info .api_called = 1 ;
991
- }
992
- nrl_verbosedebug (NRL_TXN , "IS_NULL" );
993
- return ;
994
- } else if (Z_TYPE (retval ) == IS_FALSE ) {
995
- nrl_verbosedebug (NRL_TXN , "IS_FALSE" );
996
- return ;
997
- } else if (Z_TYPE (retval ) != IS_TRUE ) {
998
- nrl_verbosedebug (NRL_TXN , "NOT_TRUE" );
999
- return ;
1000
- }
1028
+ if (NR_SUCCESS != nr_execute_handle_autoload_composer_init (vendor_path )) {
1029
+ nrl_debug (NRL_INSTRUMENT , "%s - unable to initialize Composer runtime API - package info unavailable" , __func__ );
1030
+ return ;
1001
1031
}
1002
- zval_dtor (& retval );
1003
- NRPRG (txn )-> composer_info .inside_eval_string = 1 ;
1032
+
1033
+ nrl_verbosedebug (NRL_INSTRUMENT , "%s - Composer runtime API available" , __func__ );
1034
+
1035
+ #if 1
1004
1036
result = zend_eval_string (getpackagename , & retval ,
1005
1037
"get installed packages by name" TSRMLS_CC );
1006
- NRPRG (txn )-> composer_info .inside_eval_string = 0 ;
1007
1038
if (result == SUCCESS ) {
1008
1039
if (Z_TYPE (retval ) == IS_ARRAY ) {
1009
1040
zval * value ;
@@ -1015,9 +1046,7 @@ static void nr_get_composer_package_information() {
1015
1046
ZEND_HASH_FOREACH_VAL (Z_ARRVAL (retval ), value ) {
1016
1047
if (Z_TYPE_P (value ) == IS_STRING ) {
1017
1048
buf = nr_formatf (getversion , Z_STRVAL_P (value ));
1018
- NRPRG (txn )-> composer_info .inside_eval_string = 1 ;
1019
1049
result2 = zend_eval_string (buf , & retval2 , "retrieve version for packages" );
1020
- NRPRG (txn )-> composer_info .inside_eval_string = 0 ;
1021
1050
nr_free (buf );
1022
1051
if (SUCCESS == result2 ) {
1023
1052
if (nr_php_is_zval_valid_string (& retval2 )) {
@@ -1031,24 +1060,27 @@ static void nr_get_composer_package_information() {
1031
1060
}
1032
1061
ZEND_HASH_FOREACH_END ();
1033
1062
} else {
1034
- if (NULL != NRPRG (txn )) {
1035
- NRPRG (txn )-> composer_info .api_called = 1 ;
1036
- }
1037
1063
zval_dtor (& retval );
1038
1064
return ;
1039
1065
}
1040
1066
zval_dtor (& retval );
1041
- NRPRG (txn )-> composer_info .api_called = 1 ;
1042
1067
}
1068
+ #else
1069
+ zv = nr_php_call (NULL , "Composer\\InstalledVersions::getInstalledPackages" , NULL );
1070
+ if (NULL != zv ) {
1071
+ char strbuf [NR_EXECUTE_DEBUG_STRBUFSZ ];
1072
+ nr_format_zval_for_debug (zv , strbuf , 0 , NR_EXECUTE_DEBUG_STRBUFSZ - 1 ,
1073
+ 0 );
1074
+ nrl_always ("Composer\\InstalledVersions::getInstalledPackages()=%s" ,
1075
+ strbuf );
1076
+ nr_php_zval_free (& zv );
1077
+ }
1078
+ #endif
1043
1079
}
1044
1080
1045
- static bool nr_execute_autoload_is_composer (const char * filename ) {
1046
- #define COMPOSER_MAGIC_FILE "composer/autoload_real.php"
1047
- #define COMPOSER_MAGIC_FILE_LEN (sizeof(COMPOSER_MAGIC_FILE) - 1)
1081
+ static char * nr_execute_handle_autoload_composer_get_vendor_path (const char * filename ) {
1048
1082
char * vendor_path = NULL ; // result of dirname(filename)
1049
- char * composer_magic_file = NULL ; // vendor_path + COMPOSER_MAGIC_FILE
1050
1083
char * cp = NULL ;
1051
- bool composer_detected = false;
1052
1084
1053
1085
// vendor_path = dirname(filename):
1054
1086
// 1. copy filename to vendor_path
@@ -1058,38 +1090,73 @@ static bool nr_execute_autoload_is_composer(const char* filename) {
1058
1090
// 3. replace '/' with '\0' to get the directory path
1059
1091
* cp = '\0' ;
1060
1092
1061
- // composer_magic_file = vendor_path + "/composer/autoload_real.php"
1062
- cp = composer_magic_file = nr_malloc (nr_strlen (vendor_path ) + COMPOSER_MAGIC_FILE_LEN + 2 );
1063
- cp = nr_strcpy (cp , vendor_path );
1064
- * cp ++ = '/' ;
1065
- cp = nr_strcpy (cp , COMPOSER_MAGIC_FILE );
1093
+ return vendor_path ;
1094
+ }
1095
+
1096
+ static bool nr_execute_handle_autoload_composer_file_exists (const char * vendor_path , const char * filename ) {
1097
+ char * composer_magic_file = NULL ; // vendor_path + filename
1098
+ bool file_exists = false;
1066
1099
1100
+ composer_magic_file = nr_formatf ("%s/%s" , vendor_path , filename );
1067
1101
if (0 == nr_access (composer_magic_file , F_OK | R_OK )) {
1068
- nrl_debug (NRL_INSTRUMENT , "detected composer with %s" , composer_magic_file );
1069
- composer_detected = true;
1070
- nr_fw_support_add_library_supportability_metric (NRPRG (txn ), "Composer" );
1102
+ file_exists = true;
1103
+ }
1104
+ nr_free (composer_magic_file );
1105
+ return file_exists ;
1106
+ }
1107
+
1108
+ static void nr_execute_handle_autoload_composer (const char * filename ) {
1109
+ // Composer signature file"
1110
+ #define COMPOSER_MAGIC_FILE_1 "composer/autoload_real.php"
1111
+ #define COMPOSER_MAGIC_FILE_1_LEN (sizeof(COMPOSER_MAGIC_FILE_1) - 1)
1112
+ // Composer runtime API file:
1113
+ #define COMPOSER_MAGIC_FILE_2 "composer/InstalledVersions.php"
1114
+ #define COMPOSER_MAGIC_FILE_2_LEN (sizeof(COMPOSER_MAGIC_FILE_2) - 1)
1115
+ char * vendor_path = NULL ; // result of dirname(filename)
1116
+
1117
+ vendor_path = nr_execute_handle_autoload_composer_get_vendor_path (filename );
1118
+ if (NULL == vendor_path ) {
1119
+ nrl_verbosedebug (NRL_FRAMEWORK , "unable to get vendor path from '%s'" , filename );
1120
+ return ;
1121
+ }
1122
+
1123
+ if (!nr_execute_handle_autoload_composer_file_exists (vendor_path , COMPOSER_MAGIC_FILE_1 )) {
1124
+ nrl_verbosedebug (NRL_FRAMEWORK , "'%s' not found in '%s'" , COMPOSER_MAGIC_FILE_1 , vendor_path );
1125
+ return ;
1126
+ }
1127
+
1128
+ if (!nr_execute_handle_autoload_composer_file_exists (vendor_path , COMPOSER_MAGIC_FILE_2 )) {
1129
+ nrl_verbosedebug (NRL_FRAMEWORK , "'%s' not found in '%s'" , COMPOSER_MAGIC_FILE_2 , vendor_path );
1130
+ return ;
1071
1131
}
1072
1132
1133
+ nrl_verbosedebug (NRL_FRAMEWORK , "detected composer" );
1134
+ NRPRG (txn )-> composer_info .composer_detected = true;
1135
+ nr_fw_support_add_library_supportability_metric (NRPRG (txn ), "Composer" );
1136
+
1137
+ nr_execute_handle_autoload_composer_get_packages_information (vendor_path );
1073
1138
nr_free (vendor_path );
1074
- nr_free (composer_magic_file );
1075
- return composer_detected ;
1076
1139
}
1077
1140
1078
1141
static void nr_execute_handle_autoload (const char * filename , const size_t filename_len ) {
1079
1142
#define AUTOLOAD_MAGIC_FILE "vendor/autoload.php"
1080
1143
#define AUTOLOAD_MAGIC_FILE_LEN (sizeof(AUTOLOAD_MAGIC_FILE) - 1)
1081
1144
1082
1145
if (NRPRG (txn )-> composer_info .autoload_detected ) {
1146
+ // autoload already handled
1083
1147
return ;
1084
1148
}
1085
1149
1086
- if (nr_striendswith (STR_AND_LEN (filename ), AUTOLOAD_MAGIC_FILE , AUTOLOAD_MAGIC_FILE_LEN )) {
1087
- nrl_debug (NRL_INSTRUMENT , "detected autoload with %s, which ends with %s" , filename , AUTOLOAD_MAGIC_FILE );
1088
- NRPRG (txn )-> composer_info .autoload_detected = true;
1089
- nr_fw_support_add_library_supportability_metric (NRPRG (txn ), "Autoloader" );
1090
-
1091
- NRPRG (txn )-> composer_info .composer_detected = nr_execute_autoload_is_composer (filename );
1150
+ if (!nr_striendswith (STR_AND_LEN (filename ), AUTOLOAD_MAGIC_FILE , AUTOLOAD_MAGIC_FILE_LEN )) {
1151
+ // not an autoload file
1152
+ return ;
1092
1153
}
1154
+
1155
+ nrl_debug (NRL_FRAMEWORK , "detected autoload with %s, which ends with %s" , filename , AUTOLOAD_MAGIC_FILE );
1156
+ NRPRG (txn )-> composer_info .autoload_detected = true;
1157
+ nr_fw_support_add_library_supportability_metric (NRPRG (txn ), "Autoloader" );
1158
+
1159
+ nr_execute_handle_autoload_composer (filename );
1093
1160
}
1094
1161
1095
1162
static void nr_execute_handle_logging_framework (const char * filename ,
@@ -1199,9 +1266,6 @@ static void nr_php_execute_file(const zend_op_array* op_array,
1199
1266
1200
1267
nr_php_add_user_instrumentation (TSRMLS_C );
1201
1268
1202
- if (NRPRG (txn )-> composer_info .composer_detected && !NRPRG (txn )-> composer_info .api_called ) {
1203
- nr_get_composer_package_information ();
1204
- }
1205
1269
}
1206
1270
1207
1271
/*
0 commit comments