Variant f_get_parent_class(CVarRef object /* = null_variant */) { if (hhvm) { if (!object.isInitialized()) { CallerFrame cf; HPHP::VM::Class* cls = arGetContextClass(cf()); if (cls && cls->parent()) { return CStrRef(cls->parentRef()); } return false; } } Variant class_name; if (object.isObject()) { class_name = f_get_class(object); } else if (object.isString()) { class_name = object; } else { return false; } const ClassInfo *classInfo = ClassInfo::FindClass(class_name.toString()); if (classInfo) { CStrRef parentClass = classInfo->getParentClass(); if (!parentClass.empty()) { return parentClass; } } return false; }
Array vm_get_class_vars(CStrRef className) { HPHP::VM::Class* cls = HPHP::VM::Unit::lookupClass(className.get()); if (cls == NULL) { raise_error("Unknown class %s", className->data()); } cls->initialize(); const VM::Class::SProp* sPropInfo = cls->staticProperties(); const size_t numSProps = cls->numStaticProperties(); const VM::Class::Prop* propInfo = cls->declProperties(); const size_t numDeclProps = cls->numDeclProperties(); // The class' instance property initialization template is in different // places, depending on whether it has any request-dependent initializers // (i.e. constants) const VM::Class::PropInitVec& declPropInitVec = cls->declPropInit(); const VM::Class::PropInitVec* propVals = !cls->pinitVec().empty() ? cls->getPropData() : &declPropInitVec; ASSERT(propVals != NULL); ASSERT(propVals->size() == numDeclProps); // For visibility checks CallerFrame cf; HPHP::VM::Class* ctx = arGetContextClass(cf()); HphpArray* ret = NEW(HphpArray)(numDeclProps + numSProps); for (size_t i = 0; i < numDeclProps; ++i) { StringData* name = const_cast<StringData*>(propInfo[i].m_name); // Empty names are used for invisible/private parent properties; skip them ASSERT(name->size() != 0); if (VM::Class::IsPropAccessible(propInfo[i], ctx)) { const TypedValue* value = &((*propVals)[i]); ret->nvSet(name, value, false); } } for (size_t i = 0; i < numSProps; ++i) { bool vis, access; TypedValue* value = cls->getSProp(ctx, sPropInfo[i].m_name, vis, access); if (access) { ret->nvSet(const_cast<StringData*>(sPropInfo[i].m_name), value, false); } } return ret; }
Array vm_get_class_constants(CStrRef className) { HPHP::VM::Class* cls = HPHP::VM::Unit::lookupClass(className.get()); if (cls == NULL) { return NEW(HphpArray)(0); } size_t numConstants = cls->numConstants(); HphpArray* retVal = NEW(HphpArray)(numConstants); const VM::Class::Const* consts = cls->constants(); for (size_t i = 0; i < numConstants; i++) { // Note: hphpc doesn't include inherited constants in // get_class_constants(), so mimic that behavior if (consts[i].m_class == cls) { StringData* name = const_cast<StringData*>(consts[i].m_name); TypedValue* value = cls->clsCnsGet(consts[i].m_name); retVal->nvSet(name, value, false); } } return retVal; }
Variant f_get_class(CVarRef object /* = null_variant */) { if (object.isNull()) { // No arg passed. String ret; if (hhvm) { CallerFrame cf; HPHP::VM::Class* cls = HPHP::VM::arGetContextClassImpl<true>(cf()); if (cls) { ret = CStrRef(cls->nameRef()); } } else { ret = FrameInjection::GetClassName(true); } if (ret.empty()) { raise_warning("get_class() called without object from outside a class"); return false; } return ret; } if (!object.isObject()) return false; return object.toObject()->o_getClassName(); }
bool eval_get_class_constant_hook(Variant &res, CStrRef s, const char* constant) { if (hhvm) { String clsName(s, strlen(s), CopyString); HPHP::VM::Class* cls = HPHP::VM::Unit::lookupClass(clsName.get()); if (cls && !cls->clsInfo()) { String cnsName(constant, strlen(constant), CopyString); TypedValue* tv = cls->clsCnsGet(cnsName.get()); if (tv) { res = tvAsCVarRef(tv); return true; } } } else { const Eval::ClassStatement* cls = Eval::RequestEvalState::findClass(s, true); if (cls) { return cls->getConstant(res, constant, true); } } return false; }