diff options
Diffstat (limited to 'Sluift/ElementConvertors/FormConvertor.cpp')
-rw-r--r-- | Sluift/ElementConvertors/FormConvertor.cpp | 670 |
1 files changed, 334 insertions, 336 deletions
diff --git a/Sluift/ElementConvertors/FormConvertor.cpp b/Sluift/ElementConvertors/FormConvertor.cpp index e44ca3e..245e0f9 100644 --- a/Sluift/ElementConvertors/FormConvertor.cpp +++ b/Sluift/ElementConvertors/FormConvertor.cpp @@ -1,345 +1,343 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/FormConvertor.h> -#include <lua.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> +#include <sstream> + +#include <boost/assign/list_of.hpp> #include <boost/numeric/conversion/cast.hpp> + +#include <lua.hpp> + #include <Sluift/Lua/Check.h> #include <Sluift/Lua/Value.h> -#include <Swiften/Base/foreach.h> -#include <boost/assign/list_of.hpp> -#include <sstream> using namespace Swift; namespace { - int formIndex(lua_State* L) { - lua_getfield(L, 1, "fields"); - if (lua_type(L, -1) != LUA_TTABLE) { - return 0; - } - int index = Lua::absoluteOffset(L, -1); - lua_pushnil(L); - for (lua_pushnil(L); lua_next(L, index) != 0; ) { - lua_getfield(L, -1, "name"); - if (lua_equal(L, -1, 2)) { - lua_pop(L, 1); - return 1; - } - lua_pop(L, 2); - } - return 0; - } - - int formNewIndex(lua_State* L) { - lua_getfield(L, 1, "fields"); - bool foundField = false; - if (lua_type(L, -1) == LUA_TTABLE) { - for (lua_pushnil(L); lua_next(L, -2) != 0; ) { - lua_getfield(L, -1, "name"); - if (lua_equal(L, -1, 2)) { - lua_pushvalue(L, 3); - lua_setfield(L, -3, "value"); - foundField = true; - lua_pop(L, 3); - break; - } - lua_pop(L, 2); - } - } - lua_pop(L, 1); - - if (!foundField) { - lua_pushvalue(L, 2); - lua_pushvalue(L, 3); - lua_rawset(L, 1); - } - return 0; - } - - Lua::Table convertFieldToLua(boost::shared_ptr<FormField> field) { - Lua::Table luaField = boost::assign::map_list_of("name", Lua::valueRef(field->getName())); - std::string type; - switch (field->getType()) { - case FormField::UnknownType: type = ""; break; - case FormField::BooleanType: type = "boolean"; break; - case FormField::FixedType: type = "fixed"; break; - case FormField::HiddenType: type = "hidden"; break; - case FormField::ListSingleType: type = "list-single"; break; - case FormField::TextMultiType: type = "text-multi"; break; - case FormField::TextPrivateType: type = "text-private"; break; - case FormField::TextSingleType: type = "text-single"; break; - case FormField::JIDSingleType: type = "jid-single"; break; - case FormField::JIDMultiType: type = "jid-multi"; break; - case FormField::ListMultiType: type = "list-multi"; break; - } - if (!type.empty()) { - luaField["type"] = Lua::valueRef(type); - } - if (!field->getLabel().empty()) { - luaField["label"] = Lua::valueRef(field->getLabel()); - } - if (field->getRequired()) { - luaField["required"] = Lua::boolRef(field->getRequired()); - } - if (!field->getDescription().empty()) { - luaField["description"] = Lua::valueRef(field->getDescription()); - } - - if (field->getType() == FormField::ListMultiType || field->getType() == FormField::JIDMultiType || field->getType() == FormField::TextMultiType) { - luaField["values"] = Lua::valueRef(Lua::Array(field->getValues().begin(), field->getValues().end())); - } - else if (field->getType() == FormField::BooleanType) { - luaField["value"] = Lua::boolRef(field->getBoolValue()); - } - else if (!field->getValues().empty()) { - luaField["value"] = Lua::valueRef(field->getValues()[0]); - } - - if (!field->getOptions().empty()) { - Lua::Array options; - foreach(const FormField::Option& option, field->getOptions()) { - Lua::Table luaOption = boost::assign::map_list_of - ("label", Lua::valueRef(option.label)) - ("value", Lua::valueRef(option.value)); - options.push_back(luaOption); - } - luaField["options"] = valueRef(options); - } - return luaField; - } - - Lua::Array convertFieldListToLua(const std::vector< boost::shared_ptr<FormField> >& fieldList) { - Lua::Array fields; - foreach(boost::shared_ptr<FormField> field, fieldList) { - fields.push_back(convertFieldToLua(field)); - } - return fields; - } - - - boost::shared_ptr<FormField> convertFieldFromLua(lua_State* L) { - boost::shared_ptr<FormField> result = boost::make_shared<FormField>(); - FormField::Type fieldType = FormField::UnknownType; - boost::optional<std::string> type = Lua::getStringField(L, -1, "type"); - if (type) { - if (*type == "boolean") { - fieldType = FormField::BooleanType; - } - if (*type == "fixed") { - fieldType = FormField::FixedType; - } - if (*type == "hidden") { - fieldType = FormField::HiddenType; - } - if (*type == "list-single") { - fieldType = FormField::ListSingleType; - } - if (*type == "text-multi") { - fieldType = FormField::TextMultiType; - } - if (*type == "text-private") { - fieldType = FormField::TextPrivateType; - } - if (*type == "text-single") { - fieldType = FormField::TextSingleType; - } - if (*type == "jid-single") { - fieldType = FormField::JIDSingleType; - } - if (*type == "jid-multi") { - fieldType = FormField::JIDMultiType; - } - if (*type == "list-multi") { - fieldType = FormField::ListMultiType; - } - } - result->setType(fieldType); - if (boost::optional<std::string> name = Lua::getStringField(L, -1, "name")) { - result->setName(*name); - } - if (boost::optional<std::string> description = Lua::getStringField(L, -1, "description")) { - result->setDescription(*description); - } - if (boost::optional<std::string> label = Lua::getStringField(L, -1, "label")) { - result->setLabel(*label); - } - if (boost::optional<bool> required = Lua::getBooleanField(L, -1, "required")) { - result->setRequired(*required); - } - if (boost::optional<std::string> value = Lua::getStringField(L, -1, "value")) { - result->addValue(*value); - } - else if (boost::optional<bool> value = Lua::getBooleanField(L, -1, "value")) { - result->setBoolValue(*value); - } - else { - lua_getfield(L, -1, "values"); - if (lua_istable(L, -1)) { - for (lua_pushnil(L); lua_next(L, -2); ) { - if (lua_isstring(L, -1)) { - result->addValue(lua_tostring(L, -1)); - } - lua_pop(L, 1); - } - } - lua_pop(L, 1); - } - lua_getfield(L, -1, "options"); - if (lua_istable(L, -1)) { - for (lua_pushnil(L); lua_next(L, -2); ) { - if (lua_istable(L, -1)) { - FormField::Option option("", ""); - if (boost::optional<std::string> value = Lua::getStringField(L, -1, "value")) { - option.value = *value; - } - if (boost::optional<std::string> label = Lua::getStringField(L, -1, "label")) { - option.label = *label; - } - result->addOption(option); - } - lua_pop(L, 1); - } - } - lua_pop(L, 1); - return result; - } - - std::vector< boost::shared_ptr<FormField> > convertFieldListFromLua(lua_State* L) { - std::vector< boost::shared_ptr<FormField> > result; - for (lua_pushnil(L); lua_next(L, -2);) { - result.push_back(convertFieldFromLua(L)); - lua_pop(L, 1); - } - return result; - } - - boost::shared_ptr<Form> convertFormFromLua(lua_State* L) { - boost::shared_ptr<Form> result = boost::make_shared<Form>(); - if (boost::optional<std::string> title = Lua::getStringField(L, -1, "title")) { - result->setTitle(*title); - } - if (boost::optional<std::string> instructions = Lua::getStringField(L, -1, "instructions")) { - result->setInstructions(*instructions); - } - if (boost::optional<std::string> type = Lua::getStringField(L, -1, "type")) { - Form::Type formType = Form::FormType; - if (*type == "submit") { - formType = Form::SubmitType; - } - else if (*type == "cancel") { - formType = Form::CancelType; - } - else if (*type == "result") { - formType = Form::ResultType; - } - result->setType(formType); - } - - lua_getfield(L, -1, "fields"); - if (lua_istable(L, -1)) { - foreach (boost::shared_ptr<FormField> formField, convertFieldListFromLua(L)) { - result->addField(formField); - } - } - lua_pop(L, 1); - - lua_getfield(L, -1, "reported_fields"); - if (lua_istable(L, -1)) { - foreach (boost::shared_ptr<FormField> formField, convertFieldListFromLua(L)) { - result->addReportedField(formField); - } - } - lua_pop(L, 1); - - lua_getfield(L, -1, "items"); - if (lua_istable(L, -1)) { - for (lua_pushnil(L); lua_next(L, -2);) { - result->addItem(convertFieldListFromLua(L)); - lua_pop(L, 1); - } - } - lua_pop(L, 1); - - return result; - } - - void convertFormToLua(lua_State* L, boost::shared_ptr<Form> payload) { - std::string type; - switch (payload->getType()) { - case Form::FormType: type = "form"; break; - case Form::SubmitType: type = "submit"; break; - case Form::CancelType: type = "cancel"; break; - case Form::ResultType: type = "result"; break; - } - - Lua::Table result = boost::assign::map_list_of("type", Lua::valueRef(type)); - if (!payload->getTitle().empty()) { - result["title"] = Lua::valueRef(payload->getTitle()); - } - if (!payload->getInstructions().empty()) { - result["instructions"] = Lua::valueRef(payload->getInstructions()); - } - if (!payload->getFields().empty()) { - result["fields"] = valueRef(convertFieldListToLua(payload->getFields())); - } - if (!payload->getReportedFields().empty()) { - result["reported_fields"] = valueRef(convertFieldListToLua(payload->getReportedFields())); - } - - if (!payload->getItems().empty()) { - Lua::Array luaItems; - foreach(const Form::FormItem& item, payload->getItems()) { - if (!item.empty()) { - luaItems.push_back(convertFieldListToLua(item)); - } - } - result["items"] = valueRef(luaItems); - } - - Lua::pushValue(L, result); - - lua_newtable(L); - lua_pushcfunction(L, formIndex); - lua_setfield(L, -2, "__index"); - lua_pushcfunction(L, formNewIndex); - lua_setfield(L, -2, "__newindex"); - lua_setmetatable(L, -2); - } - - int createSubmission(lua_State* L) { - boost::shared_ptr<Form> form = convertFormFromLua(L); - - // Remove all redundant elements - form->setInstructions(""); - form->setTitle(""); - form->clearItems(); - form->clearReportedFields(); - std::vector< boost::shared_ptr<FormField> > fields(form->getFields()); - form->clearFields(); - foreach (boost::shared_ptr<FormField> field, fields) { - if (field->getType() == FormField::FixedType) { - continue; - } - field->clearOptions(); - field->setLabel(""); - field->setType(FormField::UnknownType); - field->setDescription(""); - form->addField(field); - } - form->setType(Form::SubmitType); - - // Convert back - convertFormToLua(L, form); - Lua::registerTableToString(L, -1); - - return 1; - } + int formIndex(lua_State* L) { + lua_getfield(L, 1, "fields"); + if (lua_type(L, -1) != LUA_TTABLE) { + return 0; + } + int index = Lua::absoluteOffset(L, -1); + lua_pushnil(L); + for (lua_pushnil(L); lua_next(L, index) != 0; ) { + lua_getfield(L, -1, "name"); + if (lua_compare(L, -1, 2, LUA_OPEQ)) { + lua_pop(L, 1); + return 1; + } + lua_pop(L, 2); + } + return 0; + } + + int formNewIndex(lua_State* L) { + lua_getfield(L, 1, "fields"); + bool foundField = false; + if (lua_type(L, -1) == LUA_TTABLE) { + for (lua_pushnil(L); lua_next(L, -2) != 0; ) { + lua_getfield(L, -1, "name"); + if (lua_compare(L, -1, 2, LUA_OPEQ)) { + lua_pushvalue(L, 3); + lua_setfield(L, -3, "value"); + foundField = true; + lua_pop(L, 3); + break; + } + lua_pop(L, 2); + } + } + lua_pop(L, 1); + + if (!foundField) { + lua_pushvalue(L, 2); + lua_pushvalue(L, 3); + lua_rawset(L, 1); + } + return 0; + } + + Lua::Table convertFieldToLua(std::shared_ptr<FormField> field) { + Lua::Table luaField = boost::assign::map_list_of("name", Lua::valueRef(field->getName())); + std::string type; + switch (field->getType()) { + case FormField::UnknownType: type = ""; break; + case FormField::BooleanType: type = "boolean"; break; + case FormField::FixedType: type = "fixed"; break; + case FormField::HiddenType: type = "hidden"; break; + case FormField::ListSingleType: type = "list-single"; break; + case FormField::TextMultiType: type = "text-multi"; break; + case FormField::TextPrivateType: type = "text-private"; break; + case FormField::TextSingleType: type = "text-single"; break; + case FormField::JIDSingleType: type = "jid-single"; break; + case FormField::JIDMultiType: type = "jid-multi"; break; + case FormField::ListMultiType: type = "list-multi"; break; + } + if (!type.empty()) { + luaField["type"] = Lua::valueRef(type); + } + if (!field->getLabel().empty()) { + luaField["label"] = Lua::valueRef(field->getLabel()); + } + if (field->getRequired()) { + luaField["required"] = Lua::boolRef(field->getRequired()); + } + if (!field->getDescription().empty()) { + luaField["description"] = Lua::valueRef(field->getDescription()); + } + if (field->getType() == FormField::BooleanType) { + luaField["value"] = Lua::boolRef(field->getBoolValue()); + } + else if (field->getValues().size() > 1) { + luaField["value"] = Lua::valueRef(Lua::Array(field->getValues().begin(), field->getValues().end())); + } + else if (field->getValues().size() == 1) { + luaField["value"] = Lua::valueRef(field->getValues()[0]); + } + if (!field->getOptions().empty()) { + Lua::Array options; + for (const auto& option : field->getOptions()) { + Lua::Table luaOption = boost::assign::map_list_of + ("label", Lua::valueRef(option.label)) + ("value", Lua::valueRef(option.value)); + options.push_back(luaOption); + } + luaField["options"] = valueRef(options); + } + return luaField; + } + + Lua::Array convertFieldListToLua(const std::vector< std::shared_ptr<FormField> >& fieldList) { + Lua::Array fields; + for (auto&& field : fieldList) { + fields.push_back(convertFieldToLua(field)); + } + return fields; + } + + + std::shared_ptr<FormField> convertFieldFromLua(lua_State* L) { + std::shared_ptr<FormField> result = std::make_shared<FormField>(); + FormField::Type fieldType = FormField::UnknownType; + boost::optional<std::string> type = Lua::getStringField(L, -1, "type"); + if (type) { + if (*type == "boolean") { + fieldType = FormField::BooleanType; + } + if (*type == "fixed") { + fieldType = FormField::FixedType; + } + if (*type == "hidden") { + fieldType = FormField::HiddenType; + } + if (*type == "list-single") { + fieldType = FormField::ListSingleType; + } + if (*type == "text-multi") { + fieldType = FormField::TextMultiType; + } + if (*type == "text-private") { + fieldType = FormField::TextPrivateType; + } + if (*type == "text-single") { + fieldType = FormField::TextSingleType; + } + if (*type == "jid-single") { + fieldType = FormField::JIDSingleType; + } + if (*type == "jid-multi") { + fieldType = FormField::JIDMultiType; + } + if (*type == "list-multi") { + fieldType = FormField::ListMultiType; + } + } + result->setType(fieldType); + if (boost::optional<std::string> name = Lua::getStringField(L, -1, "name")) { + result->setName(*name); + } + if (boost::optional<std::string> description = Lua::getStringField(L, -1, "description")) { + result->setDescription(*description); + } + if (boost::optional<std::string> label = Lua::getStringField(L, -1, "label")) { + result->setLabel(*label); + } + if (boost::optional<bool> required = Lua::getBooleanField(L, -1, "required")) { + result->setRequired(*required); + } + if (boost::optional<std::string> value = Lua::getStringField(L, -1, "value")) { + result->addValue(*value); + } + else if (boost::optional<bool> value = Lua::getBooleanField(L, -1, "value")) { + result->setBoolValue(*value); + } + else { + lua_getfield(L, -1, "value"); + if (lua_istable(L, -1)) { + for (lua_pushnil(L); lua_next(L, -2); ) { + if (lua_isstring(L, -1)) { + result->addValue(lua_tostring(L, -1)); + } + lua_pop(L, 1); + } + } + lua_pop(L, 1); + } + lua_getfield(L, -1, "options"); + if (lua_istable(L, -1)) { + for (lua_pushnil(L); lua_next(L, -2); ) { + if (lua_istable(L, -1)) { + FormField::Option option("", ""); + if (boost::optional<std::string> value = Lua::getStringField(L, -1, "value")) { + option.value = *value; + } + if (boost::optional<std::string> label = Lua::getStringField(L, -1, "label")) { + option.label = *label; + } + result->addOption(option); + } + lua_pop(L, 1); + } + } + lua_pop(L, 1); + return result; + } + + std::vector< std::shared_ptr<FormField> > convertFieldListFromLua(lua_State* L) { + std::vector< std::shared_ptr<FormField> > result; + for (lua_pushnil(L); lua_next(L, -2);) { + result.push_back(convertFieldFromLua(L)); + lua_pop(L, 1); + } + return result; + } + + std::shared_ptr<Form> convertFormFromLua(lua_State* L) { + std::shared_ptr<Form> result = std::make_shared<Form>(); + if (boost::optional<std::string> title = Lua::getStringField(L, -1, "title")) { + result->setTitle(*title); + } + if (boost::optional<std::string> instructions = Lua::getStringField(L, -1, "instructions")) { + result->setInstructions(*instructions); + } + if (boost::optional<std::string> type = Lua::getStringField(L, -1, "type")) { + Form::Type formType = Form::FormType; + if (*type == "submit") { + formType = Form::SubmitType; + } + else if (*type == "cancel") { + formType = Form::CancelType; + } + else if (*type == "result") { + formType = Form::ResultType; + } + result->setType(formType); + } + + lua_getfield(L, -1, "fields"); + if (lua_istable(L, -1)) { + for (auto&& formField : convertFieldListFromLua(L)) { + result->addField(formField); + } + } + lua_pop(L, 1); + + lua_getfield(L, -1, "reported_fields"); + if (lua_istable(L, -1)) { + for (auto&& formField : convertFieldListFromLua(L)) { + result->addReportedField(formField); + } + } + lua_pop(L, 1); + + lua_getfield(L, -1, "items"); + if (lua_istable(L, -1)) { + for (lua_pushnil(L); lua_next(L, -2);) { + result->addItem(convertFieldListFromLua(L)); + lua_pop(L, 1); + } + } + lua_pop(L, 1); + + return result; + } + + void convertFormToLua(lua_State* L, std::shared_ptr<Form> payload) { + std::string type; + switch (payload->getType()) { + case Form::FormType: type = "form"; break; + case Form::SubmitType: type = "submit"; break; + case Form::CancelType: type = "cancel"; break; + case Form::ResultType: type = "result"; break; + } + + Lua::Table result = boost::assign::map_list_of("type", Lua::valueRef(type)); + if (!payload->getTitle().empty()) { + result["title"] = Lua::valueRef(payload->getTitle()); + } + if (!payload->getInstructions().empty()) { + result["instructions"] = Lua::valueRef(payload->getInstructions()); + } + result["fields"] = valueRef(convertFieldListToLua(payload->getFields())); + if (!payload->getReportedFields().empty()) { + result["reported_fields"] = valueRef(convertFieldListToLua(payload->getReportedFields())); + } + + if (!payload->getItems().empty()) { + Lua::Array luaItems; + for (const auto& item : payload->getItems()) { + if (!item.empty()) { + luaItems.push_back(convertFieldListToLua(item)); + } + } + result["items"] = valueRef(luaItems); + } + + Lua::pushValue(L, result); + + lua_newtable(L); + lua_pushcfunction(L, formIndex); + lua_setfield(L, -2, "__index"); + lua_pushcfunction(L, formNewIndex); + lua_setfield(L, -2, "__newindex"); + lua_setmetatable(L, -2); + } + + int createSubmission(lua_State* L) { + std::shared_ptr<Form> form = convertFormFromLua(L); + + // Remove all redundant elements + form->setInstructions(""); + form->setTitle(""); + form->clearItems(); + form->clearReportedFields(); + std::vector< std::shared_ptr<FormField> > fields(form->getFields()); + form->clearFields(); + for (auto&& field : fields) { + if (field->getType() == FormField::FixedType) { + continue; + } + field->clearOptions(); + field->setLabel(""); + field->setType(FormField::UnknownType); + field->setDescription(""); + form->addField(field); + } + form->setType(Form::SubmitType); + + // Convert back + convertFormToLua(L, form); + Lua::registerTableToString(L, -1); + + return 1; + } } FormConvertor::FormConvertor() : GenericLuaElementConvertor<Form>("form") { @@ -348,14 +346,14 @@ FormConvertor::FormConvertor() : GenericLuaElementConvertor<Form>("form") { FormConvertor::~FormConvertor() { } -boost::shared_ptr<Form> FormConvertor::doConvertFromLua(lua_State* L) { - return convertFormFromLua(L); +std::shared_ptr<Form> FormConvertor::doConvertFromLua(lua_State* L) { + return convertFormFromLua(L); } -void FormConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<Form> payload) { - convertFormToLua(L, payload); +void FormConvertor::doConvertToLua(lua_State* L, std::shared_ptr<Form> payload) { + convertFormToLua(L, payload); - lua_pushstring(L, "create_submission"); - lua_pushcfunction(L, createSubmission); - lua_rawset(L, -3); + lua_pushstring(L, "create_submission"); + lua_pushcfunction(L, createSubmission); + lua_rawset(L, -3); } |