yl_survey/api.lua
2024-09-14 23:55:37 +02:00

368 lines
12 KiB
Lua

--
-- Surveys
--
-- yl_survey.get_data
--
local function get_data()
if next(yl_survey.data) then
return true, yl_survey.data
else
return false, {}
end
end
function yl_survey.get_data() return get_data() end
-- yl_survey.get_survey
--
local function get_record(id)
local success, data = yl_survey.get_data()
if (success == false) then return nil end
return table.copy(data[id]) -- {data} or nil
end
function yl_survey.get_record(id) return get_record(id) end
-- yl_survey.create_survey
--
local function validate_nil_or_positive(value)
if (value == nil) then return true end
if ((type(value) == "number") and (value >= 0)) then return true end
return false
end
local function validate(value, expect_type, allow_nil)
if ((allow_nil == true) and (value == nil)) then return true end
if ((allow_nil == false) and (value == nil)) then return false end
if (type(value) == expect_type) then return true end
return false
end
local function validate_questiontype(allowed_types)
local valid_types = {
singlechoice = true,
multiplechoice = true,
freetext = true
}
local sm_count = 0
local ft_count = 0
for _, t in ipairs(allowed_types) do
-- Invalid question type
if (valid_types[t] == nil) then return false end
-- Either singlechoice OR multiplechoice
if ((t == "singlechoice") or (t == "multiplechoice")) then
sm_count = sm_count + 1
end
if sm_count > 1 then return false end
-- Only one freetext allowed
if (t == "freetext") then ft_count = ft_count + 1 end
if ft_count > 1 then return false end
end
if ((ft_count + sm_count) == 0) then return false end
return true
end
local function create_survey(owner, allow_names, allow_anonymous, allow_changes,
timestamp_start, timestamp_end)
-- Defense
if ((type(owner) ~= "string") or (owner == "")) then
return false, yl_survey.t("owner must be string")
end
if (allow_names == nil) then allow_names = true end -- set default
if (type(allow_names) ~= "boolean") then
return false, yl_survey.t("allow_names must be boolean")
end
if (allow_anonymous == nil) then allow_anonymous = true end -- set default
if (type(allow_anonymous) ~= "boolean") then
return false, yl_survey.t("allow_anonymous must be boolean")
end
if (allow_changes == nil) then allow_changes = false end -- set default
if (type(allow_changes) ~= "boolean") then
return false, yl_survey.t("allow_changes must be boolean")
end
if (validate_nil_or_positive(timestamp_start) == false) then
return false, yl_survey.t(
"timestamp_start if given then must be number and not negative")
end
if (validate_nil_or_positive(timestamp_end) == false) then
return false, yl_survey.t(
"timestamp_end if given then must be number and not negative")
end
-- Specialcase: We don't accept surveys NOONE can take part in
--[[
if ((allow_names == false) and (allow_anonymous == false)) then
return false, yl_survey.t("Noone can take part in that survey. " ..
"Neither named nor anonymous participants are allowed")
end
]] --
if ((allow_names == false) and (allow_anonymous == false) and
(allow_changes == false)) then
return false, yl_survey.t("Noone can take part in that survey. " ..
"Neither named nor anonymous participants are allowed. " ..
" You can't change it later")
end
-- Specialcase: We don't accept surveys where the enddate is smaller than the startdate
if (timestamp_start and timestamp_end and (timestamp_start >= timestamp_end) and
(allow_changes == false)) then
return false, yl_survey.t("Noone can take part in that survey. " ..
"It ends before it starts and you can't change it later")
end
-- UUID
local get_uuid_success, UUID = yl_survey.create_uuid()
if (get_uuid_success == false) then return false, UUID end
-- Add to list
local metadata = {
id = UUID,
owner = owner,
allow_names = allow_names,
allow_anonymous = allow_anonymous,
allow_changes = allow_changes,
timestamp_start = timestamp_start,
timestamp_end = timestamp_end,
creation_date = os.time(),
modification_date = os.time()
}
local record = {}
record["metadata"] = metadata
-- Store
local success = yl_survey.save(UUID, record)
if (success == true) then
yl_survey.data[UUID] = record
return true, UUID
else
return false, yl_survey.t("Could not store")
end
end
function yl_survey.create_survey(owner, allow_names, allow_anonymous,
allow_changes, timestamp_start, timestamp_end)
return create_survey(owner, allow_names, allow_anonymous, allow_changes,
timestamp_start, timestamp_end)
end
-- yl_survey.edit_survey
--
local function edit_survey(id, owner, allow_names, allow_anonymous,
allow_changes, timestamp_start, timestamp_end,
delete_responses)
-- Defense
if (validate(id, "string", false) == false) then
return false, yl_survey.t("id must be string")
end
if (validate(owner, "string", true) == false) then
return false, yl_survey.t("owner must be string")
end
if (validate(allow_names, "boolean", true) == false) then
return false, yl_survey.t("allow_names must be boolean")
end
if (validate(allow_anonymous, "boolean", true) == false) then
return false, yl_survey.t("allow_anonymous must be boolean")
end
if (validate(allow_changes, "boolean", true) == false) then
return false, yl_survey.t("allow_changes must be boolean")
end
if (validate(timestamp_start, "number", true) == false) then
return false, yl_survey.t("timestamp_start must be number")
end
if (validate(timestamp_end, "number", true) == false) then
return false, yl_survey.t("timestamp_end must be number")
end
if (validate(delete_responses, "boolean", true) == false) then
return false, yl_survey.t("delete_responses must be boolean")
end
if (validate_nil_or_positive(timestamp_start) == false) then
return false, yl_survey.t(
"timestamp_start if given then must be number and not negative")
end
if (validate_nil_or_positive(timestamp_end) == false) then
return false, yl_survey.t(
"timestamp_end if given then must be number and not negative")
end
local record = yl_survey.get_record(id)
if (record == nil) then
return false, yl_survey.t("record does not exist")
end
if (record["metadata"].allow_changes == false) then
return false, yl_survey.t("no changes allowed")
end
local metadata = {
id = record["metadata"].id, -- This value cannot change
owner = owner or record["metadata"].owner,
allow_names = allow_names or record["metadata"].allow_names,
allow_anonymous = allow_anonymous or record["metadata"].allow_anonymous,
allow_changes = allow_changes or record["metadata"].allow_changes,
timestamp_start = timestamp_start or record["metadata"].timestamp_start,
timestamp_end = timestamp_end or record["metadata"].timestamp_end,
creation_date = record["metadata"].creation_date, -- This value cannot change
modification_date = os.time() -- This value must change
}
record["metadata"] = metadata
-- Delete responses
local no
if (delete_responses == true) then
record, no = yl_survey.delete_responses(record)
end
-- Store
local success = yl_survey.save(id, record)
if (success == true) then
yl_survey.data[id] = record
return true, id
else
return false, yl_survey.t("Could not store")
end
end
function yl_survey.edit_survey(id, owner, allow_names, allow_anonymous,
allow_changes, timestamp_start, timestamp_end,
delete_responses)
return edit_survey(id, owner, allow_names, allow_anonymous, allow_changes,
timestamp_start, timestamp_end, delete_responses)
end
-- yl_survey.remove_record
--
local function remove_record(id)
local data_success, data = yl_survey.get_data()
if (data_success ~= true) then return false, "Cannot get data" end
local remove_success = yl_survey.remove_file(id)
if (remove_success ~= true) then
return false, yl_survey.t("Could not remove")
end
local record = yl_survey.get_record(id)
if (record == nil) then
return false, yl_survey.t("record not found, cannot remove")
end
data[id] = nil
return true, record
end
function yl_survey.remove_record(id) return remove_record(id) end
--
-- Questions
--
local function create_question(id, question, category, sort, allowed_types,
answers, enabled)
-- Defense
if (validate(id, "string", false) == false) then
return false, yl_survey.t("id must be string")
end
if (validate(question, "string", false) == false) then
return false, yl_survey.t("question must be string")
end
if (category == nil) then category = "" end
if (validate(category, "string", false) == false) then
return false, yl_survey.t("category must be string")
end
if (validate_nil_or_positive(sort) == false) then
return false, yl_survey.t("sort must be positive number")
end
if (validate(allowed_types, "table", false) == false) then
return false, yl_survey.t("allowed_types must be table")
end
if (validate(answers, "table", true) == false) then
return false, yl_survey.t("answers must be table")
end
if (enabled == nil) then enabled = true end
if (validate(enabled, "boolean", false) == false) then
return false, yl_survey.t("enabled must be boolean")
end
-- Specialcase : allowed_types must be a combination of
-- "singlechoice" or "multiplechoice" or "freetext"
if (validate_questiontype(allowed_types) == false) then
return false, yl_survey.t("wrong allowed_types")
end
-- Specialcase : answers cannot be nil or empty if allowedtypes has either multiplechoice or singlechoice
if (((answers == nil) or (next(answers) == nil)) and
((allowed_types["multiplechoice"] ~= nil) or
(allowed_types["singlechoice"] ~= nil))) then
return false, yl_survey.t(
"answers cannot be nil or empty if allowedtypes has either multiplechoice or singlechoice")
end
-- Specialcase : given sort is a duplicate
if ((type(sort) == "number") and (yl_survey.is_duplicate(record, sort) == true)) then
return false, yl_survey.t("sort is duplicate")
end
local record = yl_survey.get_record(id)
if (record == nil) then
return false, yl_survey.t("record does not exist")
end
if (record["metadata"].allow_changes == false) then
return false, yl_survey.t("no changes allowed")
end
-- Payload
-- if sort is nil, then find next sort
local next_sort = sort or yl_survey.find_next_free_number(record, "sort")
-- Find next free q_id
local next_q_id, dupe = yl_survey.find_next_free_number(record, "id")
local t_question = {
id = next_q_id,
category = category,
sort = next_sort,
question = question,
enabled = true,
allowed_types = allowed_types,
answers = answers,
responses = {}
}
record[tostring(next_q_id)] = t_question
-- Store
local success = yl_survey.save(id, record)
if (success == true) then
yl_survey.data[id] = record
return true, next_q_id
else
return false, yl_survey.t("Could not store")
end
end
function yl_survey.create_question(id, question, category, sort, allowed_types,
answers, enabled)
return create_question(id, question, category, sort, allowed_types, answers, enabled)
end