File manager - Edit - /home/premiey/www/wp-includes/images/media/pimple.tar
Back
ext/pimple/pimple.c 0000666 00000111520 15165571133 0010277 0 ustar 00 /* * This file is part of Pimple. * * Copyright (c) 2014 Fabien Potencier * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is furnished * to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #include "php_ini.h" #include "ext/standard/info.h" #include "php_pimple.h" #include "pimple_compat.h" #include "zend_interfaces.h" #include "zend.h" #include "Zend/zend_closures.h" #include "ext/spl/spl_exceptions.h" #include "Zend/zend_exceptions.h" #include "main/php_output.h" #include "SAPI.h" static zend_class_entry *pimple_ce_PsrContainerInterface; static zend_class_entry *pimple_ce_PsrContainerExceptionInterface; static zend_class_entry *pimple_ce_PsrNotFoundExceptionInterface; static zend_class_entry *pimple_ce_ExpectedInvokableException; static zend_class_entry *pimple_ce_FrozenServiceException; static zend_class_entry *pimple_ce_InvalidServiceIdentifierException; static zend_class_entry *pimple_ce_UnknownIdentifierException; static zend_class_entry *pimple_ce; static zend_object_handlers pimple_object_handlers; static zend_class_entry *pimple_closure_ce; static zend_class_entry *pimple_serviceprovider_ce; static zend_object_handlers pimple_closure_object_handlers; static zend_internal_function pimple_closure_invoker_function; #define FETCH_DIM_HANDLERS_VARS pimple_object *pimple_obj = NULL; \ ulong index; \ pimple_obj = (pimple_object *)zend_object_store_get_object(object TSRMLS_CC); \ #define PIMPLE_OBJECT_HANDLE_INHERITANCE_OBJECT_HANDLERS do { \ if (ce != pimple_ce) { \ zend_hash_find(&ce->function_table, ZEND_STRS("offsetget"), (void **)&function); \ if (function->common.scope != ce) { /* if the function is not defined in this actual class */ \ pimple_object_handlers.read_dimension = pimple_object_read_dimension; /* then overwrite the handler to use custom one */ \ } \ zend_hash_find(&ce->function_table, ZEND_STRS("offsetset"), (void **)&function); \ if (function->common.scope != ce) { \ pimple_object_handlers.write_dimension = pimple_object_write_dimension; \ } \ zend_hash_find(&ce->function_table, ZEND_STRS("offsetexists"), (void **)&function); \ if (function->common.scope != ce) { \ pimple_object_handlers.has_dimension = pimple_object_has_dimension; \ } \ zend_hash_find(&ce->function_table, ZEND_STRS("offsetunset"), (void **)&function); \ if (function->common.scope != ce) { \ pimple_object_handlers.unset_dimension = pimple_object_unset_dimension; \ } \ } else { \ pimple_object_handlers.read_dimension = pimple_object_read_dimension; \ pimple_object_handlers.write_dimension = pimple_object_write_dimension; \ pimple_object_handlers.has_dimension = pimple_object_has_dimension; \ pimple_object_handlers.unset_dimension = pimple_object_unset_dimension; \ }\ } while(0); #define PIMPLE_CALL_CB do { \ zend_fcall_info_argn(&fci TSRMLS_CC, 1, &object); \ fci.size = sizeof(fci); \ fci.object_ptr = retval->fcc.object_ptr; \ fci.function_name = retval->value; \ fci.no_separation = 1; \ fci.retval_ptr_ptr = &retval_ptr_ptr; \ \ zend_call_function(&fci, &retval->fcc TSRMLS_CC); \ efree(fci.params); \ if (EG(exception)) { \ return EG(uninitialized_zval_ptr); \ } \ } while(0); /* Psr\Container\ContainerInterface */ ZEND_BEGIN_ARG_INFO_EX(arginfo_pimple_PsrContainerInterface_get, 0, 0, 1) ZEND_ARG_INFO(0, id) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_pimple_PsrContainerInterface_has, 0, 0, 1) ZEND_ARG_INFO(0, id) ZEND_END_ARG_INFO() static const zend_function_entry pimple_ce_PsrContainerInterface_functions[] = { PHP_ABSTRACT_ME(ContainerInterface, get, arginfo_pimple_PsrContainerInterface_get) PHP_ABSTRACT_ME(ContainerInterface, has, arginfo_pimple_PsrContainerInterface_has) PHP_FE_END }; /* Psr\Container\ContainerExceptionInterface */ static const zend_function_entry pimple_ce_PsrContainerExceptionInterface_functions[] = { PHP_FE_END }; /* Psr\Container\NotFoundExceptionInterface */ static const zend_function_entry pimple_ce_PsrNotFoundExceptionInterface_functions[] = { PHP_FE_END }; /* Pimple\Exception\FrozenServiceException */ ZEND_BEGIN_ARG_INFO_EX(arginfo_FrozenServiceException___construct, 0, 0, 1) ZEND_ARG_INFO(0, id) ZEND_END_ARG_INFO() static const zend_function_entry pimple_ce_FrozenServiceException_functions[] = { PHP_ME(FrozenServiceException, __construct, arginfo_FrozenServiceException___construct, ZEND_ACC_PUBLIC) PHP_FE_END }; /* Pimple\Exception\InvalidServiceIdentifierException */ ZEND_BEGIN_ARG_INFO_EX(arginfo_InvalidServiceIdentifierException___construct, 0, 0, 1) ZEND_ARG_INFO(0, id) ZEND_END_ARG_INFO() static const zend_function_entry pimple_ce_InvalidServiceIdentifierException_functions[] = { PHP_ME(InvalidServiceIdentifierException, __construct, arginfo_InvalidServiceIdentifierException___construct, ZEND_ACC_PUBLIC) PHP_FE_END }; /* Pimple\Exception\UnknownIdentifierException */ ZEND_BEGIN_ARG_INFO_EX(arginfo_UnknownIdentifierException___construct, 0, 0, 1) ZEND_ARG_INFO(0, id) ZEND_END_ARG_INFO() static const zend_function_entry pimple_ce_UnknownIdentifierException_functions[] = { PHP_ME(UnknownIdentifierException, __construct, arginfo_UnknownIdentifierException___construct, ZEND_ACC_PUBLIC) PHP_FE_END }; /* Pimple\Container */ ZEND_BEGIN_ARG_INFO_EX(arginfo___construct, 0, 0, 0) ZEND_ARG_ARRAY_INFO(0, value, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetset, 0, 0, 2) ZEND_ARG_INFO(0, offset) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetget, 0, 0, 1) ZEND_ARG_INFO(0, offset) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetexists, 0, 0, 1) ZEND_ARG_INFO(0, offset) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetunset, 0, 0, 1) ZEND_ARG_INFO(0, offset) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_factory, 0, 0, 1) ZEND_ARG_INFO(0, callable) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_protect, 0, 0, 1) ZEND_ARG_INFO(0, callable) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_raw, 0, 0, 1) ZEND_ARG_INFO(0, id) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_extend, 0, 0, 2) ZEND_ARG_INFO(0, id) ZEND_ARG_INFO(0, callable) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_keys, 0, 0, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_register, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, provider, Pimple\\ServiceProviderInterface, 0) ZEND_ARG_ARRAY_INFO(0, values, 1) ZEND_END_ARG_INFO() static const zend_function_entry pimple_ce_functions[] = { PHP_ME(Pimple, __construct, arginfo___construct, ZEND_ACC_PUBLIC) PHP_ME(Pimple, factory, arginfo_factory, ZEND_ACC_PUBLIC) PHP_ME(Pimple, protect, arginfo_protect, ZEND_ACC_PUBLIC) PHP_ME(Pimple, raw, arginfo_raw, ZEND_ACC_PUBLIC) PHP_ME(Pimple, extend, arginfo_extend, ZEND_ACC_PUBLIC) PHP_ME(Pimple, keys, arginfo_keys, ZEND_ACC_PUBLIC) PHP_ME(Pimple, register, arginfo_register, ZEND_ACC_PUBLIC) PHP_ME(Pimple, offsetSet, arginfo_offsetset, ZEND_ACC_PUBLIC) PHP_ME(Pimple, offsetGet, arginfo_offsetget, ZEND_ACC_PUBLIC) PHP_ME(Pimple, offsetExists, arginfo_offsetexists, ZEND_ACC_PUBLIC) PHP_ME(Pimple, offsetUnset, arginfo_offsetunset, ZEND_ACC_PUBLIC) PHP_FE_END }; /* Pimple\ServiceProviderInterface */ ZEND_BEGIN_ARG_INFO_EX(arginfo_serviceprovider_register, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, pimple, Pimple\\Container, 0) ZEND_END_ARG_INFO() static const zend_function_entry pimple_serviceprovider_iface_ce_functions[] = { PHP_ABSTRACT_ME(ServiceProviderInterface, register, arginfo_serviceprovider_register) PHP_FE_END }; /* parent::__construct(sprintf("Something with %s", $arg1)) */ static void pimple_exception_call_parent_constructor(zval *this_ptr, const char *format, const char *arg1 TSRMLS_DC) { zend_class_entry *ce = Z_OBJCE_P(this_ptr); char *message = NULL; int message_len; zval *constructor_arg; message_len = spprintf(&message, 0, format, arg1); ALLOC_INIT_ZVAL(constructor_arg); ZVAL_STRINGL(constructor_arg, message, message_len, 1); zend_call_method_with_1_params(&this_ptr, ce, &ce->parent->constructor, "__construct", NULL, constructor_arg); efree(message); zval_ptr_dtor(&constructor_arg); } /** * Pass a single string parameter to exception constructor and throw */ static void pimple_throw_exception_string(zend_class_entry *ce, const char *message, zend_uint message_len TSRMLS_DC) { zval *exception, *param; ALLOC_INIT_ZVAL(exception); object_init_ex(exception, ce); ALLOC_INIT_ZVAL(param); ZVAL_STRINGL(param, message, message_len, 1); zend_call_method_with_1_params(&exception, ce, &ce->constructor, "__construct", NULL, param); zend_throw_exception_object(exception TSRMLS_CC); zval_ptr_dtor(¶m); } static void pimple_closure_free_object_storage(pimple_closure_object *obj TSRMLS_DC) { zend_object_std_dtor(&obj->zobj TSRMLS_CC); if (obj->factory) { zval_ptr_dtor(&obj->factory); } if (obj->callable) { zval_ptr_dtor(&obj->callable); } efree(obj); } static void pimple_free_object_storage(pimple_object *obj TSRMLS_DC) { zend_hash_destroy(&obj->factories); zend_hash_destroy(&obj->protected); zend_hash_destroy(&obj->values); zend_object_std_dtor(&obj->zobj TSRMLS_CC); efree(obj); } static void pimple_free_bucket(pimple_bucket_value *bucket) { if (bucket->raw) { zval_ptr_dtor(&bucket->raw); } } static zend_object_value pimple_closure_object_create(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; pimple_closure_object *pimple_closure_obj = NULL; pimple_closure_obj = ecalloc(1, sizeof(pimple_closure_object)); ZEND_OBJ_INIT(&pimple_closure_obj->zobj, ce); pimple_closure_object_handlers.get_constructor = pimple_closure_get_constructor; retval.handlers = &pimple_closure_object_handlers; retval.handle = zend_objects_store_put(pimple_closure_obj, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) pimple_closure_free_object_storage, NULL TSRMLS_CC); return retval; } static zend_function *pimple_closure_get_constructor(zval *obj TSRMLS_DC) { zend_error(E_ERROR, "Pimple\\ContainerClosure is an internal class and cannot be instantiated"); return NULL; } static int pimple_closure_get_closure(zval *obj, zend_class_entry **ce_ptr, union _zend_function **fptr_ptr, zval **zobj_ptr TSRMLS_DC) { *zobj_ptr = obj; *ce_ptr = Z_OBJCE_P(obj); *fptr_ptr = (zend_function *)&pimple_closure_invoker_function; return SUCCESS; } static zend_object_value pimple_object_create(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; pimple_object *pimple_obj = NULL; zend_function *function = NULL; pimple_obj = emalloc(sizeof(pimple_object)); ZEND_OBJ_INIT(&pimple_obj->zobj, ce); PIMPLE_OBJECT_HANDLE_INHERITANCE_OBJECT_HANDLERS retval.handlers = &pimple_object_handlers; retval.handle = zend_objects_store_put(pimple_obj, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) pimple_free_object_storage, NULL TSRMLS_CC); zend_hash_init(&pimple_obj->factories, PIMPLE_DEFAULT_ZVAL_CACHE_NUM, NULL, (dtor_func_t)pimple_bucket_dtor, 0); zend_hash_init(&pimple_obj->protected, PIMPLE_DEFAULT_ZVAL_CACHE_NUM, NULL, (dtor_func_t)pimple_bucket_dtor, 0); zend_hash_init(&pimple_obj->values, PIMPLE_DEFAULT_ZVAL_VALUES_NUM, NULL, (dtor_func_t)pimple_bucket_dtor, 0); return retval; } static void pimple_object_write_dimension(zval *object, zval *offset, zval *value TSRMLS_DC) { FETCH_DIM_HANDLERS_VARS pimple_bucket_value pimple_value = {0}, *found_value = NULL; ulong hash; pimple_zval_to_pimpleval(value, &pimple_value TSRMLS_CC); if (!offset) {/* $p[] = 'foo' when not overloaded */ zend_hash_next_index_insert(&pimple_obj->values, (void *)&pimple_value, sizeof(pimple_bucket_value), NULL); Z_ADDREF_P(value); return; } switch (Z_TYPE_P(offset)) { case IS_STRING: hash = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); zend_hash_quick_find(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hash, (void **)&found_value); if (found_value && found_value->type == PIMPLE_IS_SERVICE && found_value->initialized == 1) { pimple_free_bucket(&pimple_value); pimple_throw_exception_string(pimple_ce_FrozenServiceException, Z_STRVAL_P(offset), Z_STRLEN_P(offset) TSRMLS_CC); return; } if (zend_hash_quick_update(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hash, (void *)&pimple_value, sizeof(pimple_bucket_value), NULL) == FAILURE) { pimple_free_bucket(&pimple_value); return; } Z_ADDREF_P(value); break; case IS_DOUBLE: case IS_BOOL: case IS_LONG: if (Z_TYPE_P(offset) == IS_DOUBLE) { index = (ulong)Z_DVAL_P(offset); } else { index = Z_LVAL_P(offset); } zend_hash_index_find(&pimple_obj->values, index, (void **)&found_value); if (found_value && found_value->type == PIMPLE_IS_SERVICE && found_value->initialized == 1) { pimple_free_bucket(&pimple_value); convert_to_string(offset); pimple_throw_exception_string(pimple_ce_FrozenServiceException, Z_STRVAL_P(offset), Z_STRLEN_P(offset) TSRMLS_CC); return; } if (zend_hash_index_update(&pimple_obj->values, index, (void *)&pimple_value, sizeof(pimple_bucket_value), NULL) == FAILURE) { pimple_free_bucket(&pimple_value); return; } Z_ADDREF_P(value); break; case IS_NULL: /* $p[] = 'foo' when overloaded */ zend_hash_next_index_insert(&pimple_obj->values, (void *)&pimple_value, sizeof(pimple_bucket_value), NULL); Z_ADDREF_P(value); break; default: pimple_free_bucket(&pimple_value); zend_error(E_WARNING, "Unsupported offset type"); } } static void pimple_object_unset_dimension(zval *object, zval *offset TSRMLS_DC) { FETCH_DIM_HANDLERS_VARS switch (Z_TYPE_P(offset)) { case IS_STRING: zend_symtable_del(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); zend_symtable_del(&pimple_obj->factories, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); zend_symtable_del(&pimple_obj->protected, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); break; case IS_DOUBLE: case IS_BOOL: case IS_LONG: if (Z_TYPE_P(offset) == IS_DOUBLE) { index = (ulong)Z_DVAL_P(offset); } else { index = Z_LVAL_P(offset); } zend_hash_index_del(&pimple_obj->values, index); zend_hash_index_del(&pimple_obj->factories, index); zend_hash_index_del(&pimple_obj->protected, index); break; default: zend_error(E_WARNING, "Unsupported offset type"); } } static int pimple_object_has_dimension(zval *object, zval *offset, int check_empty TSRMLS_DC) { FETCH_DIM_HANDLERS_VARS pimple_bucket_value *retval = NULL; switch (Z_TYPE_P(offset)) { case IS_STRING: if (zend_symtable_find(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void **)&retval) == SUCCESS) { switch (check_empty) { case 0: /* isset */ return 1; /* Differs from PHP behavior (Z_TYPE_P(retval->value) != IS_NULL;) */ case 1: /* empty */ default: return zend_is_true(retval->value); } } return 0; break; case IS_DOUBLE: case IS_BOOL: case IS_LONG: if (Z_TYPE_P(offset) == IS_DOUBLE) { index = (ulong)Z_DVAL_P(offset); } else { index = Z_LVAL_P(offset); } if (zend_hash_index_find(&pimple_obj->values, index, (void **)&retval) == SUCCESS) { switch (check_empty) { case 0: /* isset */ return 1; /* Differs from PHP behavior (Z_TYPE_P(retval->value) != IS_NULL;)*/ case 1: /* empty */ default: return zend_is_true(retval->value); } } return 0; break; default: zend_error(E_WARNING, "Unsupported offset type"); return 0; } } static zval *pimple_object_read_dimension(zval *object, zval *offset, int type TSRMLS_DC) { FETCH_DIM_HANDLERS_VARS pimple_bucket_value *retval = NULL; zend_fcall_info fci = {0}; zval *retval_ptr_ptr = NULL; switch (Z_TYPE_P(offset)) { case IS_STRING: if (zend_symtable_find(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void **)&retval) == FAILURE) { pimple_throw_exception_string(pimple_ce_UnknownIdentifierException, Z_STRVAL_P(offset), Z_STRLEN_P(offset) TSRMLS_CC); return EG(uninitialized_zval_ptr); } break; case IS_DOUBLE: case IS_BOOL: case IS_LONG: if (Z_TYPE_P(offset) == IS_DOUBLE) { index = (ulong)Z_DVAL_P(offset); } else { index = Z_LVAL_P(offset); } if (zend_hash_index_find(&pimple_obj->values, index, (void **)&retval) == FAILURE) { return EG(uninitialized_zval_ptr); } break; case IS_NULL: /* $p[][3] = 'foo' first dim access */ return EG(uninitialized_zval_ptr); break; default: zend_error(E_WARNING, "Unsupported offset type"); return EG(uninitialized_zval_ptr); } if(retval->type == PIMPLE_IS_PARAM) { return retval->value; } if (zend_hash_index_exists(&pimple_obj->protected, retval->handle_num)) { /* Service is protected, return the value every time */ return retval->value; } if (zend_hash_index_exists(&pimple_obj->factories, retval->handle_num)) { /* Service is a factory, call it every time and never cache its result */ PIMPLE_CALL_CB Z_DELREF_P(retval_ptr_ptr); /* fetch dim addr will increment refcount */ return retval_ptr_ptr; } if (retval->initialized == 1) { /* Service has already been called, return its cached value */ return retval->value; } ALLOC_INIT_ZVAL(retval->raw); MAKE_COPY_ZVAL(&retval->value, retval->raw); PIMPLE_CALL_CB retval->initialized = 1; zval_ptr_dtor(&retval->value); retval->value = retval_ptr_ptr; return retval->value; } static int pimple_zval_is_valid_callback(zval *_zval, pimple_bucket_value *_pimple_bucket_value TSRMLS_DC) { if (Z_TYPE_P(_zval) != IS_OBJECT) { return FAILURE; } if (_pimple_bucket_value->fcc.called_scope) { return SUCCESS; } if (Z_OBJ_HANDLER_P(_zval, get_closure) && Z_OBJ_HANDLER_P(_zval, get_closure)(_zval, &_pimple_bucket_value->fcc.calling_scope, &_pimple_bucket_value->fcc.function_handler, &_pimple_bucket_value->fcc.object_ptr TSRMLS_CC) == SUCCESS) { _pimple_bucket_value->fcc.called_scope = _pimple_bucket_value->fcc.calling_scope; return SUCCESS; } else { return FAILURE; } } static int pimple_zval_to_pimpleval(zval *_zval, pimple_bucket_value *_pimple_bucket_value TSRMLS_DC) { _pimple_bucket_value->value = _zval; if (Z_TYPE_P(_zval) != IS_OBJECT) { return PIMPLE_IS_PARAM; } if (pimple_zval_is_valid_callback(_zval, _pimple_bucket_value TSRMLS_CC) == SUCCESS) { _pimple_bucket_value->type = PIMPLE_IS_SERVICE; _pimple_bucket_value->handle_num = Z_OBJ_HANDLE_P(_zval); } return PIMPLE_IS_SERVICE; } static void pimple_bucket_dtor(pimple_bucket_value *bucket) { zval_ptr_dtor(&bucket->value); pimple_free_bucket(bucket); } PHP_METHOD(FrozenServiceException, __construct) { char *id = NULL; int id_len; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &id, &id_len) == FAILURE) { return; } pimple_exception_call_parent_constructor(getThis(), "Cannot override frozen service \"%s\".", id TSRMLS_CC); } PHP_METHOD(InvalidServiceIdentifierException, __construct) { char *id = NULL; int id_len; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &id, &id_len) == FAILURE) { return; } pimple_exception_call_parent_constructor(getThis(), "Identifier \"%s\" does not contain an object definition.", id TSRMLS_CC); } PHP_METHOD(UnknownIdentifierException, __construct) { char *id = NULL; int id_len; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &id, &id_len) == FAILURE) { return; } pimple_exception_call_parent_constructor(getThis(), "Identifier \"%s\" is not defined.", id TSRMLS_CC); } PHP_METHOD(Pimple, protect) { zval *protected = NULL; pimple_object *pobj = NULL; pimple_bucket_value bucket = {0}; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &protected) == FAILURE) { return; } if (pimple_zval_is_valid_callback(protected, &bucket TSRMLS_CC) == FAILURE) { pimple_free_bucket(&bucket); zend_throw_exception(pimple_ce_ExpectedInvokableException, "Callable is not a Closure or invokable object.", 0 TSRMLS_CC); return; } pimple_zval_to_pimpleval(protected, &bucket TSRMLS_CC); pobj = (pimple_object *)zend_object_store_get_object(getThis() TSRMLS_CC); if (zend_hash_index_update(&pobj->protected, bucket.handle_num, (void *)&bucket, sizeof(pimple_bucket_value), NULL) == SUCCESS) { Z_ADDREF_P(protected); RETURN_ZVAL(protected, 1 , 0); } else { pimple_free_bucket(&bucket); } RETURN_FALSE; } PHP_METHOD(Pimple, raw) { zval *offset = NULL; pimple_object *pobj = NULL; pimple_bucket_value *value = NULL; ulong index; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &offset) == FAILURE) { return; } pobj = zend_object_store_get_object(getThis() TSRMLS_CC); switch (Z_TYPE_P(offset)) { case IS_STRING: if (zend_symtable_find(&pobj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void *)&value) == FAILURE) { pimple_throw_exception_string(pimple_ce_UnknownIdentifierException, Z_STRVAL_P(offset), Z_STRLEN_P(offset) TSRMLS_CC); RETURN_NULL(); } break; case IS_DOUBLE: case IS_BOOL: case IS_LONG: if (Z_TYPE_P(offset) == IS_DOUBLE) { index = (ulong)Z_DVAL_P(offset); } else { index = Z_LVAL_P(offset); } if (zend_hash_index_find(&pobj->values, index, (void *)&value) == FAILURE) { RETURN_NULL(); } break; case IS_NULL: default: zend_error(E_WARNING, "Unsupported offset type"); } if (value->raw) { RETVAL_ZVAL(value->raw, 1, 0); } else { RETVAL_ZVAL(value->value, 1, 0); } } PHP_METHOD(Pimple, extend) { zval *offset = NULL, *callable = NULL, *pimple_closure_obj = NULL; pimple_bucket_value bucket = {0}, *value = NULL; pimple_object *pobj = NULL; pimple_closure_object *pcobj = NULL; ulong index; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &offset, &callable) == FAILURE) { return; } pobj = zend_object_store_get_object(getThis() TSRMLS_CC); switch (Z_TYPE_P(offset)) { case IS_STRING: if (zend_symtable_find(&pobj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void *)&value) == FAILURE) { pimple_throw_exception_string(pimple_ce_UnknownIdentifierException, Z_STRVAL_P(offset), Z_STRLEN_P(offset) TSRMLS_CC); RETURN_NULL(); } if (value->type != PIMPLE_IS_SERVICE) { pimple_throw_exception_string(pimple_ce_InvalidServiceIdentifierException, Z_STRVAL_P(offset), Z_STRLEN_P(offset) TSRMLS_CC); RETURN_NULL(); } if (zend_hash_index_exists(&pobj->protected, value->handle_num)) { int er = EG(error_reporting); EG(error_reporting) = 0; php_error(E_DEPRECATED, "How Pimple behaves when extending protected closures will be fixed in Pimple 4. Are you sure \"%s\" should be protected?", Z_STRVAL_P(offset)); EG(error_reporting) = er; } break; case IS_DOUBLE: case IS_BOOL: case IS_LONG: if (Z_TYPE_P(offset) == IS_DOUBLE) { index = (ulong)Z_DVAL_P(offset); } else { index = Z_LVAL_P(offset); } if (zend_hash_index_find(&pobj->values, index, (void *)&value) == FAILURE) { convert_to_string(offset); pimple_throw_exception_string(pimple_ce_UnknownIdentifierException, Z_STRVAL_P(offset), Z_STRLEN_P(offset) TSRMLS_CC); RETURN_NULL(); } if (value->type != PIMPLE_IS_SERVICE) { convert_to_string(offset); pimple_throw_exception_string(pimple_ce_InvalidServiceIdentifierException, Z_STRVAL_P(offset), Z_STRLEN_P(offset) TSRMLS_CC); RETURN_NULL(); } if (zend_hash_index_exists(&pobj->protected, value->handle_num)) { int er = EG(error_reporting); EG(error_reporting) = 0; php_error(E_DEPRECATED, "How Pimple behaves when extending protected closures will be fixed in Pimple 4. Are you sure \"%ld\" should be protected?", index); EG(error_reporting) = er; } break; case IS_NULL: default: zend_error(E_WARNING, "Unsupported offset type"); } if (pimple_zval_is_valid_callback(callable, &bucket TSRMLS_CC) == FAILURE) { pimple_free_bucket(&bucket); zend_throw_exception(pimple_ce_ExpectedInvokableException, "Extension service definition is not a Closure or invokable object.", 0 TSRMLS_CC); RETURN_NULL(); } pimple_free_bucket(&bucket); ALLOC_INIT_ZVAL(pimple_closure_obj); object_init_ex(pimple_closure_obj, pimple_closure_ce); pcobj = zend_object_store_get_object(pimple_closure_obj TSRMLS_CC); pcobj->callable = callable; pcobj->factory = value->value; Z_ADDREF_P(callable); Z_ADDREF_P(value->value); if (zend_hash_index_exists(&pobj->factories, value->handle_num)) { pimple_zval_to_pimpleval(pimple_closure_obj, &bucket TSRMLS_CC); zend_hash_index_del(&pobj->factories, value->handle_num); zend_hash_index_update(&pobj->factories, bucket.handle_num, (void *)&bucket, sizeof(pimple_bucket_value), NULL); Z_ADDREF_P(pimple_closure_obj); } pimple_object_write_dimension(getThis(), offset, pimple_closure_obj TSRMLS_CC); RETVAL_ZVAL(pimple_closure_obj, 1, 1); } PHP_METHOD(Pimple, keys) { HashPosition pos; pimple_object *pobj = NULL; zval **value = NULL; zval *endval = NULL; char *str_index = NULL; int str_len; ulong num_index; if (zend_parse_parameters_none() == FAILURE) { return; } pobj = zend_object_store_get_object(getThis() TSRMLS_CC); array_init_size(return_value, zend_hash_num_elements(&pobj->values)); zend_hash_internal_pointer_reset_ex(&pobj->values, &pos); while(zend_hash_get_current_data_ex(&pobj->values, (void **)&value, &pos) == SUCCESS) { MAKE_STD_ZVAL(endval); switch (zend_hash_get_current_key_ex(&pobj->values, &str_index, (uint *)&str_len, &num_index, 0, &pos)) { case HASH_KEY_IS_STRING: ZVAL_STRINGL(endval, str_index, str_len - 1, 1); zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &endval, sizeof(zval *), NULL); break; case HASH_KEY_IS_LONG: ZVAL_LONG(endval, num_index); zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &endval, sizeof(zval *), NULL); break; } zend_hash_move_forward_ex(&pobj->values, &pos); } } PHP_METHOD(Pimple, factory) { zval *factory = NULL; pimple_object *pobj = NULL; pimple_bucket_value bucket = {0}; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &factory) == FAILURE) { return; } if (pimple_zval_is_valid_callback(factory, &bucket TSRMLS_CC) == FAILURE) { pimple_free_bucket(&bucket); zend_throw_exception(pimple_ce_ExpectedInvokableException, "Service definition is not a Closure or invokable object.", 0 TSRMLS_CC); return; } pimple_zval_to_pimpleval(factory, &bucket TSRMLS_CC); pobj = (pimple_object *)zend_object_store_get_object(getThis() TSRMLS_CC); if (zend_hash_index_update(&pobj->factories, bucket.handle_num, (void *)&bucket, sizeof(pimple_bucket_value), NULL) == SUCCESS) { Z_ADDREF_P(factory); RETURN_ZVAL(factory, 1 , 0); } else { pimple_free_bucket(&bucket); } RETURN_FALSE; } PHP_METHOD(Pimple, offsetSet) { zval *offset = NULL, *value = NULL; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &offset, &value) == FAILURE) { return; } pimple_object_write_dimension(getThis(), offset, value TSRMLS_CC); } PHP_METHOD(Pimple, offsetGet) { zval *offset = NULL, *retval = NULL; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &offset) == FAILURE) { return; } retval = pimple_object_read_dimension(getThis(), offset, 0 TSRMLS_CC); RETVAL_ZVAL(retval, 1, 0); } PHP_METHOD(Pimple, offsetUnset) { zval *offset = NULL; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &offset) == FAILURE) { return; } pimple_object_unset_dimension(getThis(), offset TSRMLS_CC); } PHP_METHOD(Pimple, offsetExists) { zval *offset = NULL; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &offset) == FAILURE) { return; } RETVAL_BOOL(pimple_object_has_dimension(getThis(), offset, 1 TSRMLS_CC)); } PHP_METHOD(Pimple, register) { zval *provider; zval **data; zval *retval = NULL; zval key; HashTable *array = NULL; HashPosition pos; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|h", &provider, pimple_serviceprovider_ce, &array) == FAILURE) { return; } RETVAL_ZVAL(getThis(), 1, 0); zend_call_method_with_1_params(&provider, Z_OBJCE_P(provider), NULL, "register", &retval, getThis()); if (retval) { zval_ptr_dtor(&retval); } if (!array) { return; } zend_hash_internal_pointer_reset_ex(array, &pos); while(zend_hash_get_current_data_ex(array, (void **)&data, &pos) == SUCCESS) { zend_hash_get_current_key_zval_ex(array, &key, &pos); pimple_object_write_dimension(getThis(), &key, *data TSRMLS_CC); zend_hash_move_forward_ex(array, &pos); } } PHP_METHOD(Pimple, __construct) { zval *values = NULL, **pData = NULL, offset; HashPosition pos; char *str_index = NULL; zend_uint str_length; ulong num_index; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!", &values) == FAILURE) { return; } PIMPLE_DEPRECATE if (!values) { return; } zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(values), &pos); while (zend_hash_has_more_elements_ex(Z_ARRVAL_P(values), &pos) == SUCCESS) { zend_hash_get_current_data_ex(Z_ARRVAL_P(values), (void **)&pData, &pos); zend_hash_get_current_key_ex(Z_ARRVAL_P(values), &str_index, &str_length, &num_index, 0, &pos); INIT_ZVAL(offset); if (zend_hash_get_current_key_type_ex(Z_ARRVAL_P(values), &pos) == HASH_KEY_IS_LONG) { ZVAL_LONG(&offset, num_index); } else { ZVAL_STRINGL(&offset, str_index, (str_length - 1), 0); } pimple_object_write_dimension(getThis(), &offset, *pData TSRMLS_CC); zend_hash_move_forward_ex(Z_ARRVAL_P(values), &pos); } } /* * This is PHP code snippet handling extend()s calls : $extended = function ($c) use ($callable, $factory) { return $callable($factory($c), $c); }; */ PHP_METHOD(PimpleClosure, invoker) { pimple_closure_object *pcobj = NULL; zval *arg = NULL, *retval = NULL, *newretval = NULL; zend_fcall_info fci = {0}; zval **args[2]; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &arg) == FAILURE) { return; } pcobj = zend_object_store_get_object(getThis() TSRMLS_CC); fci.function_name = pcobj->factory; args[0] = &arg; zend_fcall_info_argp(&fci TSRMLS_CC, 1, args); fci.retval_ptr_ptr = &retval; fci.size = sizeof(fci); if (zend_call_function(&fci, NULL TSRMLS_CC) == FAILURE || EG(exception)) { efree(fci.params); return; /* Should here return default zval */ } efree(fci.params); memset(&fci, 0, sizeof(fci)); fci.size = sizeof(fci); fci.function_name = pcobj->callable; args[0] = &retval; args[1] = &arg; zend_fcall_info_argp(&fci TSRMLS_CC, 2, args); fci.retval_ptr_ptr = &newretval; if (zend_call_function(&fci, NULL TSRMLS_CC) == FAILURE || EG(exception)) { efree(fci.params); zval_ptr_dtor(&retval); return; } efree(fci.params); zval_ptr_dtor(&retval); RETVAL_ZVAL(newretval, 1 ,1); } PHP_MINIT_FUNCTION(pimple) { zend_class_entry tmp_ce_PsrContainerInterface, tmp_ce_PsrContainerExceptionInterface, tmp_ce_PsrNotFoundExceptionInterface; zend_class_entry tmp_ce_ExpectedInvokableException, tmp_ce_FrozenServiceException, tmp_ce_InvalidServiceIdentifierException, tmp_ce_UnknownIdentifierException; zend_class_entry tmp_pimple_ce, tmp_pimple_closure_ce, tmp_pimple_serviceprovider_iface_ce; /* Psr\Container namespace */ INIT_NS_CLASS_ENTRY(tmp_ce_PsrContainerInterface, PSR_CONTAINER_NS, "ContainerInterface", pimple_ce_PsrContainerInterface_functions); INIT_NS_CLASS_ENTRY(tmp_ce_PsrContainerExceptionInterface, PSR_CONTAINER_NS, "ContainerExceptionInterface", pimple_ce_PsrContainerExceptionInterface_functions); INIT_NS_CLASS_ENTRY(tmp_ce_PsrNotFoundExceptionInterface, PSR_CONTAINER_NS, "NotFoundExceptionInterface", pimple_ce_PsrNotFoundExceptionInterface_functions); pimple_ce_PsrContainerInterface = zend_register_internal_interface(&tmp_ce_PsrContainerInterface TSRMLS_CC); pimple_ce_PsrContainerExceptionInterface = zend_register_internal_interface(&tmp_ce_PsrContainerExceptionInterface TSRMLS_CC); pimple_ce_PsrNotFoundExceptionInterface = zend_register_internal_interface(&tmp_ce_PsrNotFoundExceptionInterface TSRMLS_CC); zend_class_implements(pimple_ce_PsrNotFoundExceptionInterface TSRMLS_CC, 1, pimple_ce_PsrContainerExceptionInterface); /* Pimple\Exception namespace */ INIT_NS_CLASS_ENTRY(tmp_ce_ExpectedInvokableException, PIMPLE_EXCEPTION_NS, "ExpectedInvokableException", NULL); INIT_NS_CLASS_ENTRY(tmp_ce_FrozenServiceException, PIMPLE_EXCEPTION_NS, "FrozenServiceException", pimple_ce_FrozenServiceException_functions); INIT_NS_CLASS_ENTRY(tmp_ce_InvalidServiceIdentifierException, PIMPLE_EXCEPTION_NS, "InvalidServiceIdentifierException", pimple_ce_InvalidServiceIdentifierException_functions); INIT_NS_CLASS_ENTRY(tmp_ce_UnknownIdentifierException, PIMPLE_EXCEPTION_NS, "UnknownIdentifierException", pimple_ce_UnknownIdentifierException_functions); pimple_ce_ExpectedInvokableException = zend_register_internal_class_ex(&tmp_ce_ExpectedInvokableException, spl_ce_InvalidArgumentException, NULL TSRMLS_CC); pimple_ce_FrozenServiceException = zend_register_internal_class_ex(&tmp_ce_FrozenServiceException, spl_ce_RuntimeException, NULL TSRMLS_CC); pimple_ce_InvalidServiceIdentifierException = zend_register_internal_class_ex(&tmp_ce_InvalidServiceIdentifierException, spl_ce_InvalidArgumentException, NULL TSRMLS_CC); pimple_ce_UnknownIdentifierException = zend_register_internal_class_ex(&tmp_ce_UnknownIdentifierException, spl_ce_InvalidArgumentException, NULL TSRMLS_CC); zend_class_implements(pimple_ce_ExpectedInvokableException TSRMLS_CC, 1, pimple_ce_PsrContainerExceptionInterface); zend_class_implements(pimple_ce_FrozenServiceException TSRMLS_CC, 1, pimple_ce_PsrContainerExceptionInterface); zend_class_implements(pimple_ce_InvalidServiceIdentifierException TSRMLS_CC, 1, pimple_ce_PsrContainerExceptionInterface); zend_class_implements(pimple_ce_UnknownIdentifierException TSRMLS_CC, 1, pimple_ce_PsrNotFoundExceptionInterface); /* Pimple namespace */ INIT_NS_CLASS_ENTRY(tmp_pimple_ce, PIMPLE_NS, "Container", pimple_ce_functions); INIT_NS_CLASS_ENTRY(tmp_pimple_closure_ce, PIMPLE_NS, "ContainerClosure", NULL); INIT_NS_CLASS_ENTRY(tmp_pimple_serviceprovider_iface_ce, PIMPLE_NS, "ServiceProviderInterface", pimple_serviceprovider_iface_ce_functions); tmp_pimple_ce.create_object = pimple_object_create; tmp_pimple_closure_ce.create_object = pimple_closure_object_create; pimple_ce = zend_register_internal_class(&tmp_pimple_ce TSRMLS_CC); zend_class_implements(pimple_ce TSRMLS_CC, 1, zend_ce_arrayaccess); pimple_closure_ce = zend_register_internal_class(&tmp_pimple_closure_ce TSRMLS_CC); pimple_closure_ce->ce_flags |= ZEND_ACC_FINAL_CLASS; pimple_serviceprovider_ce = zend_register_internal_interface(&tmp_pimple_serviceprovider_iface_ce TSRMLS_CC); memcpy(&pimple_closure_object_handlers, zend_get_std_object_handlers(), sizeof(*zend_get_std_object_handlers())); pimple_object_handlers = std_object_handlers; pimple_closure_object_handlers.get_closure = pimple_closure_get_closure; pimple_closure_invoker_function.function_name = "Pimple closure internal invoker"; pimple_closure_invoker_function.fn_flags |= ZEND_ACC_CLOSURE; pimple_closure_invoker_function.handler = ZEND_MN(PimpleClosure_invoker); pimple_closure_invoker_function.num_args = 1; pimple_closure_invoker_function.required_num_args = 1; pimple_closure_invoker_function.scope = pimple_closure_ce; pimple_closure_invoker_function.type = ZEND_INTERNAL_FUNCTION; pimple_closure_invoker_function.module = &pimple_module_entry; return SUCCESS; } PHP_MINFO_FUNCTION(pimple) { php_info_print_table_start(); php_info_print_table_header(2, "SensioLabs Pimple C support", "enabled"); php_info_print_table_row(2, "Pimple supported version", PIMPLE_VERSION); php_info_print_table_end(); php_info_print_box_start(0); php_write((void *)ZEND_STRL("SensioLabs Pimple C support developed by Julien Pauli") TSRMLS_CC); if (!sapi_module.phpinfo_as_text) { php_write((void *)ZEND_STRL(sensiolabs_logo) TSRMLS_CC); } php_info_print_box_end(); } zend_module_entry pimple_module_entry = { STANDARD_MODULE_HEADER, "pimple", NULL, PHP_MINIT(pimple), NULL, NULL, NULL, PHP_MINFO(pimple), PIMPLE_VERSION, STANDARD_MODULE_PROPERTIES }; #ifdef COMPILE_DL_PIMPLE ZEND_GET_MODULE(pimple) #endif ext/pimple/README.md 0000666 00000000246 15165571133 0010126 0 ustar 00 This is Pimple 2 implemented in C * PHP >= 5.3 * Not tested under Windows, might work Install ======= > phpize > ./configure > make > make install ext/pimple/config.m4 0000666 00000003751 15165571133 0010362 0 ustar 00 dnl $Id$ dnl config.m4 for extension pimple dnl Comments in this file start with the string 'dnl'. dnl Remove where necessary. This file will not work dnl without editing. dnl If your extension references something external, use with: dnl PHP_ARG_WITH(pimple, for pimple support, dnl Make sure that the comment is aligned: dnl [ --with-pimple Include pimple support]) dnl Otherwise use enable: PHP_ARG_ENABLE(pimple, whether to enable pimple support, dnl Make sure that the comment is aligned: [ --enable-pimple Enable pimple support]) if test "$PHP_PIMPLE" != "no"; then dnl Write more examples of tests here... dnl # --with-pimple -> check with-path dnl SEARCH_PATH="/usr/local /usr" # you might want to change this dnl SEARCH_FOR="/include/pimple.h" # you most likely want to change this dnl if test -r $PHP_PIMPLE/$SEARCH_FOR; then # path given as parameter dnl PIMPLE_DIR=$PHP_PIMPLE dnl else # search default path list dnl AC_MSG_CHECKING([for pimple files in default path]) dnl for i in $SEARCH_PATH ; do dnl if test -r $i/$SEARCH_FOR; then dnl PIMPLE_DIR=$i dnl AC_MSG_RESULT(found in $i) dnl fi dnl done dnl fi dnl dnl if test -z "$PIMPLE_DIR"; then dnl AC_MSG_RESULT([not found]) dnl AC_MSG_ERROR([Please reinstall the pimple distribution]) dnl fi dnl # --with-pimple -> add include path dnl PHP_ADD_INCLUDE($PIMPLE_DIR/include) dnl # --with-pimple -> check for lib and symbol presence dnl LIBNAME=pimple # you may want to change this dnl LIBSYMBOL=pimple # you most likely want to change this dnl PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL, dnl [ dnl PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $PIMPLE_DIR/lib, PIMPLE_SHARED_LIBADD) dnl AC_DEFINE(HAVE_PIMPLELIB,1,[ ]) dnl ],[ dnl AC_MSG_ERROR([wrong pimple lib version or lib not found]) dnl ],[ dnl -L$PIMPLE_DIR/lib -lm dnl ]) dnl dnl PHP_SUBST(PIMPLE_SHARED_LIBADD) PHP_NEW_EXTENSION(pimple, pimple.c, $ext_shared) fi ext/pimple/.gitignore 0000666 00000000477 15165571133 0010645 0 ustar 00 *.sw* .deps Makefile Makefile.fragments Makefile.global Makefile.objects acinclude.m4 aclocal.m4 build/ config.cache config.guess config.h config.h.in config.log config.nice config.status config.sub configure configure.in install-sh libtool ltmain.sh missing mkinstalldirs run-tests.php *.loT .libs/ modules/ *.la *.lo ext/pimple/pimple_compat.h 0000666 00000005547 15165571133 0011662 0 ustar 00 /* * This file is part of Pimple. * * Copyright (c) 2014 Fabien Potencier * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is furnished * to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef PIMPLE_COMPAT_H_ #define PIMPLE_COMPAT_H_ #include "Zend/zend_extensions.h" /* for ZEND_EXTENSION_API_NO */ #define PHP_5_0_X_API_NO 220040412 #define PHP_5_1_X_API_NO 220051025 #define PHP_5_2_X_API_NO 220060519 #define PHP_5_3_X_API_NO 220090626 #define PHP_5_4_X_API_NO 220100525 #define PHP_5_5_X_API_NO 220121212 #define PHP_5_6_X_API_NO 220131226 #define IS_PHP_56 ZEND_EXTENSION_API_NO == PHP_5_6_X_API_NO #define IS_AT_LEAST_PHP_56 ZEND_EXTENSION_API_NO >= PHP_5_6_X_API_NO #define IS_PHP_55 ZEND_EXTENSION_API_NO == PHP_5_5_X_API_NO #define IS_AT_LEAST_PHP_55 ZEND_EXTENSION_API_NO >= PHP_5_5_X_API_NO #define IS_PHP_54 ZEND_EXTENSION_API_NO == PHP_5_4_X_API_NO #define IS_AT_LEAST_PHP_54 ZEND_EXTENSION_API_NO >= PHP_5_4_X_API_NO #define IS_PHP_53 ZEND_EXTENSION_API_NO == PHP_5_3_X_API_NO #define IS_AT_LEAST_PHP_53 ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO #if IS_PHP_53 #define object_properties_init(obj, ce) do { \ zend_hash_copy(obj->properties, &ce->default_properties, zval_copy_property_ctor(ce), NULL, sizeof(zval *)); \ } while (0); #endif #define ZEND_OBJ_INIT(obj, ce) do { \ zend_object_std_init(obj, ce TSRMLS_CC); \ object_properties_init((obj), (ce)); \ } while(0); #if IS_PHP_53 || IS_PHP_54 static void zend_hash_get_current_key_zval_ex(const HashTable *ht, zval *key, HashPosition *pos) { Bucket *p; p = pos ? (*pos) : ht->pInternalPointer; if (!p) { Z_TYPE_P(key) = IS_NULL; } else if (p->nKeyLength) { Z_TYPE_P(key) = IS_STRING; Z_STRVAL_P(key) = estrndup(p->arKey, p->nKeyLength - 1); Z_STRLEN_P(key) = p->nKeyLength - 1; } else { Z_TYPE_P(key) = IS_LONG; Z_LVAL_P(key) = p->h; } } #endif #endif /* PIMPLE_COMPAT_H_ */ ext/pimple/tests/017_1.phpt 0000666 00000000601 15165571133 0011430 0 ustar 00 --TEST-- Test extend() with exception in service factory --SKIPIF-- <?php if (!extension_loaded("pimple")) print "skip"; ?> --FILE-- <?php $p = new Pimple\Container(); $p[12] = function ($v) { throw new BadMethodCallException; }; $c = $p->extend(12, function ($w) { return 'foobar'; }); try { $p[12]; echo "Exception expected"; } catch (BadMethodCallException $e) { } --EXPECTF-- ext/pimple/tests/016.phpt 0000666 00000001101 15165571133 0011203 0 ustar 00 --TEST-- Test extend() --SKIPIF-- <?php if (!extension_loaded("pimple")) print "skip"; ?> --FILE-- <?php /* This is part of Pimple::extend() code : $extended = function ($c) use ($callable, $factory) { return $callable($factory($c), $c); }; */ $p = new Pimple\Container(); $p[12] = function ($v) { var_dump($v); return 'foo';}; /* $factory in code above */ $c = $p->extend(12, function ($w) { var_dump($w); return 'bar'; }); /* $callable in code above */ var_dump($c('param')); --EXPECTF-- string(5) "param" string(3) "foo" string(3) "bar"