Variant invoke_failed(CVarRef func, CArrRef params, bool fatal /* = true */) { if (func.isObject()) { return o_invoke_failed( func.objectForCall()->o_getClassName().c_str(), "__invoke", fatal); } else { return invoke_failed(func.toString().c_str(), params, fatal); } }
bool f_is_callable(CVarRef v, bool syntax /* = false */, VRefParam name /* = null */) { if (v.isString()) { if (name.isReferenced()) name = v; if (syntax) return true; String str = v.toString(); int c = str.find("::"); if (c != 0 && c != String::npos && c + 2 < str.size()) { String classname = str.substr(0, c); String methodname = str.substr(c + 2); return f_class_exists(classname) && ClassInfo::HasAccess(classname, methodname, true, false); } return f_function_exists(str); } if (v.is(KindOfArray)) { Array arr = v.toArray(); if (arr.size() == 2 && arr.exists(0LL) && arr.exists(1LL)) { Variant v0 = arr.rvalAt(0LL); Variant v1 = arr.rvalAt(1LL); Object obj; bool staticCall = false; if (v0.is(KindOfObject)) { obj = v0.toObject(); v0 = obj->o_getClassName(); } else if (v0.isString()) { if (!f_class_exists(v0.toString())) { return false; } staticCall = true; } if (v1.isString()) { String str = v1.toString(); int c = str.find("::"); if (c != 0 && c != String::npos && c + 2 < str.size()) { String name1 = v0.toString(); String name2 = str.substr(0, c); ASSERT(name1.get() && name2.get()); if (name1->isame(name2.get()) || ClassInfo::IsSubClass(name1, name2, false)) { staticCall = true; v0 = name2; v1 = str.substr(c + 2); } } } if (v0.isString() && v1.isString()) { if (name.isReferenced()) { name = v0.toString() + "::" + v1.toString(); } if (same(v0, s_self) || same(v0, s_parent)) { throw NotImplementedException("augmenting class scope info"); } return ClassInfo::HasAccess(v0, v1, staticCall, !obj.isNull()); } } } if (v.isObject()) { ObjectData *d = v.objectForCall(); if (name.isReferenced()) { name = d->o_getClassName() + "::__invoke"; } void *extra; const CallInfo *cit = d->t___invokeCallInfoHelper(extra); return cit != NULL; } if (name.isReferenced()) { name = v.toString(); } return false; }