/// <summary> /// Instantiate new object's enumerator and advances its position to the first element. /// </summary> /// <returns><c>True</c> whether there is an first element.</returns> void InitObjectIteratorHelper() { Debug.Assert(_dobj != null); _dobjEnumerator = TypeMembersUtils.EnumerateVisibleInstanceFields(_dobj).GetEnumerator(); // we have to create new enumerator (or implement InstancePropertyIterator.Reset) _isValid = _dobjEnumerator.MoveNext(); }
/// <summary> /// Creates <see cref="PhpArray"/> from object's properties. /// </summary> /// <param name="obj">Object instance.</param> /// <returns>Array containing given object properties keyed according to PHP specifications.</returns> public static PhpArray ClassToArray(object obj) { if (object.ReferenceEquals(obj, null)) { return(PhpArray.NewEmpty()); } else if (obj.GetType() == typeof(stdClass)) { // special case, // object is stdClass, we can simply copy its runtime fields return(((stdClass)obj).GetRuntimeFields().DeepCopy()); } else { if (obj is Array) { // [] -> array return(new PhpArray((Array)obj)); } // TODO: IList else { // obj -> array var arr = new PhpArray(); TypeMembersUtils.InstanceFieldsToPhpArray(obj, arr); return(arr); } } }
/// <summary> /// Returns the current row of a result set as an object. /// </summary> public object fetch_object(string class_name = null, PhpArray class_params = null) { if (string.IsNullOrEmpty(class_name) || nameof(stdClass).Equals(class_name, StringComparison.OrdinalIgnoreCase)) { return(_result.FetchStdClass()); } if (_result.TryReadRow(out object[] oa, out string[] names)) { // instantiate class dynamically: var ctx = _result.Connection.Context; var phpt = ctx.GetDeclaredTypeOrThrow(class_name, autoload: true); var obj = phpt.Creator(ctx, (class_params == null) ? Array.Empty <PhpValue>() : class_params.GetValues()); // set object properties using reflection: for (int i = 0; i < names.Length; i++) { // TODO: Operators.PropertySetValue( obj, names[i], FromClr(oa[i]) ); var p = TypeMembersUtils.GetDeclaredProperty(phpt, names[i]) ?? TypeMembersUtils.GetRuntimeProperty(phpt, names[i], obj); p.SetValue(ctx, obj, PhpValue.FromClr(oa[i])); } // return(obj); } else { return(null); } }
/// <summary> /// Gets the properties of the given object. /// </summary> /// <param name="caller">Caller context.</param> /// <param name="obj"></param> /// <returns>Returns an associative array of defined object accessible non-static properties for the specified object in scope. /// If a property has not been assigned a value, it will be returned with a NULL value.</returns> public static PhpArray get_object_vars([ImportCallerClass] RuntimeTypeHandle caller, object obj) { Debug.Assert(!(obj is PhpAlias), "obj must be dereferenced"); if (obj == null) { return(null); // not FALSE since PHP 5.3 } else if (obj.GetType() == typeof(stdClass)) { // optimization for stdClass: var arr = ((stdClass)obj).GetRuntimeFields(); return((arr != null) ? arr.DeepCopy() : PhpArray.NewEmpty()); } else { var result = PhpArray.NewEmpty(); foreach (var pair in TypeMembersUtils.EnumerateVisibleInstanceFields(obj, caller)) { result.Add(pair.Key, pair.Value.DeepCopy()); } return(result); } }
public override void AcceptObject(object obj) { if (obj is PhpResource res) { // Resource id #ID _output.Append($"Resource id #{res.Id}"); NewLine(); return; } if (obj is Delegate @delegate) { // Delegate ({METHOD}) _output.Append($"Delegate ({(@delegate.Method != null ? @delegate.Method.Name : PhpVariable.TypeNameNull)})"); return; } // typename Object _output.Append(obj.GetPhpTypeInfo().Name); _output.Append(" "); _output.Append("Object"); if (Enter(obj)) { // ( NewLine(); OutputIndent(); _output.Append("("); NewLine(); _indent++; // object members foreach (var fld in TypeMembersUtils.EnumerateInstanceFieldsForPrint(obj)) { OutputIndent(); _output.Append("[" + fld.Key + "] => "); _indent++; Accept(fld.Value); _indent--; NewLine(); } _indent--; OutputIndent(); _output.Append(")"); // Leave(obj); NewLine(); } else { _output.Append(RECURSION); } }
public override void AcceptObject(object obj) { if (obj is PhpResource res) { // resource(ID) of type (TYPE) _output.Append($"resource({res.Id}) of type ({res.TypeName})"); return; } if (obj is Delegate @delegate) { // delegate(TYPE) with method ({METHOD}) _output.Append($"delegate({obj.GetPhpTypeInfo().Name}) with method ({(@delegate.Method != null ? @delegate.Method.Name : PhpVariable.TypeNameNull)})"); return; } if (Enter(obj)) { var flds = TypeMembersUtils.EnumerateInstanceFieldsForDump(obj).ToList(); // Template: object(NAME)#ID (COUNT) { _output.Append($"object({obj.GetPhpTypeInfo().Name})#{unchecked((uint)obj.GetHashCode())} ({flds.Count}) {{"); _indent++; // object members foreach (var fld in flds) { // [key]=> // value NewLine(); OutputIndent(); _output.Append("[" + fld.Key + "]=>"); NewLine(); OutputIndent(); Accept(fld.Value); } // } _indent--; NewLine(); OutputIndent(); _output.Append("}"); // Leave(obj); } else { // *RECURSION* _output.Append(RECURSION); } }
public virtual long count() { if (_underlayingArray != null) { // array size return(_underlayingArray.Count); } else { // public (visible) instance properties + runtime fields return(TypeMembersUtils.EnumerateVisibleInstanceFields(_underlayingObject).LongCount()); } }
public PhpArray getArrayCopy() { if (_underlayingArray != null) { // array size return(_underlayingArray.DeepCopy()); } else { // public (visible) instance properties + runtime fields return(new PhpArray(TypeMembersUtils.EnumerateVisibleInstanceFields(_underlayingObject))); } }
public virtual long count() { if (isArrayIterator) { return(_array.Count); } else if (isObjectIterator) { return(TypeMembersUtils.FieldsCount(_dobj)); } return(0); }
public PhpArray getStaticProperties(Context ctx) { var array = new PhpArray(); foreach (var p in TypeMembersUtils.GetDeclaredProperties(_tinfo)) { if (p.IsStatic) { array[p.PropertyName] = p.GetValue(ctx, null); } } return(array); }
/// <summary> /// Sets property value dynamically on the newly instantiated object. /// </summary> protected static void SetProperty(object /*!*/ instance, PhpTypeInfo tinfo, string /*!*/ name, PhpValue value, Context /*!*/ context) { // the property name might encode its visibility and "classification" -> use these // information for suitable property desc lookups FieldAttributes visibility; string type_name; string property_name = Serialization.ParseSerializedPropertyName(name, out type_name, out visibility); var declarer = (type_name == null) ? tinfo : context.GetDeclaredType(type_name, true) ?? tinfo; // try to find a suitable field handle var fld = TypeMembersUtils.ResolveInstanceField(tinfo, property_name); if (fld != null && TypeMembersUtils.IsVisible(fld, declarer.Type.AsType())) { if ((fld.IsPrivate && declarer.Type.AsType() != fld.DeclaringType)) { // if certain conditions are met, don't use the handle even if it was found // (this is to precisely mimic the PHP behavior) fld = null; } } if (fld != null) { fld.SetValue(instance, value); } else if (tinfo.RuntimeFieldsHolder != null) { // suitable CT field not found -> add it to RT fields // (note: care must be taken so that the serialize(unserialize($x)) round // trip returns $x even if user classes specified in $x are not declared) var runtime_fields = tinfo.GetRuntimeFields(instance); if (runtime_fields == null) { runtime_fields = new PhpArray(1); tinfo.RuntimeFieldsHolder.SetValue(instance, runtime_fields); } runtime_fields[name] = value; } else { throw new ArgumentException(); } }
public override void AcceptObject(object obj) { // typename Object _output.Append(obj.GetPhpTypeInfo().Name); _output.Append(" "); _output.Append("Object"); if (Enter(obj)) { // ( NewLine(); OutputIndent(); _output.Append("("); NewLine(); _indent++; // object members foreach (var fld in TypeMembersUtils.EnumerateInstanceFieldsForPrint(obj)) { OutputIndent(); _output.Append("[" + fld.Key + "] => "); _indent++; Accept(fld.Value); _indent--; NewLine(); } _indent--; OutputIndent(); _output.Append(")"); // Leave(obj); NewLine(); } else { _output.Append(RECURSION); } }
/// <summary> /// Compares two class instances. /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <param name="comparer">The comparer.</param> /// <param name="incomparable"> /// Whether objects are incomparable while no difference is found before both objects enter an infinite recursion, returns zero. /// </param> static int CompareObjects(object x, object y, PhpComparer comparer, out bool incomparable) { Debug.Assert(x != null && y != null); incomparable = false; // check for same instance if (ReferenceEquals(x, y)) { return(0); } // check for different types var type_x = x.GetType().GetTypeInfo(); var type_y = y.GetType().GetTypeInfo(); if (type_x != type_y) { if (type_x.IsSubclassOf(type_y.AsType())) { return(-1); } if (type_y.IsSubclassOf(type_x.AsType())) { return(1); } incomparable = true; return(1); // they really are incomparable } // check for different number of fields int result = TypeMembersUtils.FieldsCount(x) - TypeMembersUtils.FieldsCount(y); if (result != 0) { return(result); } throw new NotImplementedException(); }
public PhpArray getDefaultProperties(Context ctx) { if (_tinfo.isInstantiable) { var inst = _tinfo.GetUninitializedInstance(ctx); if (inst != null) { var array = new PhpArray(); foreach (var p in TypeMembersUtils.GetDeclaredProperties(_tinfo)) { array[p.PropertyName] = p.GetValue(ctx, inst); } return(array); } } // throw new NotSupportedException("not instantiable type"); }
public override void AcceptObject(object obj) { if (Enter(obj)) { var flds = TypeMembersUtils.EnumerateInstanceFieldsForDump(obj).ToList(); // Template: object(NAME)#ID (COUNT) { _output.Append($"object({obj.GetPhpTypeInfo().Name})#{unchecked((uint)obj.GetHashCode())} ({flds.Count}) {{"); _indent++; // object members foreach (var fld in flds) { // [key]=> // value NewLine(); OutputIndent(); _output.Append("[" + fld.Key + "]=>"); NewLine(); OutputIndent(); Accept(fld.Value); } // } _indent--; NewLine(); OutputIndent(); _output.Append("}"); // Leave(obj); } else { // *RECURSION* _output.Append(RECURSION); } }
/// <summary> /// Creates <see cref="PhpArray"/> from object's properties. /// </summary> /// <param name="obj">Object instance.</param> /// <returns>Array containing given object properties keyed according to PHP specifications.</returns> public static PhpArray ClassToArray(object obj) { if (object.ReferenceEquals(obj, null)) { return(PhpArray.NewEmpty()); } else if (obj.GetType() == typeof(stdClass)) { // special case, // object is stdClass, we can simply copy its runtime fields var runtime_fields = ((stdClass)obj).GetRuntimeFields(); return((runtime_fields != null) ? runtime_fields.DeepCopy() : PhpArray.NewEmpty()); } else { if (obj is IPhpConvertible conv) { return(ToArray(conv)); } else if (obj is Array) { // [] -> array return(new PhpArray((Array)obj)); } else if (obj is System.Collections.IEnumerable) { // the same behavior as foreach for CLR enumerators return(PhpArray.Create(Operators.GetForeachEnumerator((System.Collections.IEnumerable)obj))); } else { // obj -> array var arr = new PhpArray(); TypeMembersUtils.InstanceFieldsToPhpArray(obj, arr); return(arr); } } }
// static IEnumerable<KeyValuePair<string, PhpValue>> JsonArrayProperties(PhpArray array) // { // var enumerator = array.GetFastEnumerator(); // while (enumerator.MoveNext()) // { // var current = enumerator.Current; // yield return new KeyValuePair<string, PhpValue>(current.Key.ToString(), current.Value); // } // } static IEnumerable <KeyValuePair <string, PhpValue> > JsonObjectProperties(object /*!*/ obj) { return(TypeMembersUtils.EnumerateInstanceFields(obj, TypeMembersUtils.s_propertyName, TypeMembersUtils.s_keyToString)); }
public PhpFieldsEnumerator(object obj, RuntimeTypeHandle caller) { Debug.Assert(obj != null); _enumerator = TypeMembersUtils.EnumerateVisibleInstanceFields(obj, caller).GetEnumerator(); _valid = true; }
IEnumerable <KeyValuePair <string, PhpValue> > JsonObjectProperties(object /*!*/ obj) { return(TypeMembersUtils.EnumerateInstanceFields(obj, (f, d) => f.Name, (k) => k.ToString())); }
IEnumerable <KeyValuePair <string, PhpValue> > EnumerateSerializableProperties(object obj, PhpTypeInfo tinfo, PhpArray properties) { Debug.Assert(obj != null); Debug.Assert(tinfo != null); Debug.Assert(properties != null); PhpArray runtime_fields = null; var enumerator = properties.GetFastEnumerator(); while (enumerator.MoveNext()) { // TODO: PhpFieldInfo instead of System.Reflection.FieldInfo FieldAttributes visibility; string name = enumerator.CurrentValue.ToStringOrThrow(_ctx); string declaring_type_name; string property_name = Serialization.ParseSerializedPropertyName(name, out declaring_type_name, out visibility); PhpTypeInfo declarer; // for visibility check if (declaring_type_name == null) { declarer = tinfo; } else { declarer = _ctx.GetDeclaredType(declaring_type_name); if (declarer == null) { // property name refers to an unknown class -> value will be null yield return(new KeyValuePair <string, PhpValue>(name, PhpValue.Null)); continue; } } // obtain the property desc and decorate the prop name according to its visibility and declaring class var fld = TypeMembersUtils.ResolveInstanceField(tinfo, name); if (fld != null && TypeMembersUtils.IsVisible(fld, declarer.Type.AsType())) { var fld_declarer = fld.DeclaringType; // if certain conditions are met, serialize the property as null // (this is to precisely mimic the PHP behavior) if ((visibility == (fld.Attributes & FieldAttributes.FieldAccessMask) && visibility != FieldAttributes.Public) || (visibility == FieldAttributes.Private && declarer.Type.AsType() != fld_declarer)) { yield return(new KeyValuePair <string, PhpValue>(name, PhpValue.Null)); continue; } name = Serialization.FormatSerializedPropertyName(fld, property_name, fld_declarer.GetPhpTypeInfo()); } else { fld = null; // field is not visible, try runtime fields } // obtain the property value PhpValue val; if (fld != null) { val = PhpValue.FromClr(fld.GetValue(obj)); } else { if (runtime_fields == null) { runtime_fields = tinfo.GetRuntimeFields(obj) ?? PhpArray.Empty; } if (!runtime_fields.TryGetValue(name, out val)) { // PHP 5.1+ PhpException.Throw(PhpError.Notice, string.Format(Core.Resources.ErrResources.sleep_returned_bad_field, name)); } } yield return(new KeyValuePair <string, PhpValue>(name, val)); } }