/** * Checks whether obj is an object and updates property with another zval */ int zephir_update_property_zval(zval *object, const char *property_name, unsigned int property_length, zval *value) { zend_class_entry *ce, *old_scope; zval property; old_scope = EG(scope); if (Z_TYPE_P(object) != IS_OBJECT) { php_error_docref(NULL, E_WARNING, "Attempt to assign property of non-object"); return FAILURE; } ce = Z_OBJCE_P(object); if (ce->parent) { ce = zephir_lookup_class_ce(ce, property_name, property_length); } EG(scope) = ce; if (!Z_OBJ_HT_P(object)->write_property) { const char *class_name; class_name = Z_OBJ_P(object) ? ZSTR_VAL(Z_OBJCE_P(object)->name) : ""; zend_error(E_CORE_ERROR, "Property %s of class %s cannot be updated", property_name, class_name); } ZVAL_STRINGL(&property, property_name, property_length); /* write_property will add 1 to refcount, so no Z_TRY_ADDREF_P(value); is necessary */ Z_OBJ_HT_P(object)->write_property(object, &property, value, 0); zval_ptr_dtor(&property); EG(scope) = old_scope; return SUCCESS; }
/** * Reads a property from an object */ int zephir_read_property(zval *result, zval *object, const char *property_name, zend_uint property_length, int flags) { zval property; zend_class_entry *ce, *old_scope; zval tmp; zval *res; ZVAL_UNDEF(&tmp); if (Z_TYPE_P(object) != IS_OBJECT) { if ((flags & PH_NOISY) == PH_NOISY) { php_error_docref(NULL, E_NOTICE, "Trying to get property \"%s\" of non-object", property_name); } ZVAL_NULL(result); return FAILURE; } ce = Z_OBJCE_P(object); if (ce->parent) { ce = zephir_lookup_class_ce(ce, property_name, property_length); } #if PHP_VERSION_ID >= 70100 old_scope = EG(fake_scope); EG(fake_scope) = ce; #else old_scope = EG(scope); EG(scope) = ce; #endif if (!Z_OBJ_HT_P(object)->read_property) { const char *class_name; class_name = Z_OBJ_P(object) ? ZSTR_VAL(Z_OBJCE_P(object)->name) : ""; zend_error(E_CORE_ERROR, "Property %s of class %s cannot be read", property_name, class_name); } ZVAL_STRINGL(&property, property_name, property_length); res = Z_OBJ_HT_P(object)->read_property(object, &property, flags ? BP_VAR_IS : BP_VAR_R, NULL, &tmp); if ((flags & PH_READONLY) == PH_READONLY) { ZVAL_COPY_VALUE(result, res); } else { ZVAL_COPY(result, res); } zval_ptr_dtor(&property); #if PHP_VERSION_ID >= 70100 EG(fake_scope) = old_scope; #else EG(scope) = old_scope; #endif return SUCCESS; }
/** * Increments an object property */ int zephir_property_incr_decr(zval *object, char *property_name, unsigned int property_length, unsigned int increment) { zval tmp; zend_class_entry *ce; int separated = 0; ZVAL_UNDEF(&tmp); if (Z_TYPE_P(object) != IS_OBJECT) { php_error_docref(NULL, E_WARNING, "Attempt to assign property of non-object"); return FAILURE; } ce = Z_OBJCE_P(object); if (ce->parent) { ce = zephir_lookup_class_ce(ce, property_name, property_length); } zephir_read_property(&tmp, object, property_name, property_length, 0); if (Z_TYPE(tmp) > IS_UNDEF) { Z_TRY_DELREF(tmp); /** Separation only when refcount > 1 */ if (Z_REFCOUNTED(tmp)) { if (Z_REFCOUNT(tmp) > 1) { if (!Z_ISREF(tmp)) { zval new_zv; ZVAL_DUP(&new_zv, &tmp); ZVAL_COPY_VALUE(&tmp, &new_zv); Z_TRY_DELREF(new_zv); separated = 1; } } } else { zval new_zv; ZVAL_DUP(&new_zv, &tmp); ZVAL_COPY_VALUE(&tmp, &new_zv); Z_TRY_DELREF(new_zv); separated = 1; } if (increment) { zephir_increment(&tmp); } else { zephir_decrement(&tmp); } if (separated) { zephir_update_property_zval(object, property_name, property_length, &tmp); } } return SUCCESS; }