Example #1
0
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;
}