const IniSettingMap ini_iterate(const IniSettingMap &ini, const std::string &name) { // This should never happen, but handle it anyway. if (ini.isNull()) { return init_null(); } // If for some reason we are passed a string (i.e., a leaf value), // just return it back if (ini.isString()) { return ini; } // If we just passed in a name that already has a value like: // hhvm.server.apc.ttl_limit // max_execution_time // then we just return the value now. // i.e., a value that didn't look like // hhvm.a.b[c][d], where name = hhvm.a.b.c.d // c[d] (where ini is already hhvm.a.b), where name = c.d auto value = ini[name]; if (!value.isNull()) { return value; } // Otherwise, we split on the dots (if any) to see if we can get a real value std::vector<std::string> dot_parts; folly::split('.', name, dot_parts); int dot_loc = 0; int dot_parts_size = dot_parts.size(); std::string part = dot_parts[0]; value = ini[part]; // Loop through the dot parts, getting a pointer to each // We may need to concatenate dots to be able to get a real value // e.g., if someone passed in hhvm.a.b.c.d, which in ini was equal // to hhvm.a.b[c][d], then we would start with hhvm and get null, // then hhvm.a and get null, then hhvm.a.b and actually get an object // to point to. while (value.isNull() && dot_loc < dot_parts_size - 1) { dot_loc++; part = part + "." + dot_parts[dot_loc]; value = ini[part]; } // Get to the last dot part and get its value, if it exists for (int i = dot_loc + 1; i < dot_parts_size; i++) { if (!value.isNull()) { part = dot_parts[i]; value = value[part]; } else { // If we reach a bad point, just return null return init_null(); } } return value; }
// Hdf takes precedence, as usual. No `ini` binding yet. void Config::Iterate(const IniSettingMap &ini, const Hdf &hdf, std::function<void (const IniSettingMap&, const Hdf&)> cb) { if (hdf.exists()) { for (Hdf c = hdf.firstChild(); c.exists(); c = c.next()) { cb(ini, c); } } else { auto ini_name = IniName(hdf); auto* ini_value = ini.get_ptr(ini_name); if (ini_value && ini_value->isObject()) { for (auto& val : ini_value->values()) { cb(val, hdf); } } } }
void Config::Bind(std::vector<std::string>& loc, const IniSettingMap& ini, const Hdf& config) { std::vector<std::string> ret; auto ini_name = IniName(config); auto* value = ini.get_ptr(ini_name); if (value && value->isObject()) { ini_on_update(*value, ret); loc = ret; } // If there is an HDF setting for the config, then it still wins for // the RuntimeOption value until we obliterate HDFs ret.clear(); config.configGet(ret); if (ret.size() > 0) { loc = ret; } IniSetting::Bind(IniSetting::CORE, IniSetting::PHP_INI_SYSTEM, ini_name, &loc); }
void Config::SetParsedIni(IniSettingMap &ini, const std::string confStr, const std::string &filename, bool constants_only, bool is_system) { // if we are setting constants, we must be setting system settings if (constants_only) { assertx(is_system); } auto parsed_ini = IniSetting::FromStringAsMap(confStr, filename); for (ArrayIter iter(parsed_ini.toArray()); iter; ++iter) { // most likely a string, but just make sure that we are dealing // with something that can be converted to a string assertx(iter.first().isScalar()); ini.set(iter.first().toString(), iter.second()); if (constants_only) { IniSetting::FillInConstant(iter.first().toString().toCppString(), iter.second()); } else if (is_system) { IniSetting::SetSystem(iter.first().toString().toCppString(), iter.second()); } } }