├── .gitignore ├── .travis.yml ├── CREDITS ├── CodeTips └── DruidCodeTips.php ├── EXPERIMENTAL ├── LICENSE ├── README.md ├── config.m4 ├── config.w32 ├── druid.c ├── example ├── demo.php └── tpl │ ├── request_full_demo.json │ └── request_tpl_demo.json ├── package.xml ├── php_druid.h ├── tests ├── 001.phpt ├── 002.phpt ├── 003.phpt ├── 004.phpt ├── 005.phpt ├── 006.phpt ├── 007.phpt ├── 008.phpt ├── druid.php └── issue7.php └── travis └── compile.sh /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | *.obj 5 | *.elf 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Libraries 12 | *.lib 13 | *.a 14 | *.la 15 | *.lo 16 | 17 | # Shared objects (inc. Windows DLLs) 18 | *.dll 19 | *.so 20 | *.so.* 21 | *.dylib 22 | 23 | # Executables 24 | *.exe 25 | *.out 26 | *.app 27 | *.i*86 28 | *.x86_64 29 | *.hex 30 | 31 | # Debug files 32 | *.dSYM/ 33 | *.su 34 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | compiler: 4 | - gcc 5 | - clang 6 | 7 | os: 8 | - linux 9 | # - osx 10 | 11 | php: 12 | - 5.4 13 | - 5.5 14 | - 5.6 15 | - 7.0 16 | - 7.1 17 | - 7.2 18 | - nightly 19 | 20 | notifications: 21 | email: neeke@php.net 22 | 23 | env: 24 | - REPORT_EXIT_STATUS=1 NO_INTERACTION=1 25 | 26 | #Compile 27 | before_script: 28 | - ./travis/compile.sh 29 | 30 | script: 31 | - exit 0 32 | -------------------------------------------------------------------------------- /CREDITS: -------------------------------------------------------------------------------- 1 | PHP-Druid 2 | 3 | Lead: 4 | Neeke ( neeke@php.net ) 5 | 6 | Dev: 7 | Neeke ( neeke@php.net ) 8 | Remi Collet 9 | 10 | QA: 11 | Neeke ( neeke@php.net ) 12 | Remi Collet 13 | alex.zhou -------------------------------------------------------------------------------- /CodeTips/DruidCodeTips.php: -------------------------------------------------------------------------------- 1 | debugWitch(TRUE); 43 | 44 | /** 45 | * you can also use default host with druid.host in php.ini/druid.ini 46 | */ 47 | $aHosts = array("http://10.0.3.46:9082/druid/v2/", "http://10.0.3.46:9082/druid/v2/"); 48 | $Druid_1->setDruidHosts($aHosts); 49 | 50 | /** 51 | * demo 1 52 | * 53 | * use tpl build request json 54 | */ 55 | $Druid_1->setTplPath(__DIR__ . '/tpl'); 56 | $result_1 = $Druid_1->getDataByTpl('request_tpl_demo.json', array('@startTimeToEndTime@' => '["2016-12-10T14:06:00.000Z/2016-12-27T14:36:00.000Z"]')); 57 | 58 | 59 | $Druid_2 = Druid::getInstance('druid_2_instance'); 60 | /** 61 | * demo 2 62 | * 63 | * use full request json 64 | */ 65 | $result_2 = $Druid_2->getData(file_get_contents(__DIR__ . '/tpl/request_full_demo.json')); 66 | 67 | var_dump($result_1, $result_2); 68 | var_dump($Druid_1,$Druid_2); 69 | } catch (Exception $e) { 70 | var_dump($e->getCode(), $e->getMessage(), $Druid_1->getDebugInfo(), $Druid_2->getDebugInfo()); 71 | } 72 | ``` 73 | 74 | ## PHP --re 75 | ``` 76 | Extension [ extension #30 Druid version 1.0.0 ] { 77 | 78 | - Dependencies { 79 | Dependency [ json (Required) ] 80 | } 81 | 82 | - INI { 83 | Entry [ druid.host ] 84 | Current = '' 85 | } 86 | Entry [ druid.base_auth_user ] 87 | Current = '' 88 | } 89 | Entry [ druid.base_auth_passport ] 90 | Current = '' 91 | } 92 | Entry [ druid.tpl_path ] 93 | Current = '/data/php-druid/tpl' 94 | } 95 | Entry [ druid.debug ] 96 | Current = '0' 97 | } 98 | Entry [ druid.curl_dns_cache_timeout ] 99 | Current = '1' 100 | } 101 | Entry [ druid.curl_connect_timeout ] 102 | Current = '3' 103 | } 104 | Entry [ druid.curl_timeout ] 105 | Current = '5' 106 | } 107 | } 108 | 109 | - Classes [1] { 110 | Class [ class Druid ] { 111 | 112 | - Constants [3] { 113 | Constant [ public string DRUID_VERSION ] { 1.0.0 } 114 | Constant [ public string DRUID_CONTENT_TYPE ] { Content-Type:application/json } 115 | Constant [ public string DRUID_INSTANCE_DEFAULT ] { default } 116 | } 117 | 118 | - Static properties [1] { 119 | Property [ protected static $Druid ] 120 | } 121 | 122 | - Static methods [1] { 123 | Method [ static public method getInstance ] { 124 | 125 | - Parameters [1] { 126 | Parameter #0 [ $instance_name ] 127 | } 128 | } 129 | } 130 | 131 | - Properties [8] { 132 | Property [ protected $debug ] 133 | Property [ protected $tpl_path ] 134 | Property [ protected $response_debug_info ] 135 | Property [ protected $response_code ] 136 | Property [ protected $_curl_error_no ] 137 | Property [ protected $_curl_error_str ] 138 | Property [ protected $hosts ] 139 | Property [ protected $host_rand ] 140 | } 141 | 142 | - Methods [14] { 143 | Method [ private method __construct ] { 144 | 145 | - Parameters [0] { 146 | } 147 | } 148 | 149 | Method [ private method __clone ] { 150 | } 151 | 152 | Method [ private method __sleep ] { 153 | } 154 | 155 | Method [ private method __wakeup ] { 156 | } 157 | 158 | Method [ public method __destruct ] { 159 | } 160 | 161 | Method [ public method debugWitch ] { 162 | 163 | - Parameters [1] { 164 | Parameter #0 [ $debug ] 165 | } 166 | } 167 | 168 | Method [ public method getDebugWitch ] { 169 | } 170 | 171 | Method [ public method setDruidHosts ] { 172 | 173 | - Parameters [1] { 174 | Parameter #0 [ $hosts ] 175 | } 176 | } 177 | 178 | Method [ public method getDruidHosts ] { 179 | } 180 | 181 | Method [ public method setTplPath ] { 182 | 183 | - Parameters [1] { 184 | Parameter #0 [ $tpl_path ] 185 | } 186 | } 187 | 188 | Method [ public method getTplPath ] { 189 | } 190 | 191 | Method [ public method getData ] { 192 | 193 | - Parameters [2] { 194 | Parameter #0 [ $request_json ] 195 | Parameter #1 [ $content_array ] 196 | } 197 | } 198 | 199 | Method [ public method getDataByTpl ] { 200 | 201 | - Parameters [2] { 202 | Parameter #0 [ $request_json_tpl ] 203 | Parameter #1 [ $content_array ] 204 | } 205 | } 206 | 207 | Method [ public method getDebugInfo ] { 208 | } 209 | } 210 | } 211 | } 212 | } 213 | ``` 214 | 215 | ## CodeTips 216 | ```php 217 | class Druid 218 | { 219 | const DRUID_INSTANCE_DEFAULT = 'default'; 220 | 221 | /** 222 | * @var Druid 223 | */ 224 | static private $Druid = null; 225 | 226 | /** 227 | * @return Druid 228 | */ 229 | static public function getInstance($instance_name) 230 | { 231 | if (self::$Druid == null) { 232 | self::$Druid = array(); 233 | } 234 | 235 | if (!array_key_exists($instance_name, self::$Druid)) { 236 | self::$Druid[$instance_name] = new self(); 237 | } 238 | 239 | return self::$Druid[$instance_name]; 240 | } 241 | 242 | /** 243 | * Druid constructor. 244 | */ 245 | private function __construct() 246 | { 247 | 248 | } 249 | 250 | public function __destruct() 251 | { 252 | 253 | } 254 | 255 | private function __clone() 256 | { 257 | 258 | } 259 | 260 | private function __sleep() 261 | { 262 | 263 | } 264 | 265 | private function __wakeup() 266 | { 267 | 268 | } 269 | 270 | /** 271 | * @param $bool 272 | * 273 | * @return bool 274 | */ 275 | public function debugWitch($bool) 276 | { 277 | return true; 278 | } 279 | 280 | /** 281 | * @return bool 282 | */ 283 | public function getDebugWitch() 284 | { 285 | return true; 286 | } 287 | 288 | /** 289 | * @param array $array 290 | * 291 | * @return bool 292 | */ 293 | public function setDruidHosts(array $array) 294 | { 295 | return true; 296 | } 297 | 298 | /** 299 | * @return array 300 | */ 301 | public function getDruidHosts() 302 | { 303 | return array(); 304 | } 305 | 306 | /** 307 | * @param $tpl_path 308 | * 309 | * @return bool 310 | */ 311 | public function setTplPath($tpl_path) 312 | { 313 | return true; 314 | } 315 | 316 | /** 317 | * @return string 318 | */ 319 | public function getTplPath() 320 | { 321 | return ''; 322 | } 323 | 324 | /** 325 | * @param $request_json 326 | * @param array $array 327 | * 328 | * @return array 329 | */ 330 | public function getData($request_json, array $array = array()) 331 | { 332 | return array(); 333 | } 334 | 335 | /** 336 | * @param $request_json_tpl 337 | * @param array $array 338 | * 339 | * @return array 340 | */ 341 | public function getDataByTpl($request_json_tpl, array $array = array()) 342 | { 343 | return array(); 344 | } 345 | 346 | /** 347 | * @return array 348 | */ 349 | public function getDebugInfo() 350 | { 351 | return array(); 352 | } 353 | 354 | } 355 | ``` 356 | -------------------------------------------------------------------------------- /config.m4: -------------------------------------------------------------------------------- 1 | dnl config.m4 for extension druid 2 | 3 | dnl If your extension references something external, use with: 4 | 5 | PHP_ARG_WITH(druid, for druid support, 6 | Make sure that the comment is aligned: 7 | [ --with-druid Include druid support]) 8 | 9 | PHP_ARG_WITH(curl, for curl protocol support, 10 | [ --with-curl[=DIR] Include curl protocol support]) 11 | 12 | 13 | AC_DEFUN([AC_SMARTAGENT_EPOLL], 14 | [ 15 | AC_MSG_CHECKING([for epoll]) 16 | 17 | AC_TRY_COMPILE( 18 | [ 19 | #include 20 | ], [ 21 | int epollfd; 22 | struct epoll_event e; 23 | 24 | epollfd = epoll_create(1); 25 | if (epollfd < 0) { 26 | return 1; 27 | } 28 | 29 | e.events = EPOLLIN | EPOLLET; 30 | e.data.fd = 0; 31 | 32 | if (epoll_ctl(epollfd, EPOLL_CTL_ADD, 0, &e) == -1) { 33 | return 1; 34 | } 35 | 36 | e.events = 0; 37 | if (epoll_wait(epollfd, &e, 1, 1) < 0) { 38 | return 1; 39 | } 40 | ], [ 41 | AC_DEFINE([HAVE_EPOLL], 1, [do we have epoll?]) 42 | AC_MSG_RESULT([yes]) 43 | ], [ 44 | AC_MSG_RESULT([no]) 45 | ]) 46 | ]) 47 | dnl }}} 48 | 49 | 50 | dnl Otherwise use enable: 51 | 52 | dnl PHP_ARG_ENABLE(druid, whether to enable druid support, 53 | dnl Make sure that the comment is aligned: 54 | dnl [ --enable-druid Enable druid support]) 55 | 56 | if test "$PHP_druid" != "no"; then 57 | if test -r $PHP_CURL/include/curl/easy.h; then 58 | CURL_DIR=$PHP_CURL 59 | else 60 | AC_MSG_CHECKING(for cURL in default path) 61 | for i in /usr/local /usr; do 62 | if test -r $i/include/curl/easy.h; then 63 | CURL_DIR=$i 64 | AC_MSG_RESULT(found in $i) 65 | break 66 | fi 67 | done 68 | fi 69 | 70 | if test -z "$CURL_DIR"; then 71 | AC_MSG_RESULT(not found) 72 | AC_MSG_ERROR(Please reinstall the libcurl distribution - easy.h should be in /include/curl/) 73 | fi 74 | 75 | CURL_CONFIG="curl-config" 76 | AC_MSG_CHECKING(for cURL 7.10.5 or greater) 77 | 78 | if ${CURL_DIR}/bin/curl-config --libs > /dev/null 2>&1; then 79 | CURL_CONFIG=${CURL_DIR}/bin/curl-config 80 | else 81 | if ${CURL_DIR}/curl-config --libs > /dev/null 2>&1; then 82 | CURL_CONFIG=${CURL_DIR}/curl-config 83 | fi 84 | fi 85 | 86 | curl_version_full=`$CURL_CONFIG --version` 87 | curl_version=`echo ${curl_version_full} | sed -e 's/libcurl //' | $AWK 'BEGIN { FS = "."; } { printf "%d", ($1 * 1000 + $2) * 1000 + $3;}'` 88 | if test "$curl_version" -ge 7010005; then 89 | AC_MSG_RESULT($curl_version_full) 90 | CURL_LIBS=`$CURL_CONFIG --libs` 91 | else 92 | AC_MSG_ERROR(cURL version 7.10.5 or later is required to compile php with cURL support) 93 | fi 94 | 95 | PHP_ADD_INCLUDE($CURL_DIR/include) 96 | PHP_EVAL_LIBLINE($CURL_LIBS, DRUID_SHARED_LIBADD) 97 | PHP_ADD_LIBRARY_WITH_PATH(curl, $CURL_DIR/$PHP_LIBDIR, DRUID_SHARED_LIBADD) 98 | 99 | PHP_CHECK_LIBRARY(curl,curl_easy_perform, 100 | [ 101 | AC_DEFINE(HAVE_CURL,1,[ ]) 102 | ],[ 103 | AC_MSG_ERROR(There is something wrong. Please check config.log for more information.) 104 | ],[ 105 | $CURL_LIBS -L$CURL_DIR/$PHP_LIBDIR 106 | ]) 107 | 108 | PHP_CHECK_LIBRARY(curl,curl_version_info, 109 | [ 110 | AC_DEFINE(HAVE_CURL_VERSION_INFO,1,[ ]) 111 | ],[],[ 112 | $CURL_LIBS -L$CURL_DIR/$PHP_LIBDIR 113 | ]) 114 | 115 | PHP_CHECK_LIBRARY(curl,curl_easy_strerror, 116 | [ 117 | AC_DEFINE(HAVE_CURL_EASY_STRERROR,1,[ ]) 118 | ],[],[ 119 | $CURL_LIBS -L$CURL_DIR/$PHP_LIBDIR 120 | ]) 121 | 122 | PHP_NEW_EXTENSION(druid, druid.c, $ext_shared) 123 | PHP_SUBST(DRUID_SHARED_LIBADD) 124 | fi 125 | -------------------------------------------------------------------------------- /config.w32: -------------------------------------------------------------------------------- 1 | // vim:ft=javascript 2 | 3 | ARG_ENABLE("druid", "enable druid support", "no"); 4 | 5 | if (PHP_DRUID != "no") { 6 | EXTENSION("druid", "druid.c"); 7 | 8 | AC_DEFINE("HAVE_DRUID", 1, "Have druid Support"); 9 | } 10 | -------------------------------------------------------------------------------- /druid.c: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | PHP-Druid | 4 | +----------------------------------------------------------------------+ 5 | | This source file is subject to version 2.0 of the Apache license, | 6 | | that is bundled with this package in the file LICENSE, and is | 7 | | available through the world-wide-web at the following url: | 8 | | http://www.apache.org/licenses/LICENSE-2.0.html | 9 | | If you did not receive a copy of the Apache2.0 license and are unable| 10 | | to obtain it through the world-wide-web, please send a note to | 11 | | license@php.net so we can mail you a copy immediately. | 12 | +----------------------------------------------------------------------+ 13 | | Author: Neeke.Gao | 14 | +----------------------------------------------------------------------+ 15 | */ 16 | 17 | #ifdef HAVE_CONFIG_H 18 | #include "config.h" 19 | #endif 20 | 21 | #include "php.h" 22 | #include "php_ini.h" 23 | #include "ext/standard/info.h" 24 | #include "ext/json/php_json.h" 25 | #include "php_druid.h" 26 | #include "ext/standard/php_rand.h" 27 | #include "ext/standard/php_array.h" 28 | #include "ext/standard/file.h" 29 | #include "zend_exceptions.h" 30 | 31 | 32 | 33 | #if PHP_VERSION_ID >= 70000 34 | 35 | #define DRUID_STR_SIZE(s) sizeof(s) - 1 36 | #define DRUID_ZVAL_STRING(z, s) ZVAL_STRING(z, s) 37 | #define DRUID_ZVAL_STRINGL(z, s, l) ZVAL_STRINGL(z, s, l) 38 | #define DRUID_RETURN_STRINGL(k, l) RETURN_STRINGL(k, l) 39 | #define DRUID_ADD_INDEX_STRINGL(z, i, s, l) add_index_stringl(&z, i, s, l) 40 | #define DRUID_ADD_INDEX_LONG(z, i, l) add_index_long(&z, i, l) 41 | #define DRUID_ADD_INDEX_ZVAL(z, i, zn) add_index_zval(&z, i, &zn) 42 | #define DRUID_ADD_ASSOC_LONG_EX(z, s, l, v) add_assoc_long_ex(&z, s, l, (long) v) 43 | #define DRUID_ADD_ASSOC_DOUBLE_EX(z, s, l, v) add_assoc_double_ex(&z, s, l, (double) v) 44 | #define DRUID_ADD_ASSOC_ZVAL_EX(z, s, l, zn) add_assoc_zval_ex(z, s, l, zn) 45 | #define DRUID_ADD_ASSOC_ZVAL_EX_AND(z, s, l, zn) add_assoc_zval_ex(&z, s, l, zn) 46 | #define DRUID_ADD_ASSOC_STRING_EX(a, k, l, s) add_assoc_string_ex(&a, k, l, s) 47 | #define DRUID_ADD_NEXT_INDEX_STRING(a, s) add_next_index_string(a, s) 48 | #define DRUID_ADD_NEXT_INDEX_STRINGL(a, s, l) add_next_index_stringl(a, s, l) 49 | #define DRUID_ZEND_HASH_GET_CURRENT_KEY(ht, key, idx) zend_hash_get_current_key(ht, key, idx) 50 | #define DRUID_ZEND_HASH_INDEX_UPDATE(ht, h, pData, nDataSize, pDest) zend_hash_index_update_ptr(ht, h, pData) 51 | 52 | #define DRUID_ZEND_READ_PROPERTY(ce,z,zl) zend_read_property(ce, z, zl, 1, NULL) 53 | #define DRUID_ZEND_UPDATE_PROPERTY(ce,z,zl,zn) zend_update_property(ce, z, zl, zn) 54 | #define DRUID_ZEND_UPDATE_STATIC_PROPERTY(ce,zl,zn) zend_update_static_property(ce, zl, &zn) 55 | #define DRUID_ZEND_UPDATE_PROPERTY_LONG(ce,z,zl,zn) zend_update_property_long(ce,z,zl,zn) 56 | 57 | #else 58 | 59 | #define DRUID_STR_SIZE(s) strlen(s) + 1 60 | #define DRUID_ZVAL_STRING(z, s) ZVAL_STRING(z, s, 1) 61 | #define DRUID_ZVAL_STRINGL(z, s, l) ZVAL_STRING(z, s, l, 1) 62 | #define DRUID_RETURN_STRINGL(k, l) RETURN_STRINGL(k, l, 1) 63 | #define DRUID_ADD_INDEX_STRINGL(z, i, s, l) add_index_stringl(z, i, s, l, 1) 64 | #define DRUID_ADD_INDEX_LONG(z, i, l) add_index_long(z, i, l) 65 | #define DRUID_ADD_INDEX_ZVAL(z, i, zn) add_index_zval(z, i, zn) 66 | #define DRUID_ADD_ASSOC_LONG_EX(z, s, l, v) add_assoc_long_ex(z, s, l, (long) v) 67 | #define DRUID_ADD_ASSOC_DOUBLE_EX(z, s, l, v) add_assoc_double_ex(z, s, l, (double) v) 68 | #define DRUID_ADD_ASSOC_ZVAL_EX(z, s, l, zn) add_assoc_zval_ex(z, s, l, zn) 69 | #define DRUID_ADD_ASSOC_ZVAL_EX_AND(z, s, l, zn) add_assoc_zval_ex(z, s, l, zn) 70 | #define DRUID_ADD_ASSOC_STRING_EX(a, k, l, s) add_assoc_string_ex(a, k, l, s, 1) 71 | #define DRUID_ADD_NEXT_INDEX_STRING(a, s) add_next_index_string(a, s, 1) 72 | #define DRUID_ADD_NEXT_INDEX_STRINGL(a, s, l) add_next_index_stringl(a, s, l, 1) 73 | #define DRUID_ZEND_HASH_GET_CURRENT_KEY(ht, key, idx) zend_hash_get_current_key(ht, key, idx, 0) 74 | #define DRUID_ZEND_HASH_INDEX_UPDATE(ht, h, pData, nDataSize, pDest) zend_hash_index_update(ht, h, pData, nDataSize, pDest) 75 | 76 | #define DRUID_ZEND_READ_PROPERTY(ce,z,zl) zend_read_property(ce, z, zl, 1 TSRMLS_CC) 77 | #define DRUID_ZEND_UPDATE_PROPERTY(ce,z,zl,zn) zend_update_property(ce, z, zl, zn TSRMLS_CC) 78 | #define DRUID_ZEND_UPDATE_STATIC_PROPERTY(ce,zl,zn) zend_update_static_property(ce, zl, zn TSRMLS_CC) 79 | #define DRUID_ZEND_UPDATE_PROPERTY_LONG(ce,z,zl,zn) zend_update_property_long(ce,z,zl,zn TSRMLS_CC) 80 | #endif 81 | 82 | 83 | ZEND_DECLARE_MODULE_GLOBALS(druid) 84 | 85 | static zend_module_dep druid_deps[] = 86 | { 87 | ZEND_MOD_REQUIRED("json") 88 | #ifdef ZEND_MOD_END 89 | ZEND_MOD_END 90 | #else 91 | {NULL, NULL, NULL} 92 | #endif 93 | }; 94 | 95 | static int le_druid; 96 | 97 | const zend_function_entry druid_functions[] = 98 | { 99 | #ifdef PHP_FE_END 100 | PHP_FE_END 101 | #else 102 | {NULL, NULL, NULL} 103 | #endif 104 | }; 105 | 106 | ZEND_BEGIN_ARG_INFO_EX(druid_void_arginfo, 0, 0, 0) 107 | ZEND_END_ARG_INFO() 108 | 109 | ZEND_BEGIN_ARG_INFO_EX(druid_getinstance_arginfo, 0, 0, 1) 110 | ZEND_ARG_INFO(0, instance_name) 111 | ZEND_END_ARG_INFO() 112 | 113 | ZEND_BEGIN_ARG_INFO_EX(druid_debug_arginfo, 0, 0, 1) 114 | ZEND_ARG_INFO(0, debug) 115 | ZEND_END_ARG_INFO() 116 | 117 | ZEND_BEGIN_ARG_INFO_EX(druid_setdruidhosts_arginfo, 0, 0, 1) 118 | ZEND_ARG_INFO(0, hosts) 119 | ZEND_END_ARG_INFO() 120 | 121 | ZEND_BEGIN_ARG_INFO_EX(druid_settplpath_arginfo, 0, 0, 1) 122 | ZEND_ARG_INFO(0, tpl_path) 123 | ZEND_END_ARG_INFO() 124 | 125 | ZEND_BEGIN_ARG_INFO_EX(druid_getdata_arginfo, 0, 0, 1) 126 | ZEND_ARG_INFO(0, request_json) 127 | ZEND_ARG_INFO(0, content_array) 128 | ZEND_END_ARG_INFO() 129 | 130 | ZEND_BEGIN_ARG_INFO_EX(druid_getdatabytpl_arginfo, 0, 0, 1) 131 | ZEND_ARG_INFO(0, request_json_tpl) 132 | ZEND_ARG_INFO(0, content_array) 133 | ZEND_END_ARG_INFO() 134 | 135 | 136 | const zend_function_entry druid_methods[] = 137 | { 138 | PHP_ME(DRUID_NAME, __construct, druid_void_arginfo, ZEND_ACC_CTOR|ZEND_ACC_PRIVATE) 139 | PHP_ME(DRUID_NAME, __clone, NULL, ZEND_ACC_PRIVATE) 140 | PHP_ME(DRUID_NAME, __sleep, NULL, ZEND_ACC_PRIVATE) 141 | PHP_ME(DRUID_NAME, __wakeup, NULL, ZEND_ACC_PRIVATE) 142 | PHP_ME(DRUID_NAME, __destruct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_DTOR) 143 | PHP_ME(DRUID_NAME, getInstance, druid_getinstance_arginfo, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) 144 | PHP_ME(DRUID_NAME, debugWitch, druid_debug_arginfo, ZEND_ACC_PUBLIC) 145 | PHP_ME(DRUID_NAME, getDebugWitch, NULL, ZEND_ACC_PUBLIC) 146 | PHP_ME(DRUID_NAME, setDruidHosts, druid_setdruidhosts_arginfo, ZEND_ACC_PUBLIC) 147 | PHP_ME(DRUID_NAME, getDruidHosts, NULL, ZEND_ACC_PUBLIC) 148 | PHP_ME(DRUID_NAME, setTplPath, druid_settplpath_arginfo, ZEND_ACC_PUBLIC) 149 | PHP_ME(DRUID_NAME, getTplPath, NULL, ZEND_ACC_PUBLIC) 150 | PHP_ME(DRUID_NAME, getData, druid_getdata_arginfo, ZEND_ACC_PUBLIC) 151 | PHP_ME(DRUID_NAME, getDataByTpl, druid_getdatabytpl_arginfo, ZEND_ACC_PUBLIC) 152 | PHP_ME(DRUID_NAME, getDebugInfo, NULL, ZEND_ACC_PUBLIC) 153 | { 154 | NULL, NULL, NULL 155 | } 156 | }; 157 | 158 | zend_module_entry druid_module_entry = 159 | { 160 | STANDARD_MODULE_HEADER_EX, 161 | NULL, 162 | druid_deps, 163 | DRUID_NAME, 164 | druid_functions, 165 | PHP_MINIT(druid), 166 | PHP_MSHUTDOWN(druid), 167 | PHP_RINIT(druid), 168 | PHP_RSHUTDOWN(druid), 169 | PHP_MINFO(druid), 170 | PHP_DRUID_VERSION, 171 | STANDARD_MODULE_PROPERTIES 172 | }; 173 | 174 | #ifdef COMPILE_DL_DRUID 175 | ZEND_GET_MODULE(druid) 176 | #endif 177 | 178 | PHP_INI_BEGIN() 179 | STD_PHP_INI_ENTRY("druid.host", "", PHP_INI_SYSTEM, OnUpdateString, host, zend_druid_globals, druid_globals) 180 | STD_PHP_INI_ENTRY("druid.base_auth_user", "", PHP_INI_PERDIR, OnUpdateString, base_auth_user, zend_druid_globals, druid_globals) 181 | STD_PHP_INI_ENTRY("druid.base_auth_passport", "", PHP_INI_PERDIR, OnUpdateString, base_auth_passport, zend_druid_globals, druid_globals) 182 | STD_PHP_INI_ENTRY("druid.tpl_path", "/data/php-druid/tpl", PHP_INI_PERDIR, OnUpdateString, tpl_path, zend_druid_globals, druid_globals) 183 | 184 | STD_PHP_INI_BOOLEAN("druid.debug", "0", PHP_INI_ALL, OnUpdateBool, debug, zend_druid_globals, druid_globals) 185 | 186 | STD_PHP_INI_ENTRY("druid.curl_dns_cache_timeout", "1", PHP_INI_ALL, OnUpdateLongGEZero, curl_dns_cache_timeout, zend_druid_globals, druid_globals) 187 | STD_PHP_INI_ENTRY("druid.curl_connect_timeout", "3", PHP_INI_ALL, OnUpdateLongGEZero, curl_connect_timeout, zend_druid_globals, druid_globals) 188 | STD_PHP_INI_ENTRY("druid.curl_timeout", "5", PHP_INI_ALL, OnUpdateLongGEZero, curl_timeout, zend_druid_globals, druid_globals) 189 | PHP_INI_END() 190 | 191 | static void php_druid_init_globals(zend_druid_globals *druid_globals) 192 | { 193 | 194 | } 195 | 196 | PHP_MINIT_FUNCTION(druid) 197 | { 198 | zend_class_entry ce; 199 | 200 | ZEND_INIT_MODULE_GLOBALS(druid, php_druid_init_globals, NULL); 201 | REGISTER_INI_ENTRIES(); 202 | 203 | INIT_CLASS_ENTRY(ce, DRUID_NAME, druid_methods); 204 | 205 | #if PHP_VERSION_ID >= 70000 206 | druid_ce = zend_register_internal_class_ex(&ce, NULL); 207 | #else 208 | druid_ce = zend_register_internal_class_ex(&ce, NULL, NULL TSRMLS_CC); 209 | #endif 210 | 211 | zend_declare_class_constant_stringl(druid_ce,ZEND_STRL("DRUID_VERSION"),ZEND_STRL(PHP_DRUID_VERSION) TSRMLS_CC); 212 | zend_declare_class_constant_stringl(druid_ce,ZEND_STRL("DRUID_CONTENT_TYPE"),ZEND_STRL(DRUID_CONTENT_TYPE) TSRMLS_CC); 213 | zend_declare_class_constant_stringl(druid_ce,ZEND_STRL("DRUID_INSTANCE_DEFAULT"),ZEND_STRL(DRUID_INSTANCE_DEFAULT) TSRMLS_CC); 214 | 215 | zend_declare_property_null(druid_ce, ZEND_STRL(DRUID_NAME), ZEND_ACC_STATIC | ZEND_ACC_PROTECTED TSRMLS_CC); 216 | zend_declare_property_bool(druid_ce, ZEND_STRL(DRUID_PROPERTY_DEBUG), 0, ZEND_ACC_PROTECTED TSRMLS_CC); 217 | zend_declare_property_null(druid_ce, ZEND_STRL(DRUID_PROPERTY_TPL_PATH), ZEND_ACC_PROTECTED TSRMLS_CC); 218 | 219 | zend_declare_property_null(druid_ce, ZEND_STRL(DRUID_PROPERTY_RESPONSE_INFO), ZEND_ACC_PROTECTED TSRMLS_CC); 220 | zend_declare_property_long(druid_ce, ZEND_STRL(DRUID_PROPERTY_RESPONSE_CODE),0, ZEND_ACC_PROTECTED TSRMLS_CC); 221 | 222 | zend_declare_property_long(druid_ce, ZEND_STRL(DRUID_PROPERTY_CURL_ERR_NO),0, ZEND_ACC_PROTECTED TSRMLS_CC); 223 | zend_declare_property_null(druid_ce, ZEND_STRL(DRUID_PROPERTY_CURL_ERR_STR), ZEND_ACC_PROTECTED TSRMLS_CC); 224 | 225 | zend_declare_property_null(druid_ce, ZEND_STRL(DRUID_PROPERTY_HOSTS), ZEND_ACC_PROTECTED TSRMLS_CC); 226 | zend_declare_property_bool(druid_ce, ZEND_STRL(DRUID_PROPERTY_HOST_RAND), 0, ZEND_ACC_PROTECTED TSRMLS_CC); 227 | 228 | return SUCCESS; 229 | } 230 | /* }}} */ 231 | 232 | PHP_MSHUTDOWN_FUNCTION(druid) 233 | { 234 | 235 | UNREGISTER_INI_ENTRIES(); 236 | 237 | return SUCCESS; 238 | } 239 | 240 | PHP_RINIT_FUNCTION(druid) 241 | { 242 | return SUCCESS; 243 | } 244 | 245 | PHP_RSHUTDOWN_FUNCTION(druid) 246 | { 247 | return SUCCESS; 248 | } 249 | 250 | PHP_MINFO_FUNCTION(druid) 251 | { 252 | php_info_print_table_start(); 253 | php_info_print_table_header(2, "druid support", "enabled"); 254 | php_info_print_table_row(2, "druid version", PHP_DRUID_VERSION); 255 | php_info_print_table_row(2, "druid credits", DRUID_CREDITS); 256 | php_info_print_table_end(); 257 | 258 | DISPLAY_INI_ENTRIES(); 259 | 260 | } 261 | 262 | PHP_METHOD(DRUID_NAME, getInstance) 263 | { 264 | int argc = ZEND_NUM_ARGS(); 265 | char *instance_name; 266 | zval *get_instance_array = NULL; 267 | 268 | #if PHP_VERSION_ID >= 70000 269 | size_t instance_name_len; 270 | zval *ppzval = NULL; 271 | zval set_instance_array; 272 | #else 273 | int instance_name_len; 274 | zval **ppzval = NULL; 275 | zval *set_instance_array; 276 | #endif 277 | 278 | zval *instance; 279 | 280 | //In php7 , this params instance_name can not be empty. 281 | #if PHP_VERSION_ID >= 70000 282 | if (zend_parse_parameters(argc TSRMLS_CC, "s", &instance_name, &instance_name_len) == FAILURE) 283 | { 284 | zend_throw_exception(php_com_exception_class_entry,"The instance_name can not be empty,you can use Druid::DRUID_INSTANCE_DEFAULT",999 TSRMLS_CC); 285 | RETURN_FALSE; 286 | } 287 | #else 288 | if (zend_parse_parameters(argc TSRMLS_CC, "|s", &instance_name, &instance_name_len) == FAILURE) 289 | { 290 | RETURN_FALSE; 291 | } 292 | #endif 293 | 294 | if (argc < 1) 295 | { 296 | instance_name = DRUID_INSTANCE_DEFAULT; 297 | instance_name_len = DRUID_INSTANCE_DEFAULT_LEN; 298 | } 299 | 300 | get_instance_array = zend_read_static_property(druid_ce, ZEND_STRL(DRUID_NAME), 1 TSRMLS_CC); 301 | 302 | if (get_instance_array && Z_TYPE_P(get_instance_array) == IS_ARRAY) 303 | { 304 | 305 | #if PHP_VERSION_ID >= 70000 306 | if ((ppzval = zend_hash_str_find(Z_ARRVAL_P(get_instance_array),instance_name,instance_name_len)) != NULL) 307 | { 308 | RETURN_ZVAL(ppzval, 1, 0); 309 | } 310 | else 311 | { 312 | goto initInstance; 313 | } 314 | #else 315 | if (zend_hash_find(Z_ARRVAL_P(get_instance_array), ZEND_STRL(instance_name), (void **)&ppzval) == SUCCESS ) 316 | { 317 | RETURN_ZVAL(*ppzval, 1, 0); 318 | } 319 | else 320 | { 321 | goto initInstance; 322 | } 323 | #endif 324 | } 325 | else 326 | { 327 | #if PHP_VERSION_ID >= 70000 328 | array_init(&set_instance_array); 329 | #else 330 | MAKE_STD_ZVAL(set_instance_array); 331 | array_init(set_instance_array); 332 | #endif 333 | goto initInstance; 334 | } 335 | 336 | initInstance: 337 | #if PHP_VERSION_ID >= 70000 338 | instance = getThis(); 339 | zval re_instance; 340 | 341 | if (!instance) { 342 | ZVAL_NULL(&re_instance); 343 | instance = &re_instance; 344 | } 345 | #else 346 | MAKE_STD_ZVAL(instance); 347 | #endif 348 | 349 | object_init_ex(instance, druid_ce); 350 | 351 | DRUID_ZEND_UPDATE_PROPERTY_LONG(druid_ce, instance, ZEND_STRL(DRUID_PROPERTY_CURL_ERR_NO), 0); 352 | zend_update_property_string(druid_ce, instance, ZEND_STRL(DRUID_PROPERTY_CURL_ERR_STR), "" TSRMLS_CC); 353 | 354 | zend_update_property_bool(druid_ce, instance, ZEND_STRL(DRUID_PROPERTY_DEBUG), DRUID_G(debug) TSRMLS_CC); 355 | 356 | zend_update_property_string(druid_ce, instance, ZEND_STRL(DRUID_PROPERTY_TPL_PATH), DRUID_G(tpl_path) TSRMLS_CC); 357 | 358 | DRUID_ZEND_UPDATE_PROPERTY_LONG(druid_ce, instance, ZEND_STRL(DRUID_PROPERTY_RESPONSE_CODE), 0); 359 | zend_update_property_null(druid_ce, instance, ZEND_STRL(DRUID_PROPERTY_RESPONSE_INFO) TSRMLS_CC); 360 | 361 | zend_update_property_null(druid_ce, instance, ZEND_STRL(DRUID_PROPERTY_HOSTS) TSRMLS_CC); 362 | zend_update_property_bool(druid_ce, instance, ZEND_STRL(DRUID_PROPERTY_HOST_RAND), 0 TSRMLS_CC); 363 | 364 | if (get_instance_array && IS_ARRAY == Z_TYPE_P(get_instance_array)) 365 | { 366 | DRUID_ADD_ASSOC_ZVAL_EX(get_instance_array,instance_name,instance_name_len,instance); 367 | zend_update_static_property(druid_ce, ZEND_STRL(DRUID_NAME), get_instance_array TSRMLS_CC); 368 | } 369 | else 370 | { 371 | DRUID_ADD_ASSOC_ZVAL_EX_AND(set_instance_array,instance_name,instance_name_len,instance); 372 | DRUID_ZEND_UPDATE_STATIC_PROPERTY(druid_ce, ZEND_STRL(DRUID_NAME), set_instance_array); 373 | 374 | zval_ptr_dtor(&set_instance_array); 375 | } 376 | 377 | RETURN_ZVAL(instance, 1, 0); 378 | } 379 | 380 | 381 | PHP_METHOD(DRUID_NAME, __construct) 382 | { 383 | } 384 | 385 | PHP_METHOD(DRUID_NAME,__destruct) 386 | { 387 | zend_update_property_null(druid_ce, getThis(), ZEND_STRL(DRUID_PROPERTY_RESPONSE_INFO) TSRMLS_CC); 388 | zend_update_property_null(druid_ce, getThis(), ZEND_STRL(DRUID_PROPERTY_TPL_PATH) TSRMLS_CC); 389 | zend_update_property_null(druid_ce, getThis(), ZEND_STRL(DRUID_PROPERTY_HOSTS) TSRMLS_CC); 390 | 391 | zend_update_static_property_null(druid_ce, ZEND_STRL(DRUID_NAME) TSRMLS_CC); 392 | } 393 | 394 | PHP_METHOD(DRUID_NAME, __sleep) 395 | { 396 | } 397 | 398 | PHP_METHOD(DRUID_NAME, __wakeup) 399 | { 400 | } 401 | 402 | PHP_METHOD(DRUID_NAME, __clone) 403 | { 404 | } 405 | 406 | PHP_METHOD(DRUID_NAME, debugWitch) 407 | { 408 | zend_bool debug = 0; 409 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &debug) == FAILURE) 410 | { 411 | RETURN_FALSE; 412 | } 413 | 414 | zend_update_property_bool(druid_ce, getThis(), ZEND_STRL(DRUID_PROPERTY_DEBUG), debug TSRMLS_CC); 415 | 416 | RETURN_TRUE; 417 | } 418 | 419 | PHP_METHOD(DRUID_NAME, getDebugWitch) 420 | { 421 | zval *debug = 0; 422 | debug = DRUID_ZEND_READ_PROPERTY(druid_ce, getThis(), ZEND_STRL(DRUID_PROPERTY_DEBUG)); 423 | 424 | RETURN_ZVAL(debug, 1, 0); 425 | } 426 | 427 | PHP_METHOD(DRUID_NAME, setDruidHosts) 428 | { 429 | int argc = ZEND_NUM_ARGS(); 430 | zval *hosts; 431 | 432 | if (zend_parse_parameters(argc TSRMLS_CC, "z", &hosts) == FAILURE) 433 | { 434 | RETURN_FALSE; 435 | } 436 | 437 | if (Z_TYPE_P(hosts) != IS_ARRAY) 438 | { 439 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "The argument is not an array"); 440 | RETURN_FALSE; 441 | } 442 | 443 | DRUID_ZEND_UPDATE_PROPERTY(druid_ce, getThis(), ZEND_STRL(DRUID_PROPERTY_HOSTS), hosts); 444 | zend_update_property_bool(druid_ce, getThis(), ZEND_STRL(DRUID_PROPERTY_HOST_RAND), 1 TSRMLS_CC); 445 | 446 | RETURN_TRUE; 447 | } 448 | 449 | PHP_METHOD(DRUID_NAME, getDruidHosts) 450 | { 451 | zval *hosts; 452 | hosts = DRUID_ZEND_READ_PROPERTY(druid_ce, getThis(), ZEND_STRL(DRUID_PROPERTY_HOSTS)); 453 | 454 | if (hosts) 455 | { 456 | RETURN_ZVAL(hosts, 1, 0); 457 | } 458 | else 459 | { 460 | DRUID_RETURN_STRINGL(DRUID_G(host),strlen(DRUID_G(host))); 461 | } 462 | } 463 | 464 | PHP_METHOD(DRUID_NAME, setTplPath) 465 | { 466 | char *tpl_path; 467 | 468 | #if PHP_VERSION_ID >= 70000 469 | size_t tpl_path_len; 470 | #else 471 | int tpl_path_len; 472 | #endif 473 | 474 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &tpl_path, &tpl_path_len) == FAILURE) 475 | { 476 | RETURN_FALSE; 477 | } 478 | 479 | zend_update_property_string(druid_ce, getThis(), ZEND_STRL(DRUID_PROPERTY_TPL_PATH), tpl_path TSRMLS_CC); 480 | 481 | RETURN_TRUE; 482 | } 483 | 484 | PHP_METHOD(DRUID_NAME, getTplPath) 485 | { 486 | zval *tpl_path = DRUID_ZEND_READ_PROPERTY(druid_ce, getThis(), ZEND_STRL(DRUID_PROPERTY_TPL_PATH)); 487 | 488 | RETURN_ZVAL(tpl_path, 1, 0); 489 | } 490 | 491 | /*Just used by PHP7*/ 492 | #if PHP_VERSION_ID >= 70000 493 | // We asure the src is on heap, so every call we can safe free than alloc. 494 | static char *strreplace(char *src, const char *oldstr, const char *newstr, size_t len) 495 | { 496 | char *needle; 497 | char *tmp; 498 | 499 | if(strcmp(oldstr, newstr)==0) 500 | { 501 | return src; 502 | } 503 | 504 | while((needle = strstr(src, oldstr)) && (needle - src <= len)) 505 | { 506 | tmp = (char*)emalloc(strlen(src) + (strlen(newstr) - strlen(oldstr)) + 1); 507 | 508 | strncpy(tmp, src, needle-src); 509 | 510 | tmp[needle-src]='\0'; 511 | strcat(tmp, newstr); 512 | strcat(tmp, needle+strlen(oldstr)); 513 | 514 | efree(src); 515 | src = tmp; 516 | len = strlen(src); 517 | } 518 | 519 | return src; 520 | } 521 | 522 | static char *php_strtr_array(char *str, int slen, HashTable *pats) 523 | { 524 | zend_ulong num_key; 525 | zend_string *str_key; 526 | zval *entry; 527 | char *tmp = estrdup(str); 528 | 529 | ZEND_HASH_FOREACH_KEY_VAL(pats, num_key, str_key, entry) 530 | { 531 | if (UNEXPECTED(!str_key)) 532 | { 533 | (void)num_key; 534 | } 535 | else 536 | { 537 | zend_string *s = zval_get_string(entry); 538 | 539 | if (strstr(str,ZSTR_VAL(str_key))) 540 | { 541 | tmp = strreplace(tmp, ZSTR_VAL(str_key), ZSTR_VAL(s), strlen(str)); 542 | } 543 | 544 | zend_string_release(s); 545 | zend_string_release(str_key); 546 | } 547 | } 548 | ZEND_HASH_FOREACH_END(); 549 | 550 | return tmp; 551 | } 552 | 553 | #else 554 | static char *php_strtr_array(char *str, int slen, HashTable *hash) 555 | { 556 | zval **entry; 557 | char *string_key; 558 | uint string_key_len; 559 | zval **trans; 560 | zval ctmp; 561 | ulong num_key; 562 | int minlen = 128 * 1024; 563 | int maxlen = 0, pos, len, found; 564 | char *key; 565 | HashPosition hpos; 566 | smart_str result = {0}; 567 | char *result_str; 568 | HashTable tmp_hash; 569 | 570 | zend_hash_init(&tmp_hash, zend_hash_num_elements(hash), NULL, NULL, 0); 571 | zend_hash_internal_pointer_reset_ex(hash, &hpos); 572 | 573 | while (zend_hash_get_current_data_ex(hash, (void **)&entry, &hpos) == SUCCESS) 574 | { 575 | switch (zend_hash_get_current_key_ex(hash, &string_key, &string_key_len, &num_key, 0, &hpos)) 576 | { 577 | case HASH_KEY_IS_STRING: 578 | len = string_key_len - 1; 579 | if (len < 1) 580 | { 581 | zend_hash_destroy(&tmp_hash); 582 | } 583 | else 584 | { 585 | zend_hash_add(&tmp_hash, string_key, string_key_len, entry, sizeof(zval*), NULL); 586 | if (len > maxlen) 587 | { 588 | maxlen = len; 589 | } 590 | if (len < minlen) 591 | { 592 | minlen = len; 593 | } 594 | } 595 | break; 596 | 597 | case HASH_KEY_IS_LONG: 598 | Z_TYPE(ctmp) = IS_LONG; 599 | Z_LVAL(ctmp) = num_key; 600 | 601 | convert_to_string(&ctmp); 602 | len = Z_STRLEN(ctmp); 603 | zend_hash_add(&tmp_hash, Z_STRVAL(ctmp), len + 1, entry, sizeof(zval*), NULL); 604 | zval_dtor(&ctmp); 605 | 606 | if (len > maxlen) 607 | { 608 | maxlen = len; 609 | } 610 | if (len < minlen) 611 | { 612 | minlen = len; 613 | } 614 | break; 615 | } 616 | zend_hash_move_forward_ex(hash, &hpos); 617 | } 618 | 619 | key = emalloc(maxlen + 1); 620 | pos = 0; 621 | 622 | while (pos < slen) 623 | { 624 | if ((pos + maxlen) > slen) 625 | { 626 | maxlen = slen - pos; 627 | } 628 | 629 | found = 0; 630 | memcpy(key, str + pos, maxlen); 631 | 632 | for (len = maxlen; len >= minlen; len--) 633 | { 634 | key[len] = 0; 635 | 636 | if (zend_hash_find(&tmp_hash, key, len + 1, (void**)&trans) == SUCCESS) 637 | { 638 | char *tval; 639 | int tlen; 640 | zval tmp; 641 | 642 | if (Z_TYPE_PP(trans) != IS_STRING) 643 | { 644 | tmp = **trans; 645 | zval_copy_ctor(&tmp); 646 | convert_to_string(&tmp); 647 | tval = Z_STRVAL(tmp); 648 | tlen = Z_STRLEN(tmp); 649 | } 650 | else 651 | { 652 | tval = Z_STRVAL_PP(trans); 653 | tlen = Z_STRLEN_PP(trans); 654 | } 655 | 656 | smart_str_appendl(&result, tval, tlen); 657 | pos += len; 658 | found = 1; 659 | 660 | if (Z_TYPE_PP(trans) != IS_STRING) 661 | { 662 | zval_dtor(&tmp); 663 | } 664 | 665 | break; 666 | } 667 | } 668 | 669 | if (! found) 670 | { 671 | smart_str_appendc(&result, str[pos++]); 672 | } 673 | } 674 | 675 | zend_hash_destroy(&tmp_hash); 676 | result_str = estrndup(result.c, result.len); 677 | efree(key); 678 | smart_str_free(&result); 679 | 680 | return result_str; 681 | } 682 | #endif 683 | 684 | PHP_METHOD(DRUID_NAME,getData) 685 | { 686 | int argc = ZEND_NUM_ARGS(); 687 | 688 | char *request,*request_json; 689 | #if PHP_VERSION_ID >= 70000 690 | size_t request_len; 691 | #else 692 | int request_len; 693 | #endif 694 | zval *content; 695 | 696 | if (zend_parse_parameters(argc TSRMLS_CC, "s|z", &request, &request_len, &content) == FAILURE) 697 | { 698 | RETURN_FALSE; 699 | } 700 | 701 | if (argc > 1 && Z_TYPE_P(content) != IS_ARRAY) 702 | { 703 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "The second argument is not an array"); 704 | RETURN_FALSE; 705 | } 706 | 707 | if (argc > 1) 708 | { 709 | request_json = php_strtr_array(request,request_len,HASH_OF(content)); 710 | } 711 | else 712 | { 713 | request_json = request; 714 | } 715 | 716 | druid_getApi(return_value, getThis(), request_json TSRMLS_CC); 717 | 718 | if (argc > 1) 719 | { 720 | efree(request_json); 721 | } 722 | } 723 | 724 | PHP_METHOD(DRUID_NAME,getDataByTpl) 725 | { 726 | int argc = ZEND_NUM_ARGS(); 727 | 728 | char *tpl,*request,*request_json,*filename; 729 | zval *tpl_path; 730 | zval *content; 731 | 732 | #if PHP_VERSION_ID >= 70000 733 | size_t tpl_len; 734 | #else 735 | int tpl_len; 736 | #endif 737 | 738 | if (zend_parse_parameters(argc TSRMLS_CC, "s|z", &tpl, &tpl_len, &content) == FAILURE) 739 | { 740 | RETURN_FALSE; 741 | } 742 | 743 | if (argc > 1 && Z_TYPE_P(content) != IS_ARRAY) 744 | { 745 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "The second argument is not an array"); 746 | RETURN_FALSE; 747 | } 748 | 749 | tpl_path = DRUID_ZEND_READ_PROPERTY(druid_ce, getThis(), ZEND_STRL(DRUID_PROPERTY_TPL_PATH)); 750 | 751 | spprintf(&filename, 0, "%s/%s", Z_STRVAL_P(tpl_path),tpl); 752 | request = druid_file_get_contents_by_tpl(filename TSRMLS_CC); 753 | efree(filename); 754 | 755 | if (request == NULL) 756 | { 757 | RETURN_FALSE; 758 | } 759 | 760 | if (argc > 1) 761 | { 762 | request_json = php_strtr_array(request,strlen(request),HASH_OF(content)); 763 | } 764 | else 765 | { 766 | request_json = request; 767 | } 768 | 769 | druid_getApi(return_value, getThis(), request_json TSRMLS_CC); 770 | 771 | efree(request); 772 | if (argc > 1) 773 | { 774 | efree(request_json); 775 | } 776 | } 777 | 778 | PHP_METHOD(DRUID_NAME,getDebugInfo) 779 | { 780 | zval *info = DRUID_ZEND_READ_PROPERTY(druid_ce, getThis(), ZEND_STRL(DRUID_PROPERTY_RESPONSE_INFO)); 781 | RETVAL_ZVAL(info, 1, 0); 782 | } 783 | 784 | 785 | char *druid_file_get_contents_by_tpl(char *filename TSRMLS_DC) 786 | { 787 | php_stream *stream; 788 | zval *zcontext = NULL; 789 | php_stream_context *context = NULL; 790 | char *contents; 791 | int len; 792 | 793 | #if PHP_VERSION_ID >= 70000 794 | zend_string *contents_raw; 795 | #endif 796 | 797 | context = php_stream_context_from_zval(zcontext, 0); 798 | 799 | stream = php_stream_open_wrapper_ex(filename, "rb",0 | REPORT_ERRORS, NULL, context); 800 | if (!stream) 801 | { 802 | return NULL; 803 | } 804 | 805 | #if PHP_VERSION_ID >= 70000 806 | if ((contents_raw = php_stream_copy_to_mem(stream, PHP_STREAM_COPY_ALL, 0)) != NULL) 807 | { 808 | php_stream_close(stream); 809 | contents = estrdup(ZSTR_VAL(contents_raw)); 810 | zend_string_release(contents_raw); 811 | return contents; 812 | #else 813 | if ((len = php_stream_copy_to_mem(stream, &contents, PHP_STREAM_COPY_ALL, 0)) > 0) 814 | { 815 | php_stream_close(stream); 816 | return contents; 817 | } 818 | else if (len == 0) 819 | { 820 | php_stream_close(stream); 821 | return NULL; 822 | #endif 823 | } 824 | else 825 | { 826 | php_stream_close(stream); 827 | return NULL; 828 | } 829 | 830 | php_stream_close(stream); 831 | } 832 | 833 | static void druid_getApi(zval *return_value, zval *druid, char *request_json TSRMLS_DC) 834 | { 835 | zval *err_str,*err_no; 836 | zval *response_code; 837 | 838 | struct druidCurlResult curlResult; 839 | 840 | if(druid_get_contents(druid,request_json,&curlResult TSRMLS_CC) != SUCCESS) 841 | { 842 | err_str = DRUID_ZEND_READ_PROPERTY(druid_ce, druid, ZEND_STRL(DRUID_PROPERTY_CURL_ERR_STR)); 843 | err_no = DRUID_ZEND_READ_PROPERTY(druid_ce, druid, ZEND_STRL(DRUID_PROPERTY_CURL_ERR_NO)); 844 | 845 | free(curlResult.memory); 846 | zend_throw_exception(php_com_exception_class_entry,Z_STRVAL_P(err_str),Z_LVAL_P(err_no) TSRMLS_CC); 847 | RETURN_FALSE; 848 | } 849 | 850 | response_code = DRUID_ZEND_READ_PROPERTY(druid_ce, druid, ZEND_STRL(DRUID_PROPERTY_RESPONSE_CODE)); 851 | if (Z_LVAL_P(response_code) > DRUID_RESPONSE_CODE_ERROR_BAR) 852 | { 853 | zend_throw_exception(php_com_exception_class_entry,curlResult.memory,Z_LVAL_P(response_code) TSRMLS_CC); 854 | free(curlResult.memory); 855 | RETURN_FALSE; 856 | } 857 | 858 | php_json_decode(return_value, curlResult.memory, (long)curlResult.size, 1, 512 TSRMLS_CC); 859 | free(curlResult.memory); 860 | } 861 | 862 | 863 | static size_t druid_curl_callback(void *contents, size_t size, size_t nmemb, void *userp) 864 | { 865 | size_t realsize = size * nmemb; 866 | struct druidCurlResult *mem = (struct druidCurlResult *)userp; 867 | 868 | mem->memory = realloc(mem->memory, mem->size + realsize + 1); 869 | if(mem->memory == NULL) 870 | { 871 | return 0; 872 | } 873 | 874 | memcpy(&(mem->memory[mem->size]), contents, realsize); 875 | mem->size += realsize; 876 | mem->memory[mem->size] = 0; 877 | return realsize; 878 | } 879 | 880 | int druid_php_rand(TSRMLS_D) 881 | { 882 | int rnd_idx; 883 | rnd_idx = php_rand(TSRMLS_C); 884 | 885 | if ((double) (rnd_idx / (PHP_RAND_MAX + 1.0)) < DRUID_PROPERTY_HOST_RAND_BAR) 886 | { 887 | return SUCCESS; 888 | } 889 | 890 | return FAILURE; 891 | } 892 | 893 | char *druid_get_host(zval *druid TSRMLS_DC) 894 | { 895 | int hash_sum = 0; 896 | int step = 0; 897 | zval *host_rand,*hosts; 898 | char *host_result; 899 | #if PHP_VERSION_ID >= 70000 900 | 901 | zend_ulong num_key; 902 | zend_string *str_key; 903 | zval *entry; 904 | 905 | #else 906 | 907 | zval **entry; 908 | HashPosition pos; 909 | 910 | #endif 911 | 912 | host_rand = DRUID_ZEND_READ_PROPERTY(druid_ce, druid, ZEND_STRL(DRUID_PROPERTY_HOST_RAND)); 913 | 914 | #if PHP_VERSION_ID >= 70000 915 | 916 | if (Z_TYPE_P(host_rand) == IS_TRUE) 917 | { 918 | hosts = DRUID_ZEND_READ_PROPERTY(druid_ce, druid, ZEND_STRL(DRUID_PROPERTY_HOSTS)); 919 | hash_sum = zend_hash_num_elements(HASH_OF(hosts)); 920 | ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(hosts), num_key, str_key, entry) 921 | { 922 | (void)num_key; 923 | (void)str_key; 924 | step++; 925 | zend_string *s = zval_get_string(entry); 926 | 927 | if (druid_php_rand(TSRMLS_C) == SUCCESS || step == hash_sum) 928 | { 929 | host_result = estrdup(ZSTR_VAL(s)); 930 | zend_string_release(s); 931 | return host_result; 932 | } 933 | else 934 | { 935 | zend_string_release(s); 936 | } 937 | } 938 | ZEND_HASH_FOREACH_END(); 939 | } 940 | 941 | #else 942 | 943 | if (Z_LVAL_P(host_rand) == 1) 944 | { 945 | 946 | hosts = DRUID_ZEND_READ_PROPERTY(druid_ce, druid, ZEND_STRL(DRUID_PROPERTY_HOSTS)); 947 | 948 | hash_sum = zend_hash_num_elements(HASH_OF(hosts)); 949 | 950 | for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(hosts), &pos); 951 | zend_hash_get_current_data_ex(Z_ARRVAL_P(hosts), (void **)&entry, &pos) == SUCCESS; 952 | zend_hash_move_forward_ex(Z_ARRVAL_P(hosts), &pos) 953 | ) 954 | { 955 | step++; 956 | 957 | if (Z_TYPE_PP(entry) == IS_ARRAY || Z_TYPE_PP(entry) == IS_OBJECT || Z_TYPE_PP(entry) == IS_LONG) 958 | { 959 | continue; 960 | } 961 | 962 | if (druid_php_rand(TSRMLS_C) == SUCCESS || step == hash_sum) 963 | { 964 | host_result = estrdup(Z_STRVAL_PP(entry)); 965 | 966 | return host_result; 967 | } 968 | } 969 | } 970 | #endif 971 | 972 | host_result = estrdup(DRUID_G(host)); 973 | return host_result; 974 | } 975 | 976 | int druid_get_debug_info(zval *druid,CURL *curl_handle,char *request_json TSRMLS_DC) 977 | { 978 | char *s_code; 979 | long l_code; 980 | double d_code; 981 | curl_version_info_data *info; 982 | 983 | #if PHP_VERSION_ID >= 70000 984 | 985 | zval debug_info; 986 | array_init(&debug_info); 987 | 988 | #else 989 | 990 | zval *debug_info; 991 | MAKE_STD_ZVAL(debug_info); 992 | array_init(debug_info); 993 | 994 | #endif 995 | 996 | info = curl_version_info(CURLVERSION_NOW); 997 | DRUID_ADD_ASSOC_STRING_EX(debug_info, "version", DRUID_STR_SIZE("version"), (char *)info->version); 998 | DRUID_ADD_ASSOC_STRING_EX(debug_info,"ssl_version",DRUID_STR_SIZE("ssl_version"),(char *)info->ssl_version); 999 | 1000 | if (curl_easy_getinfo(curl_handle, CURLINFO_EFFECTIVE_URL, &s_code) == CURLE_OK) 1001 | { 1002 | DRUID_ADD_ASSOC_STRING_EX(debug_info,"url",DRUID_STR_SIZE("url"),s_code); 1003 | } 1004 | if (curl_easy_getinfo(curl_handle, CURLINFO_HTTP_CODE, &l_code) == CURLE_OK) 1005 | { 1006 | DRUID_ADD_ASSOC_LONG_EX(debug_info,"http_code",DRUID_STR_SIZE("http_code"),l_code); 1007 | } 1008 | if (curl_easy_getinfo(curl_handle, CURLINFO_HEADER_SIZE, &l_code) == CURLE_OK) 1009 | { 1010 | DRUID_ADD_ASSOC_LONG_EX(debug_info,"header_size",DRUID_STR_SIZE("header_size"),l_code); 1011 | } 1012 | if (curl_easy_getinfo(curl_handle, CURLINFO_REQUEST_SIZE, &l_code) == CURLE_OK) 1013 | { 1014 | DRUID_ADD_ASSOC_LONG_EX(debug_info,"request_size",DRUID_STR_SIZE("request_size"),l_code); 1015 | } 1016 | if (curl_easy_getinfo(curl_handle, CURLINFO_FILETIME, &l_code) == CURLE_OK) 1017 | { 1018 | DRUID_ADD_ASSOC_LONG_EX(debug_info,"filetime",DRUID_STR_SIZE("filetime"),l_code); 1019 | } 1020 | if (curl_easy_getinfo(curl_handle, CURLINFO_SSL_VERIFYRESULT, &l_code) == CURLE_OK) 1021 | { 1022 | DRUID_ADD_ASSOC_LONG_EX(debug_info,"ssl_verify_result",DRUID_STR_SIZE("ssl_verify_result"),l_code); 1023 | } 1024 | if (curl_easy_getinfo(curl_handle, CURLINFO_REDIRECT_COUNT, &l_code) == CURLE_OK) 1025 | { 1026 | DRUID_ADD_ASSOC_LONG_EX(debug_info,"redirect_count",DRUID_STR_SIZE("redirect_count"),l_code); 1027 | } 1028 | if (curl_easy_getinfo(curl_handle, CURLINFO_TOTAL_TIME, &d_code) == CURLE_OK) 1029 | { 1030 | DRUID_ADD_ASSOC_DOUBLE_EX(debug_info,"total_time",DRUID_STR_SIZE("total_time"),d_code); 1031 | } 1032 | if (curl_easy_getinfo(curl_handle, CURLINFO_NAMELOOKUP_TIME, &d_code) == CURLE_OK) 1033 | { 1034 | DRUID_ADD_ASSOC_DOUBLE_EX(debug_info,"namelookup_time",DRUID_STR_SIZE("namelookup_time"),d_code); 1035 | } 1036 | if (curl_easy_getinfo(curl_handle, CURLINFO_CONNECT_TIME, &d_code) == CURLE_OK) 1037 | { 1038 | DRUID_ADD_ASSOC_DOUBLE_EX(debug_info,"connect_time",DRUID_STR_SIZE("connect_time"),d_code); 1039 | } 1040 | if (curl_easy_getinfo(curl_handle, CURLINFO_PRETRANSFER_TIME, &d_code) == CURLE_OK) 1041 | { 1042 | DRUID_ADD_ASSOC_DOUBLE_EX(debug_info,"pretransfer_time",DRUID_STR_SIZE("pretransfer_time"),d_code); 1043 | } 1044 | 1045 | if (curl_easy_getinfo(curl_handle, CURLINFO_SIZE_UPLOAD, &d_code) == CURLE_OK) 1046 | { 1047 | DRUID_ADD_ASSOC_DOUBLE_EX(debug_info,"size_upload",DRUID_STR_SIZE("size_upload"),d_code); 1048 | } 1049 | if (curl_easy_getinfo(curl_handle, CURLINFO_SIZE_DOWNLOAD, &d_code) == CURLE_OK) 1050 | { 1051 | DRUID_ADD_ASSOC_DOUBLE_EX(debug_info,"size_download",DRUID_STR_SIZE("size_download"),d_code); 1052 | } 1053 | if (curl_easy_getinfo(curl_handle, CURLINFO_SPEED_DOWNLOAD, &d_code) == CURLE_OK) 1054 | { 1055 | DRUID_ADD_ASSOC_DOUBLE_EX(debug_info,"speed_download",DRUID_STR_SIZE("speed_download"),d_code); 1056 | } 1057 | if (curl_easy_getinfo(curl_handle, CURLINFO_SPEED_UPLOAD, &d_code) == CURLE_OK) 1058 | { 1059 | DRUID_ADD_ASSOC_DOUBLE_EX(debug_info,"speed_upload",DRUID_STR_SIZE("speed_upload"),d_code); 1060 | } 1061 | if (curl_easy_getinfo(curl_handle, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &d_code) == CURLE_OK) 1062 | { 1063 | DRUID_ADD_ASSOC_DOUBLE_EX(debug_info,"download_content_length",DRUID_STR_SIZE("download_content_length"),d_code); 1064 | } 1065 | if (curl_easy_getinfo(curl_handle, CURLINFO_CONTENT_LENGTH_UPLOAD, &d_code) == CURLE_OK) 1066 | { 1067 | DRUID_ADD_ASSOC_DOUBLE_EX(debug_info,"upload_content_length",DRUID_STR_SIZE("upload_content_length"),d_code); 1068 | } 1069 | if (curl_easy_getinfo(curl_handle, CURLINFO_STARTTRANSFER_TIME, &d_code) == CURLE_OK) 1070 | { 1071 | DRUID_ADD_ASSOC_DOUBLE_EX(debug_info,"starttransfer_time",DRUID_STR_SIZE("starttransfer_time"),d_code); 1072 | } 1073 | if (curl_easy_getinfo(curl_handle, CURLINFO_REDIRECT_TIME, &d_code) == CURLE_OK) 1074 | { 1075 | DRUID_ADD_ASSOC_DOUBLE_EX(debug_info,"redirect_time",DRUID_STR_SIZE("redirect_time"),d_code); 1076 | } 1077 | 1078 | DRUID_ADD_ASSOC_STRING_EX(debug_info,"request_json",DRUID_STR_SIZE("request_json"),request_json); 1079 | #if PHP_VERSION_ID >= 70000 1080 | DRUID_ZEND_UPDATE_PROPERTY(druid_ce, druid, ZEND_STRL(DRUID_PROPERTY_RESPONSE_INFO), &debug_info); 1081 | #else 1082 | DRUID_ZEND_UPDATE_PROPERTY(druid_ce, druid, ZEND_STRL(DRUID_PROPERTY_RESPONSE_INFO), debug_info); 1083 | #endif 1084 | 1085 | zval_ptr_dtor(&debug_info); 1086 | 1087 | return SUCCESS; 1088 | } 1089 | 1090 | int druid_get_contents(zval *druid, char *request_json, struct druidCurlResult *result TSRMLS_DC) 1091 | { 1092 | CURL *curl_handle; 1093 | CURLcode res; 1094 | char *url; 1095 | long l_code; 1096 | struct curl_slist *slist = NULL; 1097 | zval *debug; 1098 | 1099 | char err_str[CURL_ERROR_SIZE + 1]; 1100 | struct druidCurlResult tmp; 1101 | 1102 | curl_global_init(CURL_GLOBAL_ALL); 1103 | 1104 | curl_handle = curl_easy_init(); 1105 | 1106 | if (!curl_handle) 1107 | { 1108 | php_error_docref(NULL TSRMLS_CC, E_ERROR, "curl init failed\n"); 1109 | return FAILURE; 1110 | } 1111 | 1112 | result->size = 0; 1113 | result->memory =malloc(1); 1114 | 1115 | url = druid_get_host(druid TSRMLS_CC); 1116 | 1117 | memset(err_str, 0, CURL_ERROR_SIZE + 1); 1118 | 1119 | tmp.memory = malloc(1); 1120 | tmp.size = 0; 1121 | 1122 | 1123 | curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, druid_curl_callback); 1124 | 1125 | curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA,(void *) &tmp); 1126 | 1127 | curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION,1); 1128 | 1129 | curl_easy_setopt(curl_handle, CURLOPT_ERRORBUFFER, err_str); 1130 | 1131 | curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 1); 1132 | curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 0); 1133 | curl_easy_setopt(curl_handle, CURLOPT_MAXREDIRS, 5); 1134 | curl_easy_setopt(curl_handle, CURLOPT_DNS_USE_GLOBAL_CACHE, 1); 1135 | 1136 | curl_easy_setopt(curl_handle, CURLOPT_DNS_CACHE_TIMEOUT, DRUID_G(curl_dns_cache_timeout)); 1137 | curl_easy_setopt(curl_handle, CURLOPT_CONNECTTIMEOUT, DRUID_G(curl_connect_timeout)); 1138 | curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, DRUID_G(curl_timeout)); 1139 | 1140 | slist = curl_slist_append(slist, DRUID_CONTENT_TYPE); 1141 | curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, slist); 1142 | 1143 | curl_easy_setopt(curl_handle,CURLOPT_URL,url); 1144 | curl_easy_setopt(curl_handle,CURLOPT_POST,1); 1145 | 1146 | curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, request_json); 1147 | curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDSIZE, strlen(request_json)); 1148 | 1149 | res = curl_easy_perform(curl_handle); 1150 | 1151 | if(res != CURLE_OK) 1152 | { 1153 | err_str[CURL_ERROR_SIZE] = 0; 1154 | 1155 | DRUID_ZEND_UPDATE_PROPERTY_LONG(druid_ce, druid, ZEND_STRL(DRUID_PROPERTY_CURL_ERR_NO), res); 1156 | zend_update_property_stringl(druid_ce, druid, ZEND_STRL(DRUID_PROPERTY_CURL_ERR_STR), err_str, CURL_ERROR_SIZE TSRMLS_CC); 1157 | 1158 | curl_easy_cleanup(curl_handle); 1159 | curl_global_cleanup(); 1160 | efree(url); 1161 | 1162 | return FAILURE; 1163 | } 1164 | 1165 | result->size = tmp.size; 1166 | result->memory = malloc(tmp.size +1); 1167 | strcpy(result->memory,tmp.memory); 1168 | 1169 | if (curl_easy_getinfo(curl_handle, CURLINFO_HTTP_CODE, &l_code) == CURLE_OK) 1170 | { 1171 | DRUID_ZEND_UPDATE_PROPERTY_LONG(druid_ce, druid, ZEND_STRL(DRUID_PROPERTY_RESPONSE_CODE), l_code); 1172 | } 1173 | 1174 | debug = DRUID_ZEND_READ_PROPERTY(druid_ce, druid, ZEND_STRL(DRUID_PROPERTY_DEBUG)); 1175 | 1176 | #if PHP_VERSION_ID >= 70000 1177 | 1178 | if (Z_TYPE_P(debug) == IS_TRUE) 1179 | { 1180 | druid_get_debug_info(druid,curl_handle,request_json TSRMLS_CC); 1181 | } 1182 | #else 1183 | 1184 | if (Z_LVAL_P(debug) == 1) 1185 | { 1186 | druid_get_debug_info(druid,curl_handle,request_json TSRMLS_CC); 1187 | } 1188 | #endif 1189 | 1190 | curl_easy_cleanup(curl_handle); 1191 | curl_global_cleanup(); 1192 | efree(url); 1193 | 1194 | return SUCCESS; 1195 | } 1196 | 1197 | -------------------------------------------------------------------------------- /example/demo.php: -------------------------------------------------------------------------------- 1 | debugWitch(true); 11 | 12 | /** 13 | * you can also use default host with druid.host in php.ini/druid.ini 14 | */ 15 | $aHosts = array("http://10.0.3.46:9082/druid/v2/", "http://10.0.3.46:9082/druid/v2/"); 16 | $Druid_1->setDruidHosts($aHosts); 17 | 18 | /** 19 | * demo 1 20 | * 21 | * use tpl build request json 22 | */ 23 | $Druid_1->setTplPath(__DIR__ . '/tpl'); 24 | $result_1 = $Druid_1->getDataByTpl('request_tpl_demo.json', array('@startTimeToEndTime@' => '["2016-12-10T14:06:00.000Z/2016-12-27T14:36:00.000Z"]')); 25 | 26 | 27 | $Druid_2 = Druid::getInstance('druid_2_instance'); 28 | /** 29 | * demo 2 30 | * 31 | * use full request json 32 | */ 33 | $result_2 = $Druid_2->getData(file_get_contents(__DIR__ . '/tpl/request_full_demo.json')); 34 | 35 | var_dump($result_1, $result_2); 36 | var_dump($Druid_1, $Druid_2); 37 | } catch (Exception $e) { 38 | var_dump($e->getCode(), $e->getMessage(), $Druid_1->getDebugInfo(), $Druid_2->getDebugInfo()); 39 | } -------------------------------------------------------------------------------- /example/tpl/request_full_demo.json: -------------------------------------------------------------------------------- 1 | { 2 | "queryType": "timeseries", 3 | "dataSource": "agentTopic-1m", 4 | "granularity": { 5 | "type": "duration", 6 | "duration": "300000" 7 | }, 8 | "intervals": ["2016-12-10T14:06:00.000Z/2016-12-27T14:36:00.000Z"], 9 | "filter": { 10 | "type": "and", 11 | "fields": [ 12 | { 13 | "type": "selector", 14 | "dimension": "accountId", 15 | "value": "107" 16 | }, 17 | { 18 | "type": "selector", 19 | "dimension": "hostId", 20 | "value": "10675435376182376" 21 | }, 22 | { 23 | "type": "selector", 24 | "dimension": "serviceType", 25 | "value": "101" 26 | } 27 | ] 28 | }, 29 | "aggregations": [ 30 | { 31 | "type": "doubleSum", 32 | "name": "oneMinute", 33 | "fieldName": "oneMinute" 34 | }, 35 | { 36 | "type": "doubleSum", 37 | "name": "fiveMinute", 38 | "fieldName": "fiveMinute" 39 | }, 40 | { 41 | "type": "doubleSum", 42 | "name": "fifteenMinute", 43 | "fieldName": "fifteenMinute" 44 | }, 45 | { 46 | "type": "longSum", 47 | "name": "count", 48 | "fieldName": "count" 49 | } 50 | ], 51 | "postAggregations": [ 52 | { 53 | "type": "arithmetic", 54 | "name": "oneMinuteAvg", 55 | "fn": "/", 56 | "fields": [ 57 | { 58 | "type": "fieldAccess", 59 | "name": "oneMinute", 60 | "fieldName": "oneMinute" 61 | }, 62 | { 63 | "type": "fieldAccess", 64 | "name": "count", 65 | "fieldName": "count" 66 | } 67 | ] 68 | }, 69 | { 70 | "type": "arithmetic", 71 | "name": "fiveMinuteAvg", 72 | "fn": "/", 73 | "fields": [ 74 | { 75 | "type": "fieldAccess", 76 | "name": "fiveMinute", 77 | "fieldName": "fiveMinute" 78 | }, 79 | { 80 | "type": "fieldAccess", 81 | "name": "count", 82 | "fieldName": "count" 83 | } 84 | ] 85 | }, 86 | { 87 | "type": "arithmetic", 88 | "name": "fifteenMinuteAvg", 89 | "fn": "/", 90 | "fields": [ 91 | { 92 | "type": "fieldAccess", 93 | "name": "fifteenMinute", 94 | "fieldName": "fifteenMinute" 95 | }, 96 | { 97 | "type": "fieldAccess", 98 | "name": "count", 99 | "fieldName": "count" 100 | } 101 | ] 102 | } 103 | ] 104 | } -------------------------------------------------------------------------------- /example/tpl/request_tpl_demo.json: -------------------------------------------------------------------------------- 1 | { 2 | "queryType": "timeseries", 3 | "dataSource": "agentTopic-1m", 4 | "granularity": { 5 | "type": "duration", 6 | "duration": "300000" 7 | }, 8 | "intervals": @startTimeToEndTime@, 9 | "filter": { 10 | "type": "and", 11 | "fields": [ 12 | { 13 | "type": "selector", 14 | "dimension": "accountId", 15 | "value": "107" 16 | }, 17 | { 18 | "type": "selector", 19 | "dimension": "hostId", 20 | "value": "10675435376182376" 21 | }, 22 | { 23 | "type": "selector", 24 | "dimension": "serviceType", 25 | "value": "101" 26 | } 27 | ] 28 | }, 29 | "aggregations": [ 30 | { 31 | "type": "doubleSum", 32 | "name": "oneMinute", 33 | "fieldName": "oneMinute" 34 | }, 35 | { 36 | "type": "doubleSum", 37 | "name": "fiveMinute", 38 | "fieldName": "fiveMinute" 39 | }, 40 | { 41 | "type": "doubleSum", 42 | "name": "fifteenMinute", 43 | "fieldName": "fifteenMinute" 44 | }, 45 | { 46 | "type": "longSum", 47 | "name": "count", 48 | "fieldName": "count" 49 | } 50 | ], 51 | "postAggregations": [ 52 | { 53 | "type": "arithmetic", 54 | "name": "oneMinuteAvg", 55 | "fn": "/", 56 | "fields": [ 57 | { 58 | "type": "fieldAccess", 59 | "name": "oneMinute", 60 | "fieldName": "oneMinute" 61 | }, 62 | { 63 | "type": "fieldAccess", 64 | "name": "count", 65 | "fieldName": "count" 66 | } 67 | ] 68 | }, 69 | { 70 | "type": "arithmetic", 71 | "name": "fiveMinuteAvg", 72 | "fn": "/", 73 | "fields": [ 74 | { 75 | "type": "fieldAccess", 76 | "name": "fiveMinute", 77 | "fieldName": "fiveMinute" 78 | }, 79 | { 80 | "type": "fieldAccess", 81 | "name": "count", 82 | "fieldName": "count" 83 | } 84 | ] 85 | }, 86 | { 87 | "type": "arithmetic", 88 | "name": "fifteenMinuteAvg", 89 | "fn": "/", 90 | "fields": [ 91 | { 92 | "type": "fieldAccess", 93 | "name": "fifteenMinute", 94 | "fieldName": "fifteenMinute" 95 | }, 96 | { 97 | "type": "fieldAccess", 98 | "name": "count", 99 | "fieldName": "count" 100 | } 101 | ] 102 | } 103 | ] 104 | } -------------------------------------------------------------------------------- /package.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | Druid 6 | pecl.php.net 7 | A Druid driver for PHP with PECL extension. 8 | 9 | A Druid driver for PHP with PECL extension. 10 | - Build Druid REST Client Use CURL. 11 | - Request both with Full-Json or Templates-Json 12 | 13 | 14 | Chitao Gao 15 | neeke 16 | neeke@php.net 17 | yes 18 | 19 | 2018-04-28 20 | 21 | 22 | 1.0.0 23 | 1.0.0 24 | 25 | 26 | stable 27 | stable 28 | 29 | Apache2.0 30 | 31 | - Merged PR #8 ZEND_ACC_CLONE have been removed in PHP 7.2 32 | - Fixed support PHP 7.2 33 | - Add function getDebugWitch 34 | - Add function getDruidHosts 35 | - Add function getTplPath 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 | 5.2.0 73 | 74 | 75 | 1.4.0 76 | 77 | 78 | 79 | Druid 80 | 81 | 82 | 83 | 2016-12-21 84 | 85 | 86 | 0.3.0 87 | 0.3.0 88 | 89 | 90 | beta 91 | beta 92 | 93 | Apache2.0 94 | 95 | - First version for pecl.net 96 | - Support PHP 5.*. 97 | 98 | 99 | 100 | 2016-12-26 101 | 102 | 103 | 0.6.0 104 | 0.6.0 105 | 106 | 107 | stable 108 | stable 109 | 110 | Apache2.0 111 | 112 | - Fix #2 missing extension dependencies 113 | - Fix #3 Support PHP 7. 114 | - Support config curl_dns_cache_timeout,curl_connect_timeout,curl_timeout. 115 | 116 | 117 | 118 | 2016-12-27 119 | 120 | 121 | 0.9.0 122 | 0.9.0 123 | 124 | 125 | stable 126 | stable 127 | 128 | Apache2.0 129 | 130 | - Fix #5 undefined symbol: Z_TYPE_PP (PHP 7) 131 | - Support arg info for php --re. 132 | - Reformat function getDataByTpl(). 133 | - Support vc9. 134 | 135 | 136 | 137 | 2017-01-10 138 | 139 | 140 | 0.9.2 141 | 0.9.2 142 | 143 | 144 | stable 145 | stable 146 | 147 | Apache2.0 148 | 149 | - Fixed #7 Support multi instance by getInstance('instance_2') 150 | - Fixed zend_mm_heap corrupted 151 | 152 | 153 | 154 | -------------------------------------------------------------------------------- /php_druid.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | PHP-Druid | 4 | +----------------------------------------------------------------------+ 5 | | This source file is subject to version 2.0 of the Apache license, | 6 | | that is bundled with this package in the file LICENSE, and is | 7 | | available through the world-wide-web at the following url: | 8 | | http://www.apache.org/licenses/LICENSE-2.0.html | 9 | | If you did not receive a copy of the Apache2.0 license and are unable| 10 | | to obtain it through the world-wide-web, please send a note to | 11 | | license@php.net so we can mail you a copy immediately. | 12 | +----------------------------------------------------------------------+ 13 | | Author: Neeke.Gao | 14 | +----------------------------------------------------------------------+ 15 | */ 16 | 17 | #ifndef PHP_DRUID_H 18 | #define PHP_DRUID_H 19 | 20 | #define DRUID_NAME "Druid" 21 | #define DRUID_CREDITS "neeke@php.net" 22 | #define PHP_DRUID_VERSION "1.0.0" 23 | 24 | #define DRUID_CONTENT_TYPE "Content-Type:application/json" 25 | #define DRUID_PROPERTY_CURL_ERR_NO "_curl_error_no" 26 | #define DRUID_PROPERTY_CURL_ERR_STR "_curl_error_str" 27 | 28 | #define DRUID_PROPERTY_DEBUG "debug" 29 | 30 | #define DRUID_PROPERTY_RESPONSE_CODE "response_code" 31 | #define DRUID_PROPERTY_RESPONSE_INFO "response_debug_info" 32 | 33 | #define DRUID_PROPERTY_TPL_PATH "tpl_path" 34 | 35 | #define DRUID_PROPERTY_HOSTS "hosts" 36 | #define DRUID_PROPERTY_HOST_RAND "host_rand" 37 | #define DRUID_PROPERTY_HOST_RAND_BAR (double)0.5 38 | 39 | #define DRUID_INSTANCE_DEFAULT "default" 40 | #define DRUID_INSTANCE_DEFAULT_LEN strlen(DRUID_INSTANCE_DEFAULT) 41 | 42 | #define DRUID_RESPONSE_CODE_ERROR_BAR 399 43 | 44 | extern zend_module_entry druid_module_entry; 45 | #define phpext_druid_ptr &druid_module_entry 46 | 47 | 48 | 49 | #ifdef PHP_WIN32 50 | # define PHP_DRUID_API __declspec(dllexport) 51 | #elif defined(__GNUC__) && __GNUC__ >= 4 52 | # define PHP_DRUID_API __attribute__ ((visibility("default"))) 53 | #else 54 | # define PHP_DRUID_API 55 | #endif 56 | 57 | #ifdef ZTS 58 | #include "TSRM.h" 59 | #endif 60 | 61 | #include 62 | #include 63 | 64 | #ifdef PHP_WIN32 65 | #include "win32/time.h" 66 | #elif defined(NETWARE) 67 | #include 68 | #include 69 | #else 70 | #include 71 | #endif 72 | 73 | struct druidCurlResult { 74 | char *memory; 75 | size_t size; 76 | }; 77 | 78 | PHP_MINIT_FUNCTION(druid); 79 | PHP_MSHUTDOWN_FUNCTION(druid); 80 | PHP_RINIT_FUNCTION(druid); 81 | PHP_RSHUTDOWN_FUNCTION(druid); 82 | PHP_MINFO_FUNCTION(druid); 83 | 84 | zend_class_entry *druid_ce,*php_com_exception_class_entry; 85 | 86 | 87 | PHP_METHOD(DRUID_NAME, __construct); 88 | PHP_METHOD(DRUID_NAME, __destruct); 89 | PHP_METHOD(DRUID_NAME, __clone); 90 | PHP_METHOD(DRUID_NAME, __sleep); 91 | PHP_METHOD(DRUID_NAME, __wakeup); 92 | PHP_METHOD(DRUID_NAME, getInstance); 93 | PHP_METHOD(DRUID_NAME, debugWitch); 94 | PHP_METHOD(DRUID_NAME, getDebugWitch); 95 | PHP_METHOD(DRUID_NAME, setDruidHosts); 96 | PHP_METHOD(DRUID_NAME, getDruidHosts); 97 | PHP_METHOD(DRUID_NAME, setTplPath); 98 | PHP_METHOD(DRUID_NAME, getTplPath); 99 | PHP_METHOD(DRUID_NAME, getData); 100 | PHP_METHOD(DRUID_NAME, getDataByTpl); 101 | PHP_METHOD(DRUID_NAME, getDebugInfo); 102 | 103 | 104 | ZEND_BEGIN_MODULE_GLOBALS(druid) 105 | char *base_auth_user; 106 | char *base_auth_passport; 107 | char *host; 108 | char *tpl_path; 109 | zend_bool debug; 110 | 111 | int curl_dns_cache_timeout; 112 | int curl_connect_timeout; 113 | int curl_timeout; 114 | ZEND_END_MODULE_GLOBALS(druid) 115 | 116 | extern ZEND_DECLARE_MODULE_GLOBALS(druid); 117 | 118 | #ifdef ZTS 119 | #define DRUID_G(v) TSRMG(druid_globals_id, zend_druid_globals *, v) 120 | #else 121 | #define DRUID_G(v) (druid_globals.v) 122 | #endif 123 | 124 | #endif 125 | 126 | int druid_php_rand(TSRMLS_D); 127 | char *druid_get_host(zval *druid TSRMLS_DC); 128 | static void druid_getApi(zval *return_value, zval *druid, char *request_json TSRMLS_DC); 129 | int druid_get_debug_info(zval *druid,CURL *curl_handle,char *request_json TSRMLS_DC); 130 | int druid_get_contents(zval *druid,char *request_json, struct druidCurlResult *resultStr TSRMLS_DC); 131 | char *druid_file_get_contents_by_tpl(char *filename TSRMLS_DC); 132 | 133 | 134 | /* 135 | * Local variables: 136 | * tab-width: 4 137 | * c-basic-offset: 4 138 | * End: 139 | * vim600: noet sw=4 ts=4 fdm=marker 140 | * vim<600: noet sw=4 ts=4 141 | */ 142 | 143 | -------------------------------------------------------------------------------- /tests/001.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check for PHP-Druid presence 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 9 | --EXPECT-- 10 | druid extension is available 11 | 12 | -------------------------------------------------------------------------------- /tests/002.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check for PHP-Druid constant property 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 1); 8 | var_dump(is_string(Druid::DRUID_CONTENT_TYPE) && strlen(Druid::DRUID_CONTENT_TYPE) > 1); 9 | var_dump(is_string(Druid::DRUID_INSTANCE_DEFAULT) && strlen(Druid::DRUID_INSTANCE_DEFAULT) > 1); 10 | ?> 11 | --EXPECT-- 12 | bool(true) 13 | bool(true) 14 | bool(true) 15 | 16 | -------------------------------------------------------------------------------- /tests/003.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check for PHP-Druid getInstance function 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 14 | --EXPECT-- 15 | bool(true) 16 | bool(true) 17 | 18 | -------------------------------------------------------------------------------- /tests/004.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check for PHP-Druid debugWitch function and getDebugWitch function 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | debugWitch(false)); 11 | var_dump($oDruidDefault->getDebugWitch()); 12 | var_dump($oDruidDefault->debugWitch(true)); 13 | var_dump($oDruidDefault->getDebugWitch()); 14 | 15 | $oDruidMy = Druid::getInstance('my'); 16 | var_dump(is_object($oDruidMy)); 17 | var_dump(is_callable(array($oDruidMy,'debugWitch'))); 18 | var_dump($oDruidMy->debugWitch(false)); 19 | var_dump($oDruidMy->getDebugWitch()); 20 | var_dump($oDruidMy->debugWitch(true)); 21 | var_dump($oDruidMy->getDebugWitch()); 22 | 23 | ?> 24 | --EXPECT-- 25 | bool(true) 26 | bool(true) 27 | bool(true) 28 | bool(false) 29 | bool(true) 30 | bool(true) 31 | bool(true) 32 | bool(true) 33 | bool(true) 34 | bool(false) 35 | bool(true) 36 | bool(true) 37 | 38 | -------------------------------------------------------------------------------- /tests/005.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check for PHP-Druid setDruidHosts function and getDruidHosts function 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | getDruidHosts() == NULL); 13 | var_dump($oDruidDefault->setDruidHosts($aHosts)); 14 | var_dump($oDruidDefault->getDruidHosts() == $aHosts); 15 | 16 | 17 | $oDruidMy = Druid::getInstance('my'); 18 | var_dump(is_object($oDruidMy)); 19 | var_dump(is_callable(array($oDruidMy,'setDruidHosts'))); 20 | var_dump($oDruidMy->getDruidHosts() == NULL); 21 | var_dump($oDruidMy->setDruidHosts($aHosts)); 22 | var_dump($oDruidMy->getDruidHosts() == $aHosts); 23 | 24 | ?> 25 | --EXPECT-- 26 | bool(true) 27 | bool(true) 28 | bool(true) 29 | bool(true) 30 | bool(true) 31 | bool(true) 32 | bool(true) 33 | bool(true) 34 | bool(true) 35 | bool(true) 36 | 37 | -------------------------------------------------------------------------------- /tests/006.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check for PHP-Druid setTplPath function and getTplPath function 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | getTplPath() == $sTplPathDefault); 14 | var_dump($oDruidDefault->setTplPath($sTplPathMy)); 15 | var_dump($oDruidDefault->getTplPath() == $sTplPathMy); 16 | 17 | $oDruidMy = Druid::getInstance('my'); 18 | var_dump(is_object($oDruidMy)); 19 | var_dump(is_callable(array($oDruidMy,'setTplPath'))); 20 | var_dump($oDruidMy->getTplPath() == $sTplPathDefault); 21 | var_dump($oDruidMy->setTplPath($sTplPathMy)); 22 | var_dump($oDruidMy->getTplPath() == $sTplPathMy); 23 | 24 | ?> 25 | --EXPECT-- 26 | bool(true) 27 | bool(true) 28 | bool(true) 29 | bool(true) 30 | bool(true) 31 | bool(true) 32 | bool(true) 33 | bool(true) 34 | bool(true) 35 | bool(true) 36 | 37 | -------------------------------------------------------------------------------- /tests/007.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check for PHP-Druid getData function 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | setDruidHosts($aHostsDefault)); 15 | 16 | try { 17 | $result = $oDruidDefault->getData($request_json, array('dataSource'=>'aaa')); 18 | var_dump($result == NULL || is_array($result)); 19 | var_dump($oDruidDefault->getDebugInfo() == NULL || is_array($oDruidDefault->getDebugInfo())); 20 | } catch (Exception $e) { 21 | var_dump(is_string($e->getMessage())); 22 | var_dump($e->getCode() > 0); 23 | } 24 | 25 | ?> 26 | --EXPECTF-- 27 | bool(true) 28 | bool(true) 29 | bool(true) 30 | bool(true) 31 | bool(true) 32 | -------------------------------------------------------------------------------- /tests/008.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check for PHP-Druid getDataByTpl function and getDebugInfo function 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | debugWitch(true)); 14 | var_dump($oDruidDefault->setDruidHosts($aHostsDefault)); 15 | var_dump($oDruidDefault->setTplPath($sTplPath)); 16 | 17 | $result = NULL; 18 | $debugInfo = NULL; 19 | 20 | try { 21 | 22 | $result = $oDruidDefault->getDataByTpl('request_tpl_demo.json', array('@startTimeToEndTime@' => '["2016-12-10T14:06:00.000Z/2016-12-27T14:36:00.000Z"]')); 23 | $debugInfo = $oDruidDefault->getDebugInfo(); 24 | 25 | var_dump($result == NULL || is_array($result)); 26 | var_dump($debugInfo == NULL || is_array($debugInfo)); 27 | } catch (Exception $e) { 28 | var_dump(is_string($e->getMessage())); 29 | var_dump($e->getCode() > 0); 30 | } 31 | 32 | 33 | if (is_array($debugInfo)) 34 | { 35 | $url = array_key_exists('url',$debugInfo) ? $debugInfo['url'] : ''; 36 | foreach ($aHostsDefault as $_url) 37 | { 38 | if (strstr($url,$_url)) { 39 | var_dump(true); 40 | break; 41 | } else { 42 | continue; 43 | } 44 | } 45 | } 46 | else 47 | { 48 | var_dump(true); 49 | } 50 | 51 | ?> 52 | --EXPECT-- 53 | bool(true) 54 | bool(true) 55 | bool(true) 56 | bool(true) 57 | bool(true) 58 | bool(true) 59 | bool(true) 60 | bool(true) 61 | 62 | -------------------------------------------------------------------------------- /tests/druid.php: -------------------------------------------------------------------------------- 1 | setDruidHosts($array); 17 | 18 | var_dump($druid); 19 | 20 | var_dump($druid->getData($request_json, array('dataSource' => 'aaa'))); 21 | 22 | var_dump($druid); 23 | 24 | var_dump($druid->getDebugInfo()); 25 | } catch (Exception $e) { 26 | echo '
';
27 |     var_dump($druid->getDebugInfo());
28 |     exit(var_dump($e->getCode(), $e->getMessage()));
29 | }
30 | 


--------------------------------------------------------------------------------
/tests/issue7.php:
--------------------------------------------------------------------------------
 1 | aa = TRUE;
10 | $Druid_1->debugWitch(TRUE);
11 | 
12 | $Druid_2->debugWitch(FALSE);
13 | $Druid_2->bb = TRUE;
14 | 
15 | $Druid_3 = Druid::getInstance(Druid::DRUID_INSTANCE_DEFAULT);
16 | $Druid_4 = Druid::getInstance('druid_2');
17 | 
18 | var_dump($Druid_1 == $Druid_3, $Druid_2 == $Druid_4);


--------------------------------------------------------------------------------
/travis/compile.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | phpize && ./configure && make clean && make
3 | 


--------------------------------------------------------------------------------