public PhpValue GetValue(PhpValue value, Context ctx, Type classContext) { var receiver = value.AsObject(); if (receiver != null) { // CONSIDER: value = Operators.PropertyGetValue( .. ) var t = receiver.GetPhpTypeInfo(); if (BinderHelpers.TryResolveDeclaredProperty(t, classContext, false, Name, out var p)) { value = p.GetValue(ctx, receiver); } else { value = Operators.RuntimePropertyGetValue(ctx, t, receiver, propertyName: Name); } return(Next.GetValue(value, ctx, classContext)); } else { PhpException.VariableMisusedAsObject(value, false); return(PhpValue.Null); } }
/// <summary> /// Tests whether <paramref name="value"/>'s class is derived from a class given by <paramref name="class_name"/>. /// </summary> /// <param name="ctx">Runtime context.</param> /// <param name="value">The object to test.</param> /// <param name="class_name">The name of the class.</param> /// <param name="allow_string">If this parameter set to FALSE, string class name as object is not allowed. This also prevents from calling autoloader if the class doesn't exist.</param> /// <returns><B>true</B> if the object <paramref name="value"/> belongs to <paramref name="class_name"/> class or /// a class which is a subclass of <paramref name="class_name"/>, <B>false</B> otherwise.</returns> public static bool is_a(Context ctx, PhpValue value, string class_name, bool allow_string) { // first load type of {value} PhpTypeInfo tvalue; var obj = value.AsObject(); if (obj != null) { tvalue = obj.GetPhpTypeInfo(); } else { var tname = value.AsString(); if (tname != null && allow_string) { // value can be a string specifying a class name tvalue = ctx.GetDeclaredType(tname, true); } else { // invalid argument type ignored return(false); } } // second, load type of {class_name} var ctype = ctx.GetDeclaredType(class_name, false); // check is_a return(tvalue != null && ctype != null && tvalue.Type.IsSubclassOf(ctype.Type.AsType())); }
public void __construct(Context ctx, PhpValue name) { Debug.Assert(_routine == null, "Subsequent call not allowed."); object instance; var str = name.ToStringOrNull(); if (str != null) { _closure = null; _routine = ctx.GetDeclaredFunction(str) ?? throw new ReflectionException(string.Format(Resources.LibResources.function_does_not_exist, str)); } else if ((instance = name.AsObject()) != null) { if (instance is Closure closure) { _closure = closure; _routine = closure.Callable() as RoutineInfo; // TODO: handle its $this parameter and use parameters } } if (_routine == null) { throw new ReflectionException(); } }
public void __construct(Context ctx, PhpValue name) { Debug.Assert(_routine == null, "Subsequent call not allowed."); object instance; var str = name.ToStringOrNull(); if (str != null) { _routine = ctx.GetDeclaredFunction(str); } else if ((instance = name.AsObject()) != null) { if (instance is Closure) { // _routine = ((Closure)instance).routine; // TODO: handle its $this parameter and use parameters throw new NotImplementedException(); } } if (_routine == null) { throw new ArgumentException(); // TODO: ReflectionException } }
internal RuntimeTypeHandle ResolveNewScope(object newthis, PhpValue newscope = default(PhpValue)) { if (newscope.IsSet) { // Operators.TypeNameOrObjectToType(newscope) + handle "static" object obj; string str; if ((obj = (newscope.AsObject())) != null) { return(obj.GetType().TypeHandle); } else if ((str = PhpVariable.AsString(newscope)) != null) { return("static".Equals(str, StringComparison.OrdinalIgnoreCase) ? _scope : _ctx.GetDeclaredTypeOrThrow(str, true).TypeHandle); } else if (newscope.IsNull) { return(default(RuntimeTypeHandle)); } else { throw new ArgumentException(nameof(newscope)); } } return(ReferenceEquals(newthis, null) ? _scope : newthis.GetType().TypeHandle); }
/// <summary> /// Verifies whether a property has been defined for the given object object or class. /// </summary> /// <remarks> /// If an object is passed in the first parameter, the property is searched among runtime fields as well. /// </remarks> public static bool property_exists(Context ctx, PhpValue classNameOrObject, string propertyName) { var tinfo = TypeNameOrObjectToType(ctx, classNameOrObject); if (tinfo == null) { return(false); } if (tinfo.GetDeclaredProperty(propertyName) != null) { // CT property found return(true); } var instance = classNameOrObject.AsObject(); if (instance != null && tinfo.GetRuntimeProperty(propertyName, instance) != null) { // RT property found return(true); } // return(false); }
/// <summary> /// Internal image save. /// </summary> /// <param name="ctx">Runtime context.</param> /// <param name="im">Image resource.</param> /// <param name="to">Optional. Filename or stream. If not specified the functiona saves the image to output stream.</param> /// <param name="saveaction">Callback that actually save the image to given stream. Called when all checks pass.</param> /// <returns>True if save succeeded.</returns> static bool imagesave(Context ctx, PhpResource im, PhpValue to /* = null*/, Action <Image <Rgba32>, Stream> saveaction) { Debug.Assert(saveaction != null); // check the gd2 resource var img = PhpGdImageResource.ValidImage(im); if (img == null) { return(false); } try { // not specified stream or filename -> save to the output stream if (to.IsEmpty) { saveaction(img.Image, ctx.OutputStream); return(true); } // filename specified? var filename = to.ToStringOrNull(); if (filename != null) { using (var stream = File.OpenWrite(Path.Combine(ctx.WorkingDirectory, filename))) { saveaction(img.Image, stream); } return(true); } // to a PHP stream ? // validate the stream resource, outputs warning in case of invalid resource var phpstream = PhpStream.GetValid(to.AsObject() as PhpResource, FileAccess.Write); if (phpstream == null) { return(false); } // save image to byte[] and pass it to php stream var ms = new MemoryStream(); saveaction(img.Image, ms); phpstream.WriteBytes(ms.ToArray()); phpstream.Flush(); // stream is closed after the operation phpstream.Dispose(); } catch { return(false); } return(true); }
/// <summary> /// Removes an object from the storage. /// </summary> public virtual void offsetUnset(PhpValue offset) { var obj = offset.AsObject(); if (obj != null) { this.storage.Remove(Keys.MakeKey(obj)); } }
public override void __construct(Context ctx, PhpValue @class) { _instance = @class.AsObject(); if (_instance == null) { throw new ReflectionException(); } _tinfo = _instance.GetPhpTypeInfo(); }
/// <summary> /// This function allows to use parser inside object. All callback functions could be set with /// xml_set_element_handler() etc and assumed to be methods of object. /// </summary> /// <param name="parser">A reference to the XML parser to use inside the object. </param> /// <param name="objRef">The object where to use the XML parser.</param> /// <returns>Returns TRUE on success or FALSE on failure. </returns> public static bool xml_set_object(PhpResource parser, PhpValue objRef) { var xmlParser = XmlParserResource.ValidResource(parser); if (xmlParser != null) { xmlParser.HandlerObject = objRef.AsObject(); return(true); } return(false); }
public PhpAlias GetAlias(ref PhpValue value, Context ctx, Type classContext) { PhpValue tmp; if (value.AsObject() is ArrayAccess arrayaccess) { // special case for ArrayAccess avoids conversion to IntStringKey tmp = arrayaccess.offsetGet(Key); switch (Next.Operation) { case RuntimeChainOperation.ArrayItem: tmp = PhpValue.EnsureAlias(ref tmp); break; case RuntimeChainOperation.Property: tmp = PhpValue.FromClass(PhpValue.EnsureObject(ref tmp)); break; case RuntimeChainOperation.End: return(PhpValue.EnsureAlias(ref tmp)); default: throw new InvalidOperationException(); } } else { var arr = PhpValue.EnsureArray(ref value); switch (Next.Operation) { case RuntimeChainOperation.ArrayItem: tmp = PhpValue.Create(arr.EnsureItemArray(Key)); break; case RuntimeChainOperation.Property: tmp = PhpValue.FromClass(arr.EnsureItemObject(Key)); break; case RuntimeChainOperation.End: return(arr.EnsureItemAlias(Key)); default: throw new InvalidOperationException(); } } // return(Next.GetAlias(ref tmp, ctx, classContext)); }
/// <summary> /// Returns the data associated with an object in the storage. /// </summary> public virtual PhpValue offsetGet(PhpValue offset) { var obj = offset.AsObject(); if (obj != null && this.storage.TryGetValue(Keys.MakeKey(obj), out PhpValue value)) { return(value.Array[Keys.Info]); } else { throw new UnexpectedValueException(); } }
/// <summary> /// Associate data to an object in the storage. /// </summary> public virtual void offsetSet(PhpValue offset, PhpValue value = default(PhpValue)) { var obj = offset.AsObject(); if (obj != null) { Keys.AttachImpl(storage, obj, value); } else { throw new ArgumentException(nameof(offset)); } }
public static string get_class(PhpValue @object) { var obj = @object.AsObject(); if (obj == null || obj is PhpResource) { // TODO: Warning: get_class() expects parameter 1 to be object, {PhpVariable.GetTypeName(@object)} given PhpException.InvalidArgumentType(nameof(@object), PhpVariable.TypeNameObject); return(null); // FALSE } return(PhpVariable.GetClassName(obj)); }
/// <summary> /// Tests whether <paramref name="value"/>'s class is derived from a class given by <paramref name="class_name"/>. /// </summary> /// <param name="ctx">Runtime context.</param> /// <param name="value">The object to test.</param> /// <param name="class_name">The name of the class.</param> /// <param name="allow_string">If this parameter set to FALSE, string class name as object is not allowed. This also prevents from calling autoloader if the class doesn't exist.</param> /// <returns><B>true</B> if the object <paramref name="value"/> belongs to <paramref name="class_name"/> class or /// a class which is a subclass of <paramref name="class_name"/>, <B>false</B> otherwise.</returns> public static bool is_a(Context ctx, PhpValue value, string class_name, bool allow_string) { var obj = value.AsObject(); if (allow_string) { // value can be a string specifying a class name // autoload is allowed throw new NotImplementedException(); } else { return(is_a(ctx, obj, class_name)); } }
/// <summary> /// Get <see cref="PhpTypeInfo"/> from either a class name or a class instance. /// </summary> /// <returns>Type info instance if object is valid class reference, otherwise <c>null</c>.</returns> internal static PhpTypeInfo TypeNameOrObjectToType(Context ctx, PhpValue @object, RuntimeTypeHandle selftype = default(RuntimeTypeHandle), bool autoload = true, bool allowName = true) { object obj; string str; if ((obj = (@object.AsObject())) != null) { return(obj.GetPhpTypeInfo()); } else if ((str = PhpVariable.AsString(@object)) != null) { return(allowName ? ctx.GetDeclaredType(str, autoload) : null); } else { // other @object types are not handled return((selftype.Equals(default) || [email protected])
/// <summary> /// Resolves type of <paramref name="class"/>. /// </summary> /// <param name="ctx">Context.</param> /// <param name="class">Either string or class instance. Otherwise an exception is thrown.</param> /// <returns>Type info. Cannot get <c>null</c>.</returns> /// <exception cref="ReflectionException">In case <paramref name="class"/> does not exist or <paramref name="class"/> is not a string or object.</exception> public static PhpTypeInfo ResolvePhpTypeInfo(Context ctx, PhpValue @class) { object instance; if (@class.IsString(out var classname)) { return(ctx.GetDeclaredType(classname, true) ?? throw new ReflectionException(string.Format(Resources.Resources.class_does_not_exist, classname))); } else if ((instance = @class.AsObject()) != null) { return(instance.GetPhpTypeInfo()); } else { throw new ReflectionException(string.Format(ErrResources.invalid_argument_type, nameof(@class), "string or object")); } }
/// <summary> /// Constructs the array iterator. /// </summary> /// <param name="ctx">Runtime context.</param> /// <param name="array">The array or object to be iterated on.</param> /// <param name="flags">Flags to control the behaviour of the ArrayIterator object. See ArrayIterator::setFlags().</param> public virtual void __construct(Context /*!*/ ctx, PhpValue array, int flags = 0) { if ((_array = array.ArrayOrNull()) != null) { InitArrayIteratorHelper(); // instantiate now, avoid repetitous checks during iteration } else if ((_dobj = array.AsObject()) != null) { //InitObjectIteratorHelper(); // lazily to avoid one additional allocation } else { throw new ArgumentException(); //// throw an PHP.Library.SPL.InvalidArgumentException if anything besides an array or an object is given. //Exception.ThrowSplException( // _ctx => new InvalidArgumentException(_ctx, true), // context, // null, 0, null); } }
internal static PhpTypeInfo ResolvePhpTypeInfo(Context ctx, PhpValue @class) { object instance; var classname = @class.ToStringOrNull(); if (classname != null) { return(ctx.GetDeclaredType(classname, true)); } else if ((instance = @class.AsObject()) != null) { return(instance.GetPhpTypeInfo()); } else { // argument type exception } return(null); }
static bool TryProcessMethodFromStream(PhpValue value, ProcessMethod @default, ref ProcessMethod processing, bool readable = false) { if (Operators.IsSet(value)) { var stream = value.AsObject() as PhpStream; if (stream != null && (readable ? stream.CanRead : stream.CanWrite)) { processing = new ProcessMethod(stream); } else { return(false); // failure } } else { processing = @default; } return(true); }
static object AsKey(PhpValue offset) { return(offset.AsObject() ?? throw (offset.IsNull ? ObjectNullException() : TypeErrorException())); }
/// <summary> /// Checks whether a dereferenced variable is an instance of class. /// </summary> /// <param name="variable">The variable.</param> /// <returns>Whether <paramref name="variable"/> is <see cref="object"/>.</returns> public static bool is_object(PhpValue variable) { var obj = variable.AsObject(); return(obj != null && !(obj is __PHP_Incomplete_Class) && !(obj is PhpResource)); }
/// <summary> /// Checks whether an object exists in the storage. /// </summary> /// <remarks>Alias for <see cref="contains(object)"/>.</remarks> public virtual bool offsetExists(PhpValue offset) => contains(offset.AsObject());