public Memory setProperty(Environment env, TraceInfo trace,
                              IObject object, String property, Memory memory, SetterCallback callback,
                              PropertyCallCache callCache, int cacheIndex)
            throws Throwable {
        ReferenceMemory value;

        PropertyEntity entity = callCache == null ? null : callCache.get(env, cacheIndex);

        if (entity == null) {
            ClassEntity context = env.getLastClassOnStack();
            entity = isInstanceOf(context) ? context.properties.get(property) : properties.get(property);

            if (callCache != null && entity != null) {
                callCache.put(env, cacheIndex, entity);
            }
        } else if (entity.getClazz() != object.getReflection()) {
            ClassEntity context = env.getLastClassOnStack();
            entity = isInstanceOf(context) ? context.properties.get(property) : properties.get(property);
        }

        if (entity == null) {
            PropertyEntity staticEntity = staticProperties.get(property);
            if (staticEntity != null) {
                invalidAccessToProperty(env, trace, staticEntity, staticEntity.canAccess(env));
                env.error(trace, ErrorType.E_STRICT,
                        Messages.ERR_ACCESSING_STATIC_PROPERTY_AS_NON_STATIC,
                        staticEntity.getClazz().getName(),
                        staticEntity.getName()
                );
            }
        }

        int accessFlag = entity == null ? 0 : entity.canAccess(env);

        ArrayMemory props = object.getPropertiesForChange();

        if (entity != null) {
            if (entity.setter != null) {
                if (callback != null)
                    memory = callback.invoke(entity, getProperty(env, trace, object, property, null, 0), memory);

                try {
                    ObjectInvokeHelper.invokeMethod(object, entity.setter, env, trace, new Memory[]{memory}, false);
                } catch (IllegalArgumentException e) {
                    if (!object.getReflection().isInstanceOf(entity.setter.getClazz())) {
                        return setProperty(env, trace, object, property, memory, callback, null, 0);
                    }

                    throw e;
                }
                return memory;
            } else if (entity.getter != null) {
                env.error(trace, ErrorType.E_RECOVERABLE_ERROR, Messages.ERR_READONLY_PROPERTY.fetch(entity.getClazz().getName(), property));
            }
        }

        value = props == null || accessFlag != 0 ? null : props.getByScalar(entity == null ? property : entity.specificName);

        if (value == null) {
            boolean recursive = false;

            ClassEntity context = env.getLastClassOnStack();

            if (context != null && methodMagicSet != null && context.getId() == methodMagicSet.getClazz().getId()) {
                recursive = env.peekCall(0).flags == FLAG_SET;
            }

            if (methodMagicSet != null && !recursive) {
                StringMemory memoryProperty = new StringMemory(property);

                if (callback != null) {
                    Memory o1 = Memory.NULL;
                    if (methodMagicGet != null) {
                        try {
                            Memory[] args = new Memory[]{memoryProperty};
                            env.pushCall(
                                    trace, object, args, methodMagicGet.getName(), methodMagicSet.getClazz().getName(), name
                            );
                            env.peekCall(0).flags = FLAG_GET;

                            args = InvokeArgumentHelper.checkType(env, trace, methodMagicGet, args);
                            o1 = methodMagicGet.invokeDynamic(object, env, trace, args);
                        } finally {
                            env.popCall();
                        }
                    }
                    memory = callback.invoke(entity, o1, memory);
                }

                try {
                    Memory[] args = new Memory[]{memoryProperty, memory};
                    env.pushCall(trace, object, args, methodMagicSet.getName(), methodMagicSet.getClazz().getName(), name);
                    env.peekCall(0).flags = FLAG_SET;

                    args = InvokeArgumentHelper.checkType(env, trace, methodMagicSet, args);
                    methodMagicSet.invokeDynamic(object, env, trace, args);
                } finally {
                    env.popCall();
                }
            } else {
                /*if (accessFlag != 0) {
                    invalidAccessToProperty(env, trace, entity, accessFlag);
                    return Memory.NULL;
                }*/

                if (callback != null)
                    memory = callback.invoke(entity, Memory.NULL, memory);

                String name = property;
                if (entity != null) {
                    if (accessFlag != 0 && context == null) {
                        switch (accessFlag) {
                            case 2:
                                if (object.getReflection().getId() == entity.getClazz().getId()) {
                                    invalidAccessToProperty(env, trace, entity, accessFlag);
                                    return Memory.NULL;
                                }
                                break;
                            case 1:
                                invalidAccessToProperty(env, trace, entity, accessFlag);
                                return Memory.NULL;
                        }
                    }

                    if (context != null) {
                        switch (entity.modifier) {
                            case PRIVATE:
                                if (entity.getClazz().getId() == context.getId())
                                    name = entity.specificName;
                                break;
                            case PROTECTED:
                                if (context.isInstanceOf(entity.getClazz()))
                                    name = entity.specificName;
                        }
                    }
                }

                return props == null
                        ? Memory.NULL
                        : (entity == null ? props.refOfIndex(name).assign(memory) : entity.assignValue(env, trace, object, name, memory));
            }
        } else {
            if (callback != null)
                memory = callback.invoke(entity, value, memory);

            if (entity instanceof CompilePropertyEntity) {
                return entity.assignValue(env, trace, object, property, memory);
            }

            if (entity != null && entity.isTyped()) {
                if (!memory.isImmutable()) {
                    env.error(
                            trace, Messages.ERR_ASSIGN_BY_REF_FOR_TYPED_PROP.fetch(
                            entity.getClazz().getName(),
                            entity.getName())
                    );
                }

                return value.assign(entity.typedValue(env, trace, memory));
            } else {
                return value.assign(entity == null ? memory : entity.typedValue(env, trace, memory));
            }
        }
        return memory;
    }
return empty list if success else list with not valid implemented methods in class

@param _interface
@return
jphp-runtime/src/php/runtime/reflection/ClassEntity.java