package php.runtime.ext.core.reflection; import php.runtime.Memory; import php.runtime.common.HintType; import php.runtime.common.Messages; import php.runtime.env.Environment; import php.runtime.memory.LongMemory; import php.runtime.memory.ObjectMemory; import php.runtime.memory.StringMemory; import php.runtime.reflection.ClassEntity; import php.runtime.reflection.PropertyEntity; import static php.runtime.annotation.Reflection.*; @Name("ReflectionProperty") @Signature({ @Arg(value = "name", type = HintType.STRING, readOnly = true), @Arg(value = "class", type = HintType.STRING, readOnly = true) }) public class ReflectionProperty extends Reflection implements Reflector { public final static int IS_STATIC = 1; public final static int IS_PUBLIC = 256; public final static int IS_PROTECTED = 512; public final static int IS_PRIVATE = 1024; protected PropertyEntity entity; protected boolean hackAccess = false; public ReflectionProperty(Environment env, ClassEntity clazz) { super(env, clazz); } public void setEntity(PropertyEntity entity) { this.entity = entity; getProperties().put("name", new StringMemory(entity.getName())); getProperties().put("class", new StringMemory(entity.getClazz().getName())); } @Signature({@Arg("class"), @Arg("name")}) public Memory __construct(Environment env, Memory... args){ ClassEntity classEntity; Memory arg = args[0]; if (arg.isObject()){ classEntity = arg.toValue(ObjectMemory.class).getReflection(); } else classEntity = env.fetchClass(arg.toString()); if (classEntity == null){ exception(env, Messages.ERR_CLASS_NOT_FOUND.fetch(arg)); return Memory.NULL; } String prop = args[1].toString(); PropertyEntity entity = classEntity.findProperty(prop); if (entity == null) entity = classEntity.findStaticProperty(prop); if (entity == null){ exception(env, Messages.ERR_UNDEFINED_PROPERTY.fetch(classEntity.getName(), prop)); return Memory.NULL; } setEntity(entity); return Memory.NULL; } @Override @Signature public Memory __toString(Environment env, Memory... args) { return new StringMemory("TODO"); } @Signature public Memory getDeclaringClass(Environment env, Memory... args){ ReflectionClass clazz = new ReflectionClass(env, env.fetchClass("ReflectionClass")); clazz.setEntity(entity.getClazz()); return new ObjectMemory(clazz); } @Signature public Memory getDocComment(Environment env, Memory... args){ if (entity.getDocComment() == null) return Memory.FALSE; return new StringMemory(entity.getDocComment().toString()); } @Signature public Memory getModifiers(Environment env, Memory... args){ int mod = 0; if (entity.isStatic()) mod += IS_STATIC; if (entity.isPrivate()) mod += IS_PRIVATE; if (entity.isProtected()) mod += IS_PROTECTED; if (entity.isPublic()) mod += IS_PUBLIC; return LongMemory.valueOf(mod); } @Signature public Memory getName(Environment env, Memory... args){ return new StringMemory(entity.getName()); } @Signature(@Arg(value = "object", optional = @Optional(value = "NULL"))) public Memory getValue(Environment env, Memory... args) throws Throwable { if (!hackAccess){ int access = entity.canAccess(env); if (access != 0) { exception(env, "Cannot access non-public member %s::$%s", entity.getClazz().getName(), entity.getName()); return Memory.NULL; } } Memory arg = args[0]; if (arg.isNull()){ if (!entity.isStatic()) exception(env, "Dynamic property %s::$%s cannot get a property value statically", entity.getClazz().getName(), entity.getName()); return entity.getClazz().getStaticProperty(env, env.trace(), entity.getName(), true, false, null, null, 0); } else { if (arg.isObject()){ if (entity.isStatic()) exception(env, "Static property %s::$%s cannot get a property value dynamically", entity.getClazz().getName(), entity.getName()); return arg.toValue(ObjectMemory.class).getProperties().valueOfIndex(entity.getSpecificName()); } else exception(env, "Argument 1 must be object, given %s", arg.getRealType().toString()); } return Memory.NULL; } @Signature public Memory isDefault(Environment env, Memory... args){ return entity.isDefault() ? Memory.TRUE : Memory.FALSE; } @Signature public Memory isPublic(Environment env, Memory... args){ return entity.isPublic() ? Memory.TRUE : Memory.FALSE; } @Signature public Memory isPrivate(Environment env, Memory... args){ return entity.isPrivate() ? Memory.TRUE : Memory.FALSE; } @Signature public Memory isProtected(Environment env, Memory... args){ return entity.isProtected() ? Memory.TRUE : Memory.FALSE; } @Signature public Memory isStatic(Environment env, Memory... args){ return entity.isStatic() ? Memory.TRUE : Memory.FALSE; } @Signature(@Arg("accessible")) public Memory setAccessible(Environment env, Memory... args){ hackAccess = args[0].toBoolean(); return Memory.NULL; } @Signature({@Arg("object"), @Arg("value")}) public Memory setValue(Environment env, Memory... args) throws Throwable { if (!hackAccess){ int access = entity.canAccess(env); if (access != 0) { exception(env, "Cannot access non-public member %s::$%s", entity.getClazz().getName(), entity.getName()); } } Memory arg = args[0]; if (entity.isStatic()){ if (!arg.isNull()) exception(env, "Static property %s::$%s cannot get a property value dynamically", entity.getClazz().getName(), entity.getName()); entity.getClazz().getStaticProperty(env, env.trace(), entity.getName(), true, false, null, null, 0).assign(args[1]); } else { if (arg.isObject()){ arg.toValue(ObjectMemory.class).getProperties().refOfIndex(entity.getSpecificName()).assign(args[1]); } else exception(env, "Argument 1 must be object, given %s", arg.getRealType().toString()); } return Memory.NULL; } }