├── LICENSE ├── README.md ├── config.m4 ├── config.w32 ├── php_symfony_dic.h └── symfony_dic.c /LICENSE: -------------------------------------------------------------------------------- 1 | Julien Pauli 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is furnished 8 | to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Symfony Dependency Injection Container Optimizer 2 | ================================================ 3 | 4 | This extension declares a Symfony\Component\DependencyInjection\ContainerOptimizerInterface interface. 5 | 6 | Simply make your container implement it : 7 | 8 | ```php 9 | phpize 24 | > ./configure 25 | > make 26 | > make install 27 | 28 | 29 | * Supports PHP 5.3, 5.4, 5.5 and 5.6 30 | * Supports ZTS -------------------------------------------------------------------------------- /config.m4: -------------------------------------------------------------------------------- 1 | dnl $Id$ 2 | dnl config.m4 for extension symfony_dic 3 | 4 | dnl Comments in this file start with the string 'dnl'. 5 | dnl Remove where necessary. This file will not work 6 | dnl without editing. 7 | 8 | dnl If your extension references something external, use with: 9 | 10 | dnl PHP_ARG_WITH(symfony_dic, for symfony_dic support, 11 | dnl Make sure that the comment is aligned: 12 | dnl [ --with-symfony_dic Include symfony_dic support]) 13 | 14 | dnl Otherwise use enable: 15 | 16 | PHP_ARG_ENABLE(symfony_dic, whether to enable symfony_dic support, 17 | dnl Make sure that the comment is aligned: 18 | [ --enable-symfony_dic Enable symfony_dic support]) 19 | 20 | if test "$PHP_SYMFONY_DIC" != "no"; then 21 | dnl Write more examples of tests here... 22 | 23 | dnl # --with-symfony_dic -> check with-path 24 | dnl SEARCH_PATH="/usr/local /usr" # you might want to change this 25 | dnl SEARCH_FOR="/include/symfony_dic.h" # you most likely want to change this 26 | dnl if test -r $PHP_SYMFONY_DIC/$SEARCH_FOR; then # path given as parameter 27 | dnl SYMFONY_DIC_DIR=$PHP_SYMFONY_DIC 28 | dnl else # search default path list 29 | dnl AC_MSG_CHECKING([for symfony_dic files in default path]) 30 | dnl for i in $SEARCH_PATH ; do 31 | dnl if test -r $i/$SEARCH_FOR; then 32 | dnl SYMFONY_DIC_DIR=$i 33 | dnl AC_MSG_RESULT(found in $i) 34 | dnl fi 35 | dnl done 36 | dnl fi 37 | dnl 38 | dnl if test -z "$SYMFONY_DIC_DIR"; then 39 | dnl AC_MSG_RESULT([not found]) 40 | dnl AC_MSG_ERROR([Please reinstall the symfony_dic distribution]) 41 | dnl fi 42 | 43 | dnl # --with-symfony_dic -> add include path 44 | dnl PHP_ADD_INCLUDE($SYMFONY_DIC_DIR/include) 45 | 46 | dnl # --with-symfony_dic -> check for lib and symbol presence 47 | dnl LIBNAME=symfony_dic # you may want to change this 48 | dnl LIBSYMBOL=symfony_dic # you most likely want to change this 49 | 50 | dnl PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL, 51 | dnl [ 52 | dnl PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $SYMFONY_DIC_DIR/$PHP_LIBDIR, SYMFONY_DIC_SHARED_LIBADD) 53 | dnl AC_DEFINE(HAVE_SYMFONY_DICLIB,1,[ ]) 54 | dnl ],[ 55 | dnl AC_MSG_ERROR([wrong symfony_dic lib version or lib not found]) 56 | dnl ],[ 57 | dnl -L$SYMFONY_DIC_DIR/$PHP_LIBDIR -lm 58 | dnl ]) 59 | dnl 60 | dnl PHP_SUBST(SYMFONY_DIC_SHARED_LIBADD) 61 | 62 | PHP_NEW_EXTENSION(symfony_dic, symfony_dic.c, $ext_shared) 63 | fi 64 | -------------------------------------------------------------------------------- /config.w32: -------------------------------------------------------------------------------- 1 | // $Id$ 2 | // vim:ft=javascript 3 | 4 | // If your extension references something external, use ARG_WITH 5 | // ARG_WITH("symfony_dic", "for symfony_dic support", "no"); 6 | 7 | // Otherwise, use ARG_ENABLE 8 | // ARG_ENABLE("symfony_dic", "enable symfony_dic support", "no"); 9 | 10 | if (PHP_SYMFONY_DIC != "no") { 11 | EXTENSION("symfony_dic", "symfony_dic.c"); 12 | } 13 | 14 | -------------------------------------------------------------------------------- /php_symfony_dic.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | PHP Version 5 | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 1997-2014 The PHP Group | 6 | +----------------------------------------------------------------------+ 7 | | This source file is subject to version 3.01 of the PHP license, | 8 | | that is bundled with this package in the file LICENSE, and is | 9 | | available through the world-wide-web at the following url: | 10 | | http://www.php.net/license/3_01.txt | 11 | | If you did not receive a copy of the PHP license and are unable to | 12 | | obtain it through the world-wide-web, please send a note to | 13 | | license@php.net so we can mail you a copy immediately. | 14 | +----------------------------------------------------------------------+ 15 | | Author: Julien Pauli | 16 | +----------------------------------------------------------------------+ 17 | */ 18 | 19 | /* $Id$ */ 20 | 21 | #ifndef PHP_SYMFONY_DIC_H 22 | #define PHP_SYMFONY_DIC_H 23 | 24 | extern zend_module_entry symfony_dic_module_entry; 25 | #define phpext_symfony_dic_ptr &symfony_dic_module_entry 26 | zend_module_entry *get_module(void); 27 | 28 | #define PHP_SYMFONY_DIC_VERSION "0.1.0" 29 | 30 | #ifdef PHP_WIN32 31 | # define PHP_SYMFONY_DIC_API __declspec(dllexport) 32 | #elif defined(__GNUC__) && __GNUC__ >= 4 33 | # define PHP_SYMFONY_DIC_API __attribute__ ((visibility("default"))) 34 | #else 35 | # define PHP_SYMFONY_DIC_API 36 | #endif 37 | 38 | #ifdef ZTS 39 | #include "TSRM.h" 40 | #endif 41 | 42 | #ifndef RETVAL_ZVAL_FAST 43 | #define RETVAL_ZVAL_FAST(z) do { \ 44 | zval *_z = (z); \ 45 | if (Z_ISREF_P(_z)) { \ 46 | RETVAL_ZVAL(_z, 1, 0); \ 47 | } else { \ 48 | zval_ptr_dtor(&return_value); \ 49 | Z_ADDREF_P(_z); \ 50 | *return_value_ptr = _z; \ 51 | } \ 52 | } while (0) 53 | #endif 54 | 55 | ZEND_BEGIN_MODULE_GLOBALS(symfony_dic) 56 | char cache_done; 57 | long invalid_behavior; 58 | zend_class_entry *ServiceCircularReferenceException; 59 | zend_class_entry *ServiceNotFoundException; 60 | zend_class_entry *InactiveScopeException; 61 | ZEND_END_MODULE_GLOBALS(symfony_dic) 62 | 63 | ZEND_DECLARE_MODULE_GLOBALS(symfony_dic); 64 | 65 | PHP_GINIT_FUNCTION(symfony_dic); 66 | PHP_GSHUTDOWN_FUNCTION(symfony_dic); 67 | PHP_MINIT_FUNCTION(symfony_dic); 68 | PHP_MSHUTDOWN_FUNCTION(symfony_dic); 69 | PHP_RINIT_FUNCTION(symfony_dic); 70 | PHP_RSHUTDOWN_FUNCTION(symfony_dic); 71 | PHP_MINFO_FUNCTION(symfony_dic); 72 | 73 | #define OVERWRITE_METHOD(meth) \ 74 | zend_function *meth; \ 75 | \ 76 | if (zend_hash_find(&ce->function_table, #meth, sizeof(#meth), (void **)&meth) == FAILURE) { \ 77 | return FAILURE; \ 78 | } \ 79 | zend_function_dtor(meth); \ 80 | \ 81 | meth->type = ZEND_INTERNAL_FUNCTION; \ 82 | meth->internal_function.handler = dic_optimizer_##meth##_handler; \ 83 | meth->internal_function.module = &symfony_dic_module_entry; \ 84 | meth->internal_function.arg_info = (zend_arg_info *)dic_optimizer_##meth##_arg_infos; 85 | 86 | #define RETURN_THIS RETURN_ZVAL(getThis(), 1, 0) 87 | #define SYMFONY_DIC_TOKEN_ALIASES_KEY "aliases" 88 | #define SYMFONY_DIC_TOKEN_SERVICES_KEY "services" 89 | #define SYMFONY_DIC_TOKEN_LOADING_KEY "loading" 90 | #define SYMFONY_DIC_TOKEN_METHODMAP_KEY "methodMap" 91 | 92 | #define SYMFONY_DIC_TOKEN_SERVICE_CIRCULAR_REFERENCE_EXCEPTION_KEY_UP "Symfony\\Component\\DependencyInjection\\Exception\\ServiceCircularReferenceException" 93 | #define SYMFONY_DIC_TOKEN_SERVICE_NOT_FOUND_EXCEPTION_KEY_UP "Symfony\\Component\\DependencyInjection\\Exception\\ServiceNotFoundException" 94 | #define SYMFONY_DIC_TOKEN_INACTIVE_SCOPE_EXCEPTION_KEY_UP "Symfony\\Component\\DependencyInjection\\Exception\\InactiveScopeException" 95 | 96 | #ifdef ZTS 97 | #define SYMFONY_DIC_G(v) TSRMG(symfony_dic_globals_id, zend_symfony_dic_globals *, v) 98 | #else 99 | #define SYMFONY_DIC_G(v) (symfony_dic_globals.v) 100 | #endif 101 | 102 | #endif /* PHP_SYMFONY_DIC_H */ 103 | -------------------------------------------------------------------------------- /symfony_dic.c: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | PHP Version 5 | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 1997-2014 The PHP Group | 6 | +----------------------------------------------------------------------+ 7 | | This source file is subject to version 3.01 of the PHP license, | 8 | | that is bundled with this package in the file LICENSE, and is | 9 | | available through the world-wide-web at the following url: | 10 | | http://www.php.net/license/3_01.txt | 11 | | If you did not receive a copy of the PHP license and are unable to | 12 | | obtain it through the world-wide-web, please send a note to | 13 | | license@php.net so we can mail you a copy immediately. | 14 | +----------------------------------------------------------------------+ 15 | | Author: Julien Pauli | 16 | +----------------------------------------------------------------------+ 17 | */ 18 | 19 | /* $Id$ */ 20 | 21 | #ifdef HAVE_CONFIG_H 22 | #include "config.h" 23 | #endif 24 | 25 | #include "php.h" 26 | #include "php_ini.h" 27 | #include "ext/standard/info.h" 28 | #include "ext/standard/php_string.h" 29 | #include "php_symfony_dic.h" 30 | #include "Zend/zend_exceptions.h" 31 | 32 | static zend_class_entry *dic_optimizer_ce; 33 | 34 | ZEND_BEGIN_ARG_INFO(dic_optimizer_get_arg_infos, 0) 35 | ZEND_ARG_INFO(0, id) 36 | ZEND_ARG_INFO(0, invalidBehavior) 37 | ZEND_END_ARG_INFO() 38 | 39 | ZEND_BEGIN_ARG_INFO(dic_optimizer_has_arg_infos, 0) 40 | ZEND_ARG_INFO(0, id) 41 | ZEND_END_ARG_INFO() 42 | 43 | ZEND_BEGIN_ARG_INFO(dic_optimizer_camelize_arg_infos, 0) 44 | ZEND_ARG_INFO(0, id) 45 | ZEND_END_ARG_INFO() 46 | 47 | zend_module_entry symfony_dic_module_entry = { 48 | STANDARD_MODULE_HEADER, 49 | "symfony_dic", 50 | NULL, 51 | PHP_MINIT(symfony_dic), 52 | NULL, 53 | PHP_RINIT(symfony_dic), 54 | NULL, 55 | PHP_MINFO(symfony_dic), 56 | PHP_SYMFONY_DIC_VERSION, 57 | PHP_MODULE_GLOBALS(symfony_dic), 58 | PHP_GINIT(symfony_dic), 59 | NULL, 60 | NULL, 61 | STANDARD_MODULE_PROPERTIES_EX 62 | }; 63 | 64 | #ifdef COMPILE_DL_SYMFONY_DIC 65 | ZEND_GET_MODULE(symfony_dic) 66 | #endif 67 | 68 | PHP_GINIT_FUNCTION(symfony_dic) 69 | { 70 | memset(&symfony_dic_globals, 0, sizeof(symfony_dic_globals)); 71 | } 72 | 73 | static void dic_optimizer_get_handler(INTERNAL_FUNCTION_PARAMETERS) 74 | { 75 | char *id, should_free = 1; 76 | zend_ulong id_hash; 77 | int id_len, i; 78 | long oninvalid, exception_on_invalid_reference_const; 79 | zval **found_service, **alias, **method_in_map = NULL, *this_services, *this_aliases, *this_methodMap, *this_loading; 80 | zend_function *method = NULL; 81 | 82 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &id, &id_len, &oninvalid) == FAILURE) { 83 | return; 84 | } 85 | 86 | if (strcmp(id, "service_container") == 0) { 87 | RETURN_THIS; 88 | } 89 | 90 | this_services = zend_read_property(Z_OBJCE_P(getThis()), getThis(), SYMFONY_DIC_TOKEN_SERVICES_KEY, sizeof(SYMFONY_DIC_TOKEN_SERVICES_KEY) - 1, 0 TSRMLS_CC); 91 | this_aliases = zend_read_property(Z_OBJCE_P(getThis()), getThis(), SYMFONY_DIC_TOKEN_ALIASES_KEY, sizeof(SYMFONY_DIC_TOKEN_ALIASES_KEY) - 1, 0 TSRMLS_CC); 92 | this_loading = zend_read_property(Z_OBJCE_P(getThis()), getThis(), SYMFONY_DIC_TOKEN_LOADING_KEY, sizeof(SYMFONY_DIC_TOKEN_LOADING_KEY) - 1, 0 TSRMLS_CC); 93 | this_methodMap = zend_read_property(Z_OBJCE_P(getThis()), getThis(), SYMFONY_DIC_TOKEN_METHODMAP_KEY, sizeof(SYMFONY_DIC_TOKEN_METHODMAP_KEY) - 1, 0 TSRMLS_CC); 94 | 95 | if (!SYMFONY_DIC_G(cache_done)) { 96 | zval invalidBehavior; 97 | zend_class_entry **exception_ce; 98 | 99 | zend_get_constant_ex("self::EXCEPTION_ON_INVALID_REFERENCE", sizeof("self::EXCEPTION_ON_INVALID_REFERENCE") - 1, &invalidBehavior, Z_OBJCE_P(getThis()), 0 TSRMLS_CC); 100 | SYMFONY_DIC_G(invalid_behavior) = Z_LVAL(invalidBehavior); 101 | 102 | if (FAILURE == zend_lookup_class(SYMFONY_DIC_TOKEN_SERVICE_CIRCULAR_REFERENCE_EXCEPTION_KEY_UP, sizeof(SYMFONY_DIC_TOKEN_SERVICE_CIRCULAR_REFERENCE_EXCEPTION_KEY_UP) - 1, &exception_ce TSRMLS_CC)) { 103 | zend_error_noreturn(E_ERROR, "Class %s not found", SYMFONY_DIC_TOKEN_SERVICE_CIRCULAR_REFERENCE_EXCEPTION_KEY_UP); 104 | } 105 | SYMFONY_DIC_G(ServiceCircularReferenceException) = *exception_ce; 106 | if (FAILURE == zend_lookup_class(SYMFONY_DIC_TOKEN_SERVICE_NOT_FOUND_EXCEPTION_KEY_UP, sizeof(SYMFONY_DIC_TOKEN_SERVICE_NOT_FOUND_EXCEPTION_KEY_UP) - 1, &exception_ce TSRMLS_CC)) { 107 | zend_error_noreturn(E_ERROR, "Class %s not found", SYMFONY_DIC_TOKEN_SERVICE_NOT_FOUND_EXCEPTION_KEY_UP); 108 | } 109 | SYMFONY_DIC_G(ServiceNotFoundException) = *exception_ce; 110 | if (FAILURE == zend_lookup_class(SYMFONY_DIC_TOKEN_INACTIVE_SCOPE_EXCEPTION_KEY_UP, sizeof(SYMFONY_DIC_TOKEN_INACTIVE_SCOPE_EXCEPTION_KEY_UP) - 1, &exception_ce TSRMLS_CC)) { 111 | zend_error_noreturn(E_ERROR, "Class %s not found", SYMFONY_DIC_TOKEN_INACTIVE_SCOPE_EXCEPTION_KEY_UP); 112 | } 113 | SYMFONY_DIC_G(InactiveScopeException) = *exception_ce; 114 | 115 | SYMFONY_DIC_G(cache_done) = 1; 116 | } 117 | 118 | exception_on_invalid_reference_const = SYMFONY_DIC_G(invalid_behavior); 119 | 120 | if (ZEND_NUM_ARGS() <= 1) { 121 | oninvalid = exception_on_invalid_reference_const; 122 | } 123 | 124 | if (IS_INTERNED(id)) { 125 | id_hash = INTERNED_HASH(id); 126 | } else { 127 | id_hash = zend_inline_hash_func(id, id_len + 1); 128 | } 129 | 130 | id = estrndup(id, id_len); /* zend_str_tolower will change it otherwise */ 131 | 132 | for (i = 0; i <= 1; i++, zend_str_tolower(id, id_len), id_hash = zend_inline_hash_func(id, id_len + 1)) { 133 | if (zend_hash_quick_find(Z_ARRVAL_P(this_aliases), id, id_len + 1, id_hash, (void **)&alias) == SUCCESS) { 134 | should_free = 0; 135 | efree(id); 136 | id = Z_STRVAL_PP(alias); 137 | id_len = Z_STRLEN_PP(alias); 138 | id_hash = zend_inline_hash_func(id, id_len + 1); 139 | } 140 | if (zend_hash_quick_find(Z_ARRVAL_P(this_services), id, id_len + 1, id_hash, (void **)&found_service) == SUCCESS) { 141 | RETVAL_ZVAL_FAST(*found_service); 142 | goto free_and_return; 143 | } 144 | } 145 | 146 | if (zend_hash_quick_exists(Z_ARRVAL_P(this_loading), id, id_len + 1, id_hash)) { 147 | zval *ServiceCircularReferenceException; 148 | ALLOC_INIT_ZVAL(ServiceCircularReferenceException); /* ctor_args */ 149 | object_init_ex(ServiceCircularReferenceException, SYMFONY_DIC_G(ServiceCircularReferenceException)); 150 | zend_throw_exception_object(ServiceCircularReferenceException TSRMLS_CC); 151 | goto free_and_return; 152 | } 153 | 154 | zend_hash_quick_find(Z_ARRVAL_P(this_methodMap), id, id_len + 1, id_hash, (void **)&method_in_map); 155 | 156 | if (!method_in_map) { 157 | char *new_id; 158 | 159 | for (i=0; i < id_len; i++) { 160 | if (id[i] == '_') { 161 | memmove(&id[i], &id[i + 1], --id_len); 162 | } 163 | } 164 | php_strtr(id, id_len, ".\\", "__", 2); 165 | id_len = spprintf(&new_id, 0, "get%sservice", id); 166 | efree(id); 167 | id = new_id; 168 | id_hash = zend_inline_hash_func(id, id_len + 1); 169 | 170 | zend_hash_quick_find(&Z_OBJCE_P(getThis())->function_table, id, id_len + 1, id_hash, (void **)&method); 171 | if (!method) { 172 | if (oninvalid == exception_on_invalid_reference_const) { 173 | zval *ServiceNotFoundException; 174 | ALLOC_INIT_ZVAL(ServiceNotFoundException); 175 | object_init_ex(ServiceNotFoundException, SYMFONY_DIC_G(ServiceNotFoundException)); 176 | zend_throw_exception_object(ServiceNotFoundException TSRMLS_CC); /* ctor_args */ 177 | } 178 | goto free_and_return; 179 | } 180 | } else { 181 | char *method_name_lc; 182 | method_name_lc = zend_str_tolower_dup(Z_STRVAL_PP(method_in_map), Z_STRLEN_PP(method_in_map)); 183 | zend_hash_find(&Z_OBJCE_P(getThis())->function_table, method_name_lc, Z_STRLEN_PP(method_in_map) + 1, (void **)&method); 184 | efree(method_name_lc); 185 | } 186 | 187 | zend_fcall_info fci = {0}; 188 | zend_fcall_info_cache fcic = {0}; 189 | zval *loading, *result; 190 | 191 | ALLOC_INIT_ZVAL(loading); ZVAL_BOOL(loading, 1); 192 | zend_hash_quick_add(Z_ARRVAL_P(this_loading), id, id_len + 1, id_hash, &loading, sizeof(zval *), NULL); 193 | 194 | fcic.called_scope = Z_OBJCE_P(getThis()); 195 | fcic.calling_scope = Z_OBJCE_P(getThis()); 196 | fcic.function_handler = method; 197 | fcic.initialized = 1; 198 | fcic.object_ptr = getThis(); 199 | 200 | fci.retval_ptr_ptr = &result; 201 | fci.size = sizeof(zend_fcall_info); 202 | 203 | zend_call_function(&fci, &fcic TSRMLS_CC); 204 | 205 | zend_hash_quick_del(Z_ARRVAL_P(this_loading), id, id_len + 1, id_hash); 206 | 207 | if (!EG(exception)) { 208 | RETVAL_ZVAL_FAST(result); 209 | } else { 210 | zend_hash_quick_del(Z_ARRVAL_P(this_services), id, id_len, id_hash); 211 | 212 | if (instanceof_function(Z_OBJCE_P(EG(exception)), SYMFONY_DIC_G(InactiveScopeException) TSRMLS_CC) && oninvalid == exception_on_invalid_reference_const) { 213 | EG(exception) = NULL; 214 | } 215 | } 216 | zval_ptr_dtor(&result); 217 | free_and_return: 218 | if (should_free) { efree(id); } 219 | return; 220 | } 221 | 222 | static void dic_optimizer_has_handler(INTERNAL_FUNCTION_PARAMETERS) 223 | { 224 | char *id, *new_id, lowered = 0; 225 | int id_len, result; 226 | zval *this_services, *this_aliases; 227 | zend_ulong id_hash; 228 | 229 | if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &id, &id_len) == FAILURE) { 230 | return; 231 | } 232 | 233 | if (strcmp(id, "service_container") == 0) { 234 | RETURN_TRUE 235 | } 236 | 237 | this_services = zend_read_property(Z_OBJCE_P(getThis()), getThis(), SYMFONY_DIC_TOKEN_SERVICES_KEY, sizeof(SYMFONY_DIC_TOKEN_SERVICES_KEY) - 1, 0 TSRMLS_CC); 238 | this_aliases = zend_read_property(Z_OBJCE_P(getThis()), getThis(), SYMFONY_DIC_TOKEN_ALIASES_KEY, sizeof(SYMFONY_DIC_TOKEN_ALIASES_KEY) - 1, 0 TSRMLS_CC); 239 | 240 | find: 241 | if (IS_INTERNED(id)) { 242 | id_hash = INTERNED_HASH(id); 243 | } else { 244 | id_hash = zend_inline_hash_func(id, id_len + 1); 245 | } 246 | 247 | if (zend_hash_quick_exists(Z_ARRVAL_P(this_aliases), id, id_len + 1, id_hash) || 248 | zend_hash_quick_exists(Z_ARRVAL_P(this_services), id, id_len + 1, id_hash)) { 249 | goto return_true; 250 | } 251 | 252 | if (!lowered) { 253 | lowered = 1; 254 | id = zend_str_tolower_dup(id, id_len); 255 | goto find; 256 | } 257 | 258 | php_strtr(id, id_len, ".\\", "__", 2); 259 | id_len = spprintf(&new_id, 0, "get%sservice", id); 260 | 261 | result = zend_hash_exists(&Z_OBJCE_P(getThis())->function_table, new_id, id_len + 1); 262 | efree(new_id); 263 | 264 | if (result) { 265 | goto return_true; 266 | } else { 267 | goto return_false; 268 | } 269 | 270 | return_true: 271 | if (lowered) { efree(id); } 272 | RETURN_TRUE; 273 | return_false: 274 | if (lowered) { efree(id); } 275 | RETURN_FALSE; 276 | } 277 | 278 | static void dic_optimizer_camelize_handler(INTERNAL_FUNCTION_PARAMETERS) 279 | { 280 | char *arg = NULL; 281 | int arg_len, i; 282 | 283 | if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &arg, &arg_len) == FAILURE) { 284 | return; 285 | } 286 | 287 | php_strtr(arg, arg_len, "_.\\", " __", 3); 288 | for (i=arg_len; i>=0; i--) { 289 | if (arg[i] == ' ') { 290 | arg[i+1] = toupper(arg[i+1]); 291 | memmove(&arg[i], &arg[i+1], --arg_len); 292 | } 293 | } 294 | arg[0] = toupper(arg[0]); 295 | 296 | RETURN_STRINGL(arg, arg_len, 1); 297 | } 298 | 299 | static int dic_optimizer_interface_gets_implemented(zend_class_entry *iface, zend_class_entry *ce TSRMLS_DC) 300 | { 301 | OVERWRITE_METHOD(get) 302 | OVERWRITE_METHOD(has) 303 | OVERWRITE_METHOD(camelize) 304 | 305 | return SUCCESS; 306 | } 307 | 308 | PHP_MINIT_FUNCTION(symfony_dic) 309 | { 310 | zend_class_entry dic_optimizer; 311 | INIT_NS_CLASS_ENTRY(dic_optimizer, "Symfony\\Component\\DependencyInjection", "ContainerOptimizerInterface", NULL); 312 | 313 | dic_optimizer_ce = zend_register_internal_interface(&dic_optimizer TSRMLS_CC); 314 | dic_optimizer_ce->interface_gets_implemented = dic_optimizer_interface_gets_implemented; 315 | 316 | return SUCCESS; 317 | } 318 | 319 | PHP_RINIT_FUNCTION(symfony_dic) 320 | { 321 | SYMFONY_DIC_G(cache_done) = 0; 322 | SYMFONY_DIC_G(ServiceCircularReferenceException) = 323 | SYMFONY_DIC_G(ServiceNotFoundException) = 324 | SYMFONY_DIC_G(InactiveScopeException) = NULL; 325 | 326 | return SUCCESS; 327 | } 328 | 329 | PHP_MINFO_FUNCTION(symfony_dic) 330 | { 331 | php_info_print_table_start(); 332 | php_info_print_table_header(2, "Symfony DIC optimizer support", "enabled"); 333 | php_info_print_table_end(); 334 | } 335 | --------------------------------------------------------------------------------