示例#1
0
        /// <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();
        }
示例#2
0
 /// <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);
         }
     }
 }
示例#3
0
        /// <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);
            }
        }
示例#4
0
        /// <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);
            }
        }
示例#5
0
            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);
                }
            }
示例#6
0
            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);
                }
            }
示例#7
0
 public virtual long count()
 {
     if (_underlayingArray != null)
     {
         // array size
         return(_underlayingArray.Count);
     }
     else
     {
         // public (visible) instance properties + runtime fields
         return(TypeMembersUtils.EnumerateVisibleInstanceFields(_underlayingObject).LongCount());
     }
 }
示例#8
0
 public PhpArray getArrayCopy()
 {
     if (_underlayingArray != null)
     {
         // array size
         return(_underlayingArray.DeepCopy());
     }
     else
     {
         // public (visible) instance properties + runtime fields
         return(new PhpArray(TypeMembersUtils.EnumerateVisibleInstanceFields(_underlayingObject)));
     }
 }
示例#9
0
        public virtual long count()
        {
            if (isArrayIterator)
            {
                return(_array.Count);
            }
            else if (isObjectIterator)
            {
                return(TypeMembersUtils.FieldsCount(_dobj));
            }

            return(0);
        }
示例#10
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);
        }
示例#11
0
            /// <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();
                }
            }
示例#12
0
            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);
                }
            }
示例#13
0
        /// <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();
        }
示例#14
0
        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");
        }
示例#15
0
            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);
                }
            }
示例#16
0
 /// <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);
         }
     }
 }
示例#17
0
                // 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));
                }
示例#18
0
 public PhpFieldsEnumerator(object obj, RuntimeTypeHandle caller)
 {
     Debug.Assert(obj != null);
     _enumerator = TypeMembersUtils.EnumerateVisibleInstanceFields(obj, caller).GetEnumerator();
     _valid      = true;
 }
示例#19
0
 IEnumerable <KeyValuePair <string, PhpValue> > JsonObjectProperties(object /*!*/ obj)
 {
     return(TypeMembersUtils.EnumerateInstanceFields(obj, (f, d) => f.Name, (k) => k.ToString()));
 }
示例#20
0
                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));
                    }
                }