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.lang.IObject;
import php.runtime.memory.ArrayMemory;
import php.runtime.memory.LongMemory;
import php.runtime.memory.ObjectMemory;
import php.runtime.memory.StringMemory;
import php.runtime.reflection.ClassEntity;
import php.runtime.reflection.MethodEntity;
import php.runtime.reflection.ParameterEntity;
import php.runtime.reflection.support.AbstractFunctionEntity;
import static php.runtime.annotation.Reflection.*;
@Name("ReflectionMethod")
@Signature({
@Arg(value = "name", type = HintType.STRING, readOnly = true),
@Arg(value = "class", type = HintType.STRING, readOnly = true)
})
public class ReflectionMethod extends ReflectionFunctionAbstract {
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 ;
public final static int IS_ABSTRACT = 2 ;
public final static int IS_FINAL = 4 ;
protected MethodEntity methodEntity;
protected ArrayMemory cachedParameters;
protected boolean hackAccess = false;
public ReflectionMethod(Environment env, MethodEntity methodEntity) {
super(env);
setEntity(methodEntity);
}
public ReflectionMethod(Environment env, ClassEntity clazz) {
super(env, clazz);
}
public void setEntity(MethodEntity entity) {
this.methodEntity = 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 _class = args[0];
if (_class.isObject())
classEntity = _class.toValue(ObjectMemory.class).getReflection();
else
classEntity = env.fetchClass(_class.toString(), true);
if (classEntity == null){
exception(env, Messages.ERR_CLASS_NOT_FOUND.fetch(_class));
return Memory.NULL;
}
MethodEntity entity = classEntity.findMethod(args[1].toString().toLowerCase());
if (entity == null){
exception(env, Messages.ERR_METHOD_NOT_FOUND.fetch(_class, args[1]));
return Memory.NULL;
}
setEntity(entity);
return Memory.NULL;
}
@Override
protected AbstractFunctionEntity getEntity() {
return methodEntity;
}
@Override
@Signature
public Memory getParameters(Environment env, Memory... args) {
if (cachedParameters != null)
return cachedParameters;
ParameterEntity[] parameters = methodEntity.getParameters(Integer.MAX_VALUE);
ClassEntity entity = env.fetchClass("ReflectionParameter");
ArrayMemory result = new ArrayMemory();
int i = 0;
for(ParameterEntity param : parameters){
ReflectionParameter e = new ReflectionParameter(env, entity);
e.setEntity(param);
e.setFunctionEntity(methodEntity);
e.setPosition(i);
i++;
result.add(new ObjectMemory(e));
}
return cachedParameters = result;
}
@Signature
public Memory getDeclaringClass(Environment env, Memory... args){
ClassEntity entity = env.fetchClass("ReflectionClass");
ReflectionClass r = new ReflectionClass(env, entity);
r.setEntity(methodEntity.getClazz());
return new ObjectMemory(r);
}
@Signature
public Memory getModifiers(Environment env, Memory... args){
int mod = 0;
if (methodEntity.isAbstract())
mod |= IS_ABSTRACT;
if (methodEntity.isFinal())
mod |= IS_FINAL;
if (methodEntity.isPrivate())
mod |= IS_PRIVATE;
else if (methodEntity.isProtected())
mod |= IS_PROTECTED;
else if (methodEntity.isPublic())
mod |= IS_PUBLIC;
if (methodEntity.isStatic())
mod |= IS_STATIC;
return LongMemory.valueOf(mod);
}
@Signature
public Memory getPrototype(Environment env, Memory... args){
if (methodEntity.getPrototype() == null)
return Memory.NULL;
ClassEntity classEntity = env.fetchClass("ReflectionMethod");
ReflectionMethod r = new ReflectionMethod(env, classEntity);
r.setEntity(methodEntity.getPrototype());
return new ObjectMemory(r);
}
@Signature
public Memory isConstructor(Environment env, Memory... args) {
return methodEntity.getClazz().methodConstruct == methodEntity ? Memory.TRUE : Memory.FALSE;
}
@Signature
public Memory isDestruct(Environment env, Memory... args) {
return methodEntity.getClazz().methodDestruct == methodEntity ? Memory.TRUE : Memory.FALSE;
}
@Signature
public Memory isAbstract(Environment env, Memory... args){
return methodEntity.isAbstract() ? Memory.TRUE : Memory.FALSE;
}
@Signature
public Memory isFinal(Environment env, Memory... args){
return methodEntity.isFinal() ? Memory.TRUE : Memory.FALSE;
}
@Signature
public Memory isStatic(Environment env, Memory... args){
return methodEntity.isStatic() ? Memory.TRUE : Memory.FALSE;
}
@Signature
public Memory isPublic(Environment env, Memory... args){
return methodEntity.isPublic() ? Memory.TRUE : Memory.FALSE;
}
@Signature
public Memory isProtected(Environment env, Memory... args){
return methodEntity.isProtected() ? Memory.TRUE : Memory.FALSE;
}
@Signature
public Memory isPrivate(Environment env, Memory... args){
return methodEntity.isPrivate() ? Memory.TRUE : Memory.FALSE;
}
@Signature(@Arg("accessible"))
public Memory setAccessible(Environment env, Memory... args){
hackAccess = args[0].toBoolean();
return Memory.NULL;
}
@Signature(@Arg("object"))
public Memory getClosure(final Environment env, Memory... args) throws Throwable {
IObject object;
if (args[0].isNull()){
object = null;
} else if (args[0].isObject()) {
object = args[0].toValue(ObjectMemory.class).value;
} else {
exception(env, "Argument 1 must be NULL or object, %s given", args[0].getRealType().toString());
return Memory.NULL;
}
if (object == null && !methodEntity.isStatic()){
exception(env, "Cannot use method as static");
return Memory.NULL;
} else if (object != null && methodEntity.isStatic()){
exception(env, "Cannot use method as non static");
return Memory.NULL;
}
return new ObjectMemory(methodEntity.getClosure(env, object));
}
}