Ejemplo n.º 1
0
        /// <summary>
        /// Try to load all <paramref name="providedTypes"/>. This can invoke autoloading if necessary.
        /// Check if they were not modified, so calling compilation unit has to be invalidated and recompiled.
        /// </summary>
        /// <param name="providedTypes">a list of provided type declarators. Can be a <B>null</B> reference.</param>
        /// <param name="target">The script context to be checked.</param>
        /// <param name="caller">Current class context.</param>
        /// <returns><paramref name="providedTypes"/> are loadable and match in context of <paramref name="target"/>.</returns>
        public static bool LoadAndMatch(List <ProvidedType> providedTypes, ScriptContext /*!*/ target, DTypeDesc caller)
        {
            Debug.Assert(target != null);

            if (providedTypes != null && providedTypes.Count > 0)
            {
                //// there is less declarators than we require:
                //if (target.DeclaredTypes.Count < providedTypes.Count) return false;

                // looks up each provided declarator in the target context:
                foreach (ProvidedType declarator in providedTypes)
                {
                    //DTypeDesc decl_type;
                    //target.DeclaredTypes.TryGetValue(declarator.Key, out decl_type);

                    // When class is compiled in runtime, autoload is invoked on base class (if isn't already declared).
                    // We have to call autoload on the base class also in transient assembly
                    var decl_type = target.ResolveType(declarator.Key, null, caller, null, ResolveTypeFlags.UseAutoload);
                    if (decl_type == null || decl_type.RealType != declarator.Value.RealType)
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Sets a property of a <see cref="DObject"/> instance according to deserialized name and value.
        /// </summary>
        /// <param name="instance">The instance being deserialized.</param>
        /// <param name="name">The property name formatted for serialization (see <see cref="FormatPropertyName"/>).</param>
        /// <param name="value">The property value.</param>
        /// <param name="context">Current <see cref="ScriptContext"/>.</param>
        public static void SetProperty(DObject /*!*/ instance, string /*!*/ name, object value, ScriptContext /*!*/ context)
        {
            // the property name might encode its visibility and "classification" -> use these
            // information for suitable property desc lookups
            PhpMemberAttributes visibility;
            string type_name;

            string property_name = ParsePropertyName(name, out type_name, out visibility);

            DTypeDesc declarer;

            if (type_name == null)
            {
                declarer = instance.TypeDesc;
            }
            else
            {
                declarer = context.ResolveType(type_name);
                if (declarer == null)
                {
                    declarer = instance.TypeDesc;
                }
            }

            // try to find a suitable field handle
            DPropertyDesc property;

            if (instance.TypeDesc.GetProperty(new VariableName(property_name), declarer, out property) ==
                PHP.Core.Reflection.GetMemberResult.OK)
            {
                if ((property.IsPrivate &&
                     declarer != property.DeclaringType))
                {
                    // if certain conditions are met, don't use the handle even if it was found
                    // (this is to precisely mimic the PHP behavior)
                    property = null;
                }
            }
            else
            {
                property = null;
            }

            if (property != null)
            {
                property.Set(instance, value);
            }
            else
            {
                // 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)
                if (instance.RuntimeFields == null)
                {
                    instance.RuntimeFields = new PhpArray();
                }
                instance.RuntimeFields[name] = value;
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Returns an unitialized instance of the specified type or <see cref="__PHP_Incomplete_Class"/>.
        /// </summary>
        /// <param name="typeName">The type name.</param>
        /// <param name="context">Current <see cref="ScriptContext"/>.</param>
        /// <returns>The newly created instance or <B>null</B> if <paramref name="typeName"/> denotes
        /// a primitive type.</returns>
        /// <remarks>
        /// If the <paramref name="typeName"/> denotes a CLR type, no constructor is executed. If the
        /// <paramref name="typeName"/> denotes a PHP type, no user constructor (e.g. <c>__construct</c>)
        /// is executed.
        /// </remarks>
        public static DObject GetUninitializedInstance(string /*!*/ typeName, ScriptContext /*!*/ context)
        {
            // resolve the specified type
            DTypeDesc type = context.ResolveType(typeName);

            if (type == null || type.IsAbstract)
            {
                PhpCallback callback = context.Config.Variables.DeserializationCallback;
                if (callback != null && !callback.IsInvalid)
                {
                    callback.Invoke(typeName);
                    type = context.ResolveType(typeName);

                    if (type == null || type.IsAbstract)
                    {
                        // unserialize_callback_func failed
                        PhpException.Throw(PhpError.Warning, CoreResources.GetString("unserialize_callback_failed",
                                                                                     ((IPhpConvertible)callback).ToString()));
                    }
                }
            }

            if (type == null || type.IsAbstract)
            {
                // type not found -> create __PHP_Incomplete_Class
                __PHP_Incomplete_Class pic = new __PHP_Incomplete_Class(context, false);
                pic.__PHP_Incomplete_Class_Name.Value = typeName;
                pic.__PHP_Incomplete_Class_Name.IsSet = true;

                return(pic);
            }
            else
            {
                // create the instance
                return(type.New(context) as DObject);
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Searches for type using <see cref="ScriptContext.ResolveType"/>. If the type is found
        /// and has a declarator (is a user type) then the caller is made dependent on it.
        /// </summary>
        /// <returns>The type.</returns>
        public DTypeDesc FindAndProvideType(string name)
        {
            // finds a type - searches in script context and in libraries, may also run __autoload:
            DTypeDesc type = context.ResolveType(name, null, caller, null, ResolveTypeFlags.UseAutoload);

            // if the type is a user type then does provide the type:
            if (type != null && context.DeclaredTypes.ContainsKey(name))
            {
                if (providedTypes == null)
                {
                    providedTypes = new List <ProvidedType>();
                }

                providedTypes.Add(new ProvidedType(name, type));

                Debug.WriteLine("PROVIDER", "Added: {0} ({1})", name, type.RealType.FullName);
            }

            return(type);
        }
Ejemplo n.º 5
0
        public virtual object isSubclassOf(ScriptContext/*!*/context, object @class)
        {
            var classname = PhpVariable.AsString(@class);

            if (!string.IsNullOrEmpty(classname) && this.typedesc != null)
            {
                var dtype = context.ResolveType(classname, null, null, null, ResolveTypeFlags.ThrowErrors | ResolveTypeFlags.UseAutoload);
                return dtype != null && this.typedesc.IsAssignableFrom(dtype);
            }

            return false;
        }
Ejemplo n.º 6
0
		/// <summary>
		/// Sets a property of a <see cref="DObject"/> instance according to deserialized name and value.
		/// </summary>
		/// <param name="instance">The instance being deserialized.</param>
		/// <param name="name">The property name formatted for serialization (see <see cref="FormatPropertyName"/>).</param>
		/// <param name="value">The property value.</param>
		/// <param name="context">Current <see cref="ScriptContext"/>.</param>
		public static void SetProperty(DObject/*!*/ instance, string/*!*/ name, object value, ScriptContext/*!*/ context)
		{
			// the property name might encode its visibility and "classification" -> use these
			// information for suitable property desc lookups
			PhpMemberAttributes visibility;
			string type_name;

			string property_name = ParsePropertyName(name, out type_name, out visibility);

			DTypeDesc declarer;
			if (type_name == null) declarer = instance.TypeDesc;
			else
			{
				declarer = context.ResolveType(type_name);
				if (declarer == null) declarer = instance.TypeDesc;
			}

			// try to find a suitable field handle
			DPropertyDesc property;
			if (instance.TypeDesc.GetProperty(new VariableName(property_name), declarer, out property) ==
				PHP.Core.Reflection.GetMemberResult.OK)
			{
				if ((property.IsPrivate &&
					declarer != property.DeclaringType))
				{
					// if certain conditions are met, don't use the handle even if it was found
					// (this is to precisely mimic the PHP behavior)
					property = null;
				}
			}
			else property = null;

			if (property != null) property.Set(instance, value);
			else
			{
				// 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)
                if (instance.RuntimeFields == null) instance.RuntimeFields = new PhpArray();
				instance.RuntimeFields[name] = value;
			}
		}
Ejemplo n.º 7
0
		/// <summary>
		/// Returns an unitialized instance of the specified type or <see cref="__PHP_Incomplete_Class"/>.
		/// </summary>
		/// <param name="typeName">The type name.</param>
		/// <param name="context">Current <see cref="ScriptContext"/>.</param>
		/// <returns>The newly created instance or <B>null</B> if <paramref name="typeName"/> denotes
		/// a primitive type.</returns>
		/// <remarks>
		/// If the <paramref name="typeName"/> denotes a CLR type, no constructor is executed. If the
		/// <paramref name="typeName"/> denotes a PHP type, no user constructor (e.g. <c>__construct</c>)
		/// is executed.
		/// </remarks>
		public static DObject GetUninitializedInstance(string/*!*/ typeName, ScriptContext/*!*/ context)
		{
			// resolve the specified type
			DTypeDesc type = context.ResolveType(typeName);
			if (type == null || type.IsAbstract)
			{
				PhpCallback callback = context.Config.Variables.DeserializationCallback;
				if (callback != null && !callback.IsInvalid)
				{
					callback.Invoke(typeName);
					type = context.ResolveType(typeName);

					if (type == null || type.IsAbstract)
					{
						// unserialize_callback_func failed
						PhpException.Throw(PhpError.Warning, CoreResources.GetString("unserialize_callback_failed",
							((IPhpConvertible)callback).ToString()));
					}
				}
			}

			if (type == null || type.IsAbstract)
			{
				// type not found -> create __PHP_Incomplete_Class
				__PHP_Incomplete_Class pic = new __PHP_Incomplete_Class(context, false);
				pic.__PHP_Incomplete_Class_Name.Value = typeName;
				pic.__PHP_Incomplete_Class_Name.IsSet = true;

				return pic;
			}
			else
			{
				// create the instance
				return type.New(context) as DObject;
			}
		}
Ejemplo n.º 8
0
		/// <summary>
		/// Returns names and values of properties whose names have been returned by <c>__sleep</c>.
		/// </summary>
		/// <param name="instance">The instance being serialized.</param>
		/// <param name="sleepResult">The array returned by <c>__sleep</c>.</param>
		/// <param name="context">Current <see cref="ScriptContext"/>.</param>
		/// <returns>Name-value pairs. Names are properly formatted for serialization.</returns>
		/// <exception cref="PhpException">Property of the name returned from <c>__sleep</c> does not exist.</exception>
		/// <remarks>
		/// This method returns exactly <paramref name="sleepResult"/>'s <see cref="PhpHashtable.Count"/> items.
		/// </remarks>
		public static IEnumerable<KeyValuePair<string, object>> EnumerateSerializableProperties(
			DObject/*!*/ instance,
			PhpArray/*!*/ sleepResult,
			ScriptContext/*!*/ context)
		{
			foreach (object item in sleepResult.Values)
			{
				PhpMemberAttributes visibility;
				string name = PHP.Core.Convert.ObjectToString(item);
				string declaring_type_name;
				string property_name = ParsePropertyName(name, out declaring_type_name, out visibility);

				DTypeDesc declarer;
				if (declaring_type_name == null) declarer = instance.TypeDesc;
				else
				{
					declarer = context.ResolveType(declaring_type_name);
					if (declarer == null)
					{
						// property name refers to an unknown class -> value will be null
						yield return new KeyValuePair<string, object>(name, null);
						continue;
					}
				}

				// obtain the property desc and decorate the prop name according to its visibility and declaring class
				DPropertyDesc property;
				if (instance.TypeDesc.GetProperty(new VariableName(property_name), declarer, out property) ==
					GetMemberResult.OK && !property.IsStatic)
				{
					if ((Enums.VisibilityEquals(visibility, property.MemberAttributes) &&
						visibility != PhpMemberAttributes.Public)
						||
						(visibility == PhpMemberAttributes.Private &&
						declarer != property.DeclaringType))
					{
						// if certain conditions are met, serialize the property as null
						// (this is to precisely mimic the PHP behavior)
						yield return new KeyValuePair<string, object>(name, null);
						continue;
					}
					name = FormatPropertyName(property, property_name);
				}
				else property = null;

				// obtain the property value
				object val = null;

				if (property != null)
				{
					val = property.Get(instance);
				}
				else if (instance.RuntimeFields == null || !instance.RuntimeFields.TryGetValue(name, out val))
				{
					// this is new in PHP 5.1
					PhpException.Throw(PhpError.Notice, CoreResources.GetString("sleep_returned_bad_field", name));
				}

				yield return new KeyValuePair<string, object>(name, val);
			}
		}
Ejemplo n.º 9
0
		/// <summary>
		/// Converts a class name or class instance to <see cref="DTypeDesc"/> object.
		/// </summary>
		/// <param name="scriptContext">Current <see cref="ScriptContext"/>.</param>
		/// <param name="namingContext">Current <see cref="NamingContext"/>.</param>
        /// <param name="caller">The caller of the method to resolve visible properties properly. Can be UnknownTypeDesc.</param>
        /// <param name="classNameOrObject">The class name or class instance (<see cref="DObject"/>).</param>
		/// <param name="useAutoload"><B>True</B> iff the <c>__autoload</c> magic function should be used.</param>
		/// <returns>The type desc that corresponds to <paramref name="classNameOrObject"/> or <B>null</B>
		/// if the type could not be found or <paramref name="classNameOrObject"/> is neither a string
		/// nor <see cref="DObject"/>.</returns>
		internal static DTypeDesc ClassNameOrObjectToType(ScriptContext/*!*/ scriptContext, NamingContext namingContext,
			DTypeDesc caller, object classNameOrObject, bool useAutoload)
		{
			string class_name = PhpVariable.AsString(classNameOrObject);
			if (class_name != null)
			{
				// lookup the Type
				return scriptContext.ResolveType(class_name, namingContext, caller, null,
					(useAutoload ? ResolveTypeFlags.UseAutoload : ResolveTypeFlags.None));
			}
			else
			{
				DObject obj = classNameOrObject as DObject;
				if (obj != null) return obj.TypeDesc;
			}

			return null;
		}
Ejemplo n.º 10
0
        public virtual object __construct(ScriptContext context, object @class, object methodname)
        {
            string methodnameStr = PhpVariable.AsString(methodname);

            this.dtype = null;
            this.method = null;

            DObject dobj;
            
            if ((dobj = (@class as DObject)) != null)
            {
                this.dtype = dobj.TypeDesc;
            }
            else
            {
                var str = PhpVariable.AsString(@class);
                if (str != null)
                    this.dtype = context.ResolveType(str, null, null, null, ResolveTypeFlags.UseAutoload);

                if (this.dtype == null)
                {
                    PhpException.Throw(PhpError.Error, string.Format("Class {0} does not exist", str));
                    return false;
                }
            }
            
            if (this.dtype.GetMethod(new Name(methodnameStr), dtype, out this.method) == GetMemberResult.NotFound)
            {
                PhpException.Throw(PhpError.Error, string.Format("Method {0}::{1}() does not exist", dtype.MakeFullName(), methodnameStr));  
                return false;
            }

            return null;
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Returns names and values of properties whose names have been returned by <c>__sleep</c>.
        /// </summary>
        /// <param name="instance">The instance being serialized.</param>
        /// <param name="sleepResult">The array returned by <c>__sleep</c>.</param>
        /// <param name="context">Current <see cref="ScriptContext"/>.</param>
        /// <returns>Name-value pairs. Names are properly formatted for serialization.</returns>
        /// <exception cref="PhpException">Property of the name returned from <c>__sleep</c> does not exist.</exception>
        /// <remarks>
        /// This method returns exactly <paramref name="sleepResult"/>'s <see cref="PhpHashtable.Count"/> items.
        /// </remarks>
        public static IEnumerable <KeyValuePair <string, object> > EnumerateSerializableProperties(
            DObject /*!*/ instance,
            PhpArray /*!*/ sleepResult,
            ScriptContext /*!*/ context)
        {
            foreach (object item in sleepResult.Values)
            {
                PhpMemberAttributes visibility;
                string name = PHP.Core.Convert.ObjectToString(item);
                string declaring_type_name;
                string property_name = ParsePropertyName(name, out declaring_type_name, out visibility);

                DTypeDesc declarer;
                if (declaring_type_name == null)
                {
                    declarer = instance.TypeDesc;
                }
                else
                {
                    declarer = context.ResolveType(declaring_type_name);
                    if (declarer == null)
                    {
                        // property name refers to an unknown class -> value will be null
                        yield return(new KeyValuePair <string, object>(name, null));

                        continue;
                    }
                }

                // obtain the property desc and decorate the prop name according to its visibility and declaring class
                DPropertyDesc property;
                if (instance.TypeDesc.GetProperty(new VariableName(property_name), declarer, out property) ==
                    GetMemberResult.OK && !property.IsStatic)
                {
                    if ((Enums.VisibilityEquals(visibility, property.MemberAttributes) &&
                         visibility != PhpMemberAttributes.Public)
                        ||
                        (visibility == PhpMemberAttributes.Private &&
                         declarer != property.DeclaringType))
                    {
                        // if certain conditions are met, serialize the property as null
                        // (this is to precisely mimic the PHP behavior)
                        yield return(new KeyValuePair <string, object>(name, null));

                        continue;
                    }
                    name = FormatPropertyName(property, property_name);
                }
                else
                {
                    property = null;
                }

                // obtain the property value
                object val = null;

                if (property != null)
                {
                    val = property.Get(instance);
                }
                else if (instance.RuntimeFields == null || !instance.RuntimeFields.TryGetValue(name, out val))
                {
                    // this is new in PHP 5.1
                    PhpException.Throw(PhpError.Notice, CoreResources.GetString("sleep_returned_bad_field", name));
                }

                yield return(new KeyValuePair <string, object>(name, val));
            }
        }
Ejemplo n.º 12
0
		/// <summary>
        /// Try to load all <paramref name="providedTypes"/>. This can invoke autoloading if necessary.
        /// Check if they were not modified, so calling compilation unit has to be invalidated and recompiled.
        /// </summary>
		/// <param name="providedTypes">a list of provided type declarators. Can be a <B>null</B> reference.</param>
		/// <param name="target">The script context to be checked.</param>
        /// <param name="caller">Current class context.</param>
		/// <returns><paramref name="providedTypes"/> are loadable and match in context of <paramref name="target"/>.</returns>
        public static bool LoadAndMatch(List<ProvidedType> providedTypes, ScriptContext/*!*/ target, DTypeDesc caller)
		{
			Debug.Assert(target != null);

            if (providedTypes != null && providedTypes.Count > 0)
			{
                //// there is less declarators than we require:
                //if (target.DeclaredTypes.Count < providedTypes.Count) return false;

				// looks up each provided declarator in the target context:
				foreach (ProvidedType declarator in providedTypes)
				{
                    //DTypeDesc decl_type;
                    //target.DeclaredTypes.TryGetValue(declarator.Key, out decl_type);

                    // When class is compiled in runtime, autoload is invoked on base class (if isn't already declared). 
                    // We have to call autoload on the base class also in transient assembly
                    var decl_type = target.ResolveType(declarator.Key, null, caller, null, ResolveTypeFlags.UseAutoload);
                    if (decl_type == null || decl_type.RealType != declarator.Value.RealType)
						return false;
				}
			}

			return true;
		}
Ejemplo n.º 13
0
        public virtual object __construct(ScriptContext context, object @class, object methodname)
        {
            string methodnameStr = PhpVariable.AsString(methodname);

            if (@class == null || string.IsNullOrEmpty(methodnameStr))
                return false;

            this.dtype = null;
            this.method = null;

            DObject dobj;
            string str;

            if ((dobj = (@class as DObject)) != null)
            {
                this.dtype = dobj.TypeDesc;
            }
            else if ((str = PhpVariable.AsString(@class)) != null)
            {
                this.dtype = context.ResolveType(str, null, null, null, ResolveTypeFlags.UseAutoload);
            }

            if (this.dtype == null)
                return false;

            if (this.dtype.GetMethod(new Name(methodnameStr), dtype, out this.method) == GetMemberResult.NotFound)
                return false;

            return null;
        }
Ejemplo n.º 14
0
 /// <summary>
 /// Resolves the <paramref name="typeName"/> and provides corresponding <see cref="DTypeDesc"/> or <c>null</c> reference.
 /// </summary>
 private static DTypeDesc ResolveType(ScriptContext/*!*/context, string typeName)
 {
     return context.ResolveType(typeName, null, null, null, ResolveTypeFlags.ThrowErrors | ResolveTypeFlags.UseAutoload);
 }
Ejemplo n.º 15
0
        /// <summary>
        /// Attempts to bind this callback to its target.
        /// </summary>
        /// <param name="quiet"><B>true</B> of no errors should be thrown, <B>false</B> otherwise.</param>
        /// <param name="nameContext">Current <see cref="NamingContext"/> for function and class name resolution.</param>
        /// <param name="caller">Current class context or a <see cref="UnknownTypeDesc"/> if the class context
        /// should be determined ad-hoc.</param>
        /// <returns><B>True</B> if the callback was successfully bound, <B>false</B> if an error occured.</returns>
        public bool Bind(bool quiet, DTypeDesc caller, NamingContext nameContext)
        {
            if (IsInvalid)
            {
                return(false);
            }

            switch (state)
            {
            case State.UnboundFunction:
            {
                if (context == null)
                {
                    context = ScriptContext.CurrentContext;
                }

                routineDesc = context.ResolveFunction(targetName, nameContext, quiet);
                if (routineDesc == null)
                {
                    return(false);
                }

                state = State.Bound;
                return(true);
            }

            case State.UnboundStaticMethod:
            {
                if (context == null)
                {
                    context = ScriptContext.CurrentContext;
                }

                if (caller != null && caller.IsUnknown)
                {
                    callingContext = PhpStackTrace.GetClassContext();
                }
                else
                {
                    callingContext = caller;
                }

                // try to find the CLR method

                // find the class according to className
                ResolveTypeFlags flags = ResolveTypeFlags.UseAutoload;
                if (!quiet)
                {
                    flags |= ResolveTypeFlags.ThrowErrors;
                }

                DTypeDesc type = context.ResolveType(className, nameContext, callingContext, null, flags);
                if (type == null)
                {
                    return(false);
                }

                // find the method
                bool is_caller_method;
                lateStaticBindType = type;
                routineDesc        = Operators.GetStaticMethodDesc(type, targetName,
                                                                   ref instance, callingContext, context, quiet, false, out is_caller_method);

                if (routineDesc == null)
                {
                    return(false);
                }

                if (instance != null)
                {
                    dummyInstance = true;
                }
                state = is_caller_method ? State.BoundToCaller : State.Bound;
                return(true);
            }

            case State.UnboundInstanceMethod:
            {
                if (caller != null && caller.IsUnknown)
                {
                    callingContext = PhpStackTrace.GetClassContext();
                }
                else
                {
                    callingContext = caller;
                }

                // ask the instance for a handle to the method
                bool is_caller_method;
                routineDesc = instance.GetMethodDesc(targetName, callingContext, quiet, out is_caller_method);
                if (routineDesc == null)
                {
                    return(false);
                }

                state = (is_caller_method ? State.BoundToCaller : State.Bound);
                return(true);
            }
            }
            return(true);
        }
Ejemplo n.º 16
0
        public virtual object __construct(ScriptContext/*!*/context, object/*Traversable*/ iterator, [Optional]object classname)
        {
            this.iterator = iterator as DObject;    // iterator.RealObject is Traversable ?
            if (this.iterator != null)
            {
                if (classname != null && classname != Arg.Default &&
                    !(this.iterator.RealObject is SPL.Iterator)    // downcast only if it is not an Iterator instance
                    )
                {
                    var downcast = context.ResolveType(PhpVariable.AsString(classname), null, this.iterator.TypeDesc, null, ResolveTypeFlags.ThrowErrors);

                    if (downcast == null || // not found
                        !downcast.IsAssignableFrom(this.iterator.TypeDesc) ||    // not base
                        !DTypeDesc.Create(typeof(Traversable)).IsAssignableFrom(downcast))   // not Traversable
                    {
                        // TODO: error
                        // zend_throw_exception(spl_ce_LogicException, "Class to downcast to not found or not base class or does not implement Traversable", 0 TSRMLS_CC);

                        this.iterator = null;
                    }
                    else
                    {
                        //if (DTypeDesc.Create(typeof(IteratorAggregate)).IsAssignableFrom(downcast))
                        //{
                        //    // {downcast} is IteratorAggregate
                        //    context.Stack.AddFrame();
                        //    var result = this.iterator.InvokeMethod("getIterator", null, context);

                        //    if (result == null || !(result is DObject) || !(((DObject)result).RealObject is Traversable))
                        //    {
                        //        //zend_throw_exception_ex(spl_ce_LogicException, 0 TSRMLS_CC, "%s::getIterator() must return an object that implements Traversable", ce->name);
                        //        this.iterator = null;
                        //    }
                        //    else
                        //    {
                        //        this.iterator = (DObject)result;
                        //    }
                        //}
                        throw new NotImplementedException();
                    }
                }
            }
            else
            {
                // TODO: error
            }

            //rewind(context);  // not in PHP, performance reasons (foreach causes rewind() itself)

            return null;
        }
Ejemplo n.º 17
0
        public virtual object __construct(ScriptContext context, object @class, object propertyname)
        {
            string propertynameStr = PhpVariable.AsString(propertyname);

            if (@class == null || string.IsNullOrEmpty(propertynameStr))
                return false;

            this.dtype = null;
            this.property = null;

            DObject dobj;
            string str;

            if ((dobj = (@class as DObject)) != null)
            {
                this.dtype = dobj.TypeDesc;
            }
            else if ((str = PhpVariable.AsString(@class)) != null)
            {
                this.dtype = context.ResolveType(str, null, null, null, ResolveTypeFlags.UseAutoload);
            }

            if (this.dtype == null)
                return false;

            if (this.dtype.GetProperty(new VariableName(propertynameStr), dtype, out this.property) == GetMemberResult.NotFound)
            {
                object runtimeValue;
                if (dobj != null && dobj.RuntimeFields != null && dobj.RuntimeFields.TryGetValue(propertynameStr, out runtimeValue))
                {
                    // create desc of runtime field:
                    this.property = new RuntimePhpProperty(dtype,
                        (instance) => ((DObject)instance).GetRuntimeField(this.name, null),
                        (instance, value) => ((DObject)instance).SetRuntimeField(this.name, value, null, null, null));
                    this.property.Member = new KnownRuntimeProperty(this.property, propertynameStr);
                }
                else
                {
                    return false;
                }
            }

            return null;
        }