/* {{{ */ zend_bool uopz_extend(zend_class_entry *clazz, zend_class_entry *parent) { zend_bool is_final = clazz->ce_flags & ZEND_ACC_FINAL; clazz->ce_flags &= ~ZEND_ACC_FINAL; if ((clazz->ce_flags & ZEND_ACC_INTERFACE) && !(parent->ce_flags & ZEND_ACC_INTERFACE)) { uopz_exception( "the class provided (%s) cannot extend %s, because %s is not an interface", ZSTR_VAL(clazz->name), ZSTR_VAL(parent->name), ZSTR_VAL(parent->name)); return 0; } if (instanceof_function(clazz, parent)) { uopz_exception( "the class provided (%s) already extends %s", ZSTR_VAL(clazz->name), ZSTR_VAL(parent->name)); return 0; } if (parent->ce_flags & ZEND_ACC_TRAIT) { zend_do_implement_trait(clazz, parent); } else zend_do_inheritance(clazz, parent); if (parent->ce_flags & ZEND_ACC_TRAIT) zend_do_bind_traits(clazz); if (is_final) clazz->ce_flags |= ZEND_ACC_FINAL; return instanceof_function(clazz, parent); } /* }}} */
/* {{{ install_class */ static int install_class(apc_class_t cl, apc_context_t* ctxt, int lazy TSRMLS_DC) { zend_class_entry* class_entry = cl.class_entry; zend_class_entry* parent = NULL; int status; /* Special case for mangled names. Mangled names are unique to a file. * There is no way two classes with the same mangled name will occur, * unless a file is included twice. And if in case, a file is included * twice, all mangled name conflicts can be ignored and the class redeclaration * error may be deferred till runtime of the corresponding DECLARE_CLASS * calls. */ if(cl.name_len != 0 && cl.name[0] == '\0') { if(zend_hash_exists(CG(class_table), cl.name, cl.name_len+1)) { return SUCCESS; } } if(lazy && cl.name_len != 0 && cl.name[0] != '\0') { status = zend_hash_add(APCG(lazy_class_table), cl.name, cl.name_len+1, &cl, sizeof(apc_class_t), NULL); if(status == FAILURE) { zend_error(E_ERROR, "Cannot redeclare class %s", cl.name); } return status; } class_entry = apc_copy_class_entry_for_execution(cl.class_entry, ctxt TSRMLS_CC); if (class_entry == NULL) return FAILURE; /* restore parent class pointer for compile-time inheritance */ if (cl.parent_name != NULL) { zend_class_entry** parent_ptr = NULL; /* * __autoload brings in the old issues with mixed inheritance. * When a statically inherited class triggers autoload, it runs * afoul of a potential require_once "parent.php" in the previous * line, which when executed provides the parent class, but right * now goes and hits __autoload which could fail. * * missing parent == re-compile. * * whether __autoload is enabled or not, because __autoload errors * cause php to die. * * Aside: Do NOT pass *strlen(cl.parent_name)+1* because * zend_lookup_class_ex does it internally anyway! */ status = zend_lookup_class_ex(cl.parent_name, strlen(cl.parent_name), #ifdef ZEND_ENGINE_2_4 NULL, #endif 0, &parent_ptr TSRMLS_CC); if (status == FAILURE) { if(APCG(report_autofilter)) { apc_warning("Dynamic inheritance detected for class %s" TSRMLS_CC, cl.name); } class_entry->parent = NULL; return status; } else { parent = *parent_ptr; class_entry->parent = parent; zend_do_inheritance(class_entry, parent TSRMLS_CC); } } status = zend_hash_add(EG(class_table), cl.name, cl.name_len+1, &class_entry, sizeof(zend_class_entry*), NULL); if (status == FAILURE) { apc_error("Cannot redeclare class %s" TSRMLS_CC, cl.name); } return status; }