Exemple #1
0
        public static bool IsA(DTypeDesc caller, object obj, string className)
        {
            if (obj == null || !(obj is DObject))
            {
                return(false);
            }

            DObject   dobj = (DObject)obj;
            DTypeDesc type = ScriptContext.CurrentContext.ResolveType(className, null, caller, null, ResolveTypeFlags.None);    // do not call autoload [workitem:26664]

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

            return(type.IsAssignableFrom(dobj.TypeDesc));
        }
Exemple #2
0
        /// <summary>
        /// Attemps to find a method desc according to a given class name and method name. Used when
        /// a non-virtual dispatch is about to be performed and when a <c>array(class, method)</c>
        /// callback is being bound.
        /// </summary>
        /// <param name="requestedType">The type whose method should be returned.</param>
        /// <param name="methodName">The method name.</param>
        /// <param name="self">Current <c>$this</c>. Will be set to an instance, on which the resulting
        /// CLR method should be invoked (<B>null</B> if the CLR method is static).</param>
        /// <param name="caller"><see cref="Type"/> of the object that request the lookup.</param>
        /// <param name="context">Current <see cref="ScriptContext"/>.</param>
        /// <param name="quiet">If <B>true</B>, no exceptions will be thrown if an error occurs.</param>
        /// <param name="removeFrame">If <B>true</B>, <see cref="PhpStack.RemoveFrame"/> will be called
        /// before throwing an exception.</param>
        /// <param name="isCallerMethod">Will be set to true, if required method was not found but __callStatic was.</param>
        /// <returns>The <see cref="DRoutineDesc"/> or <B>null</B> on error.</returns>
        internal static DRoutineDesc GetStaticMethodDesc(DTypeDesc requestedType, string methodName, ref DObject self,
            DTypeDesc caller, ScriptContext context, bool quiet, bool removeFrame, out bool isCallerMethod)
        {
            Debug.Assert(requestedType != null);

            isCallerMethod = false;

            DRoutineDesc method;
            GetMemberResult result = requestedType.GetMethod(new Name(methodName), caller, out method);

            if (result == GetMemberResult.NotFound)
            {
                // if not found, perform __callStatic or __call 'magic' method lookup
                Name callMethod = (self != null && requestedType.IsAssignableFrom(self.TypeDesc)) ?
                    Name.SpecialMethodNames.Call : Name.SpecialMethodNames.CallStatic;

                if ((result = requestedType.GetMethod(callMethod, caller, out method)) != GetMemberResult.NotFound)
                {
                    isCallerMethod = true;
                }
                else
                {
                    // there is no such method in the class
                    if (removeFrame) context.Stack.RemoveFrame();
                    if (!quiet) PhpException.UndefinedMethodCalled(requestedType.MakeFullName(), methodName);

                    return null;
                }
            }

            if (result == GetMemberResult.BadVisibility)
            {
                if (removeFrame) context.Stack.RemoveFrame();
                if (!quiet)
                {
                    PhpException.MethodNotAccessible(
                        method.DeclaringType.MakeFullName(),
                        method.MakeFullName(),
                        (caller == null ? String.Empty : caller.MakeFullName()),
                        method.IsProtected);
                }
                return null;
            }

            // check whether the method is abstract
            if (method.IsAbstract)
            {
                if (removeFrame) context.Stack.RemoveFrame();
                if (!quiet) PhpException.AbstractMethodCalled(method.DeclaringType.MakeFullName(), method.MakeFullName());

                return null;
            }

            if (method.IsStatic)
            {
                self = null;
            }
            else
            {
                // check whether self is of acceptable type
                if (self != null && !method.DeclaringType.RealType.IsInstanceOfType(self.RealObject)) self = null;


                /*
                // PHP allows for static invocations of instance method
				if (self == null &&
					(requestedType.IsAbstract || !(requestedType is PhpTypeDesc)) &&
					(method.DeclaringType.IsAbstract || !(method.DeclaringType is PhpTypeDesc)))
				{
					// calling instance methods declared in abstract classes statically through abstract classes
					// is unsupported -  passing null as 'this' to such instance method could result in
					// NullReferenceException even if the method does not touch $this
					if (removeFrame) context.Stack.RemoveFrame();
					if (!quiet)
					{
						PhpException.Throw(PhpError.Error, CoreResources.GetString("nonstatic_method_called_statically",
							method.DeclaringType.MakeFullName(), method.MakeFullName()));
					}
					return null;
				}

				if (self == null)
				{
                    if (!quiet && !context.Config.Variables.ZendEngineV1Compatible)
                    {
                        PhpException.Throw(PhpError.Strict, CoreResources.GetString("nonstatic_method_called_statically",
                            method.DeclaringType.MakeFullName(), method.MakeFullName()));
                    }

					// create a dummy instance to be passed as 'this' to the instance method
					DTypeDesc dummy_type =
						(!requestedType.IsAbstract && requestedType is PhpTypeDesc) ? requestedType : method.DeclaringType;

					self = PhpFunctionUtils.InvokeConstructor(
                        dummy_type,
                        //Emit.Types.ScriptContext_Bool,
                        context, false);
				}*/


                //
                // The code above was commented and replaced with following.
                //
                // We can call instance method, and pass null as 'this', and expect
                // it can fail with NullReferenceException (even if the method does not touch $this).
                // 
                // Note this solution has no side effect as above - invoking constructor of dummy instance.
                //

                // !! self can be null !!

                if (self == null)
                {
                    if (!quiet /*&& !context.Config.Variables.ZendEngineV1Compatible*/)
                    {
                        PhpException.Throw(PhpError.Strict, CoreResources.GetString("nonstatic_method_called_statically",
                            method.DeclaringType.MakeFullName(), method.MakeFullName()));
                    }
                }

            }

            return method;
        }