bsw/jbe@0: local issue bsw/jbe@0: local area bsw/jbe@0: bsw/jbe@0: local issue_id = param.get("issue_id", atom.integer) bsw/jbe@0: if issue_id then bsw@969: issue = Issue:new_selector():add_where{"id=?",issue_id}:for_share():single_object_mode():exec() bsw/jbe@5: if issue.closed then bsw/jbe@5: slot.put_into("error", _"This issue is already closed.") bsw/jbe@5: return false bsw/jbe@5: elseif issue.fully_frozen then bsw/jbe@5: slot.put_into("error", _"Voting for this issue has already begun.") bsw/jbe@5: return false bsw@967: elseif issue.phase_finished then bsw@967: slot.put_into("error", _"Current phase is already closed.") bsw@967: return false bsw/jbe@5: end bsw/jbe@0: area = issue.area bsw/jbe@0: else bsw/jbe@0: local area_id = param.get("area_id", atom.integer) bsw/jbe@0: area = Area:new_selector():add_where{"id=?",area_id}:single_object_mode():exec() bsw/jbe@52: if not area.active then bsw/jbe@52: slot.put_into("error", "Invalid area.") bsw/jbe@52: return false bsw/jbe@52: end bsw/jbe@0: end bsw/jbe@0: bsw@281: if not app.session.member:has_voting_right_for_unit_id(area.unit_id) then bsw/jbe@1309: return execute.view { module = "index", view = "403" } bsw@281: end bsw@281: bsw@904: local policy_id = param.get("policy_id", atom.integer) bsw@904: local policy bsw@904: if policy_id then bsw@904: policy = Policy:by_id(policy_id) bsw@904: end bsw@904: bsw@904: if not issue then bsw@904: if policy_id == -1 then bsw@904: slot.put_into("error", _"Please choose a policy") bsw@904: return false bsw@904: end bsw@904: if not policy.active then bsw@904: slot.put_into("error", "Invalid policy.") bsw@904: return false bsw@904: end bsw@904: if policy.polling and not app.session.member:has_polling_right_for_unit_id(area.unit_id) then bsw/jbe@1309: return execute.view { module = "index", view = "403" } bsw@904: end bsw@904: if not area:get_reference_selector("allowed_policies") bsw@904: :add_where{ "policy.id = ?", policy_id } bsw@904: :optional_object_mode() bsw@904: :exec() bsw@904: then bsw/jbe@1309: slot.put_into("error", "policy not allowed") bsw/jbe@1309: return false bsw@904: end bsw@904: end bsw@904: bsw@904: local is_polling = (issue and param.get("polling", atom.boolean)) or (policy and policy.polling) or false bsw@904: bsw@904: local tmp = db:query({ "SELECT text_entries_left, initiatives_left FROM member_contingent_left WHERE member_id = ? AND polling = ?", app.session.member.id, is_polling }, "opt_object") bsw@904: if not tmp or tmp.initiatives_left < 1 then bsw@904: slot.put_into("error", _"Sorry, your contingent for creating initiatives has been used up. Please try again later.") bsw@904: return false bsw@904: end bsw@904: if tmp and tmp.text_entries_left < 1 then bsw@904: slot.put_into("error", _"Sorry, you have reached your personal flood limit. Please be slower...") bsw@904: return false bsw@904: end bsw@904: bsw/jbe@6: local name = param.get("name") bsw/jbe@6: bsw/jbe@6: local name = util.trim(name) bsw/jbe@6: bsw/jbe@6: if #name < 3 then bsw@1045: slot.put_into("error", _"Please enter a meaningful title for your initiative!") bsw@1045: return false bsw@1045: end bsw@1045: bsw@1045: if #name > 140 then bsw@1045: slot.put_into("error", _"This title is too long!") bsw/jbe@6: return false bsw/jbe@6: end bsw/jbe@6: bsw@1092: local timing bsw@1096: if not issue and policy.free_timeable then bsw@1092: local free_timing_string = util.trim(param.get("free_timing")) bsw@1092: if not free_timing_string or #free_timing_string < 1 then bsw@1092: slot.put_into("error", _"Choose timing") bsw@1092: return false bsw@1092: end bsw@1092: local available_timings bsw@1092: if config.free_timing and config.free_timing.available_func then bsw@1092: available_timings = config.free_timing.available_func(policy) bsw@1092: if available_timings == false then bsw/jbe@1309: slot.put_into("error", "error in free timing config") bsw/jbe@1309: return false bsw@1092: end bsw@1092: end bsw@1092: if available_timings then bsw@1092: local timing_available = false bsw@1092: for i, available_timing in ipairs(available_timings) do bsw@1092: if available_timing.id == free_timing_string then bsw@1092: timing_available = true bsw@1092: end bsw@1092: end bsw@1092: if not timing_available then bsw@1092: slot.put_into("error", _"Invalid timing") bsw@1092: return false bsw@1092: end bsw@1092: end bsw@1092: timing = config.free_timing.calculate_func(policy, free_timing_string) bsw@1092: if not timing then bsw/jbe@1309: slot.put_into("error", "error in free timing config") bsw/jbe@1309: return false bsw@1092: end bsw@1092: end bsw@1092: bsw/jbe@1309: local draft_text = param.get("draft") bsw/jbe@1309: bsw/jbe@1309: if not draft_text then bsw/jbe@1309: return false bsw/jbe@1309: end bsw/jbe@1309: bsw/jbe@1309: local draft_text = util.wysihtml_preproc(draft_text) bsw/jbe@1309: bsw/jbe@1309: local valid_html, error_message = util.html_is_safe(draft_text) bsw/jbe@1309: if not valid_html then bsw/jbe@1309: slot.put_into("error", _("Draft contains invalid formatting or character sequence: #{error_message}", { error_message = error_message }) ) bsw/jbe@1309: return false bsw/jbe@1309: end bsw/jbe@1309: bsw/jbe@1309: if config.initiative_abstract then bsw/jbe@1309: local abstract = param.get("abstract") bsw/jbe@1309: if not abstract then bsw/jbe@1309: return false bsw/jbe@1309: end bsw/jbe@1309: abstract = encode.html(abstract) bsw/jbe@1309: draft_text = abstract .. "" .. draft_text bsw/jbe@1309: end bsw/jbe@1309: bsw/jbe@1309: local location = param.get("location") bsw/jbe@1309: if location == "" then bsw/jbe@1309: location = nil bsw/jbe@1309: end bsw/jbe@1309: bsw@1045: if param.get("preview") or param.get("edit") then bsw@95: return bsw@95: end bsw@81: bsw/jbe@0: local initiative = Initiative:new() bsw/jbe@0: bsw/jbe@0: if not issue then bsw/jbe@0: issue = Issue:new() bsw/jbe@0: issue.area_id = area.id bsw@7: issue.policy_id = policy_id bsw@898: bsw@898: if policy.polling then bsw@898: issue.accepted = 'now' bsw@898: issue.state = 'discussion' bsw@898: initiative.polling = true bsw@901: bsw@901: if policy.free_timeable then bsw@901: issue.discussion_time = timing.discussion bsw@901: issue.verification_time = timing.verification bsw@901: issue.voting_time = timing.voting bsw@901: end bsw@901: bsw@898: end bsw@898: bsw/jbe@0: issue:save() bsw@286: bsw@286: if config.etherpad then bsw@286: local result = net.curl( bsw@286: config.etherpad.api_base bsw@286: .. "api/1/createGroupPad?apikey=" .. config.etherpad.api_key bsw@286: .. "&groupID=" .. config.etherpad.group_id bsw@286: .. "&padName=Issue" .. tostring(issue.id) jbe@326: .. "&text=" .. request.get_absolute_baseurl() .. "issue/show/" .. tostring(issue.id) .. ".html" bsw@286: ) bsw@286: end bsw/jbe@0: end bsw/jbe@0: bsw@898: if param.get("polling", atom.boolean) and app.session.member:has_polling_right_for_unit_id(area.unit_id) then bsw@898: initiative.polling = true bsw@898: end bsw/jbe@0: initiative.issue_id = issue.id bsw/jbe@6: initiative.name = name bsw/jbe@0: initiative:save() bsw/jbe@0: bsw/jbe@0: local draft = Draft:new() bsw/jbe@0: draft.initiative_id = initiative.id bsw/jbe@4: draft.formatting_engine = formatting_engine bsw/jbe@1309: draft.content = draft_text bsw/jbe@1309: draft.location = location bsw/jbe@0: draft.author_id = app.session.member.id bsw/jbe@0: draft:save() bsw/jbe@0: bsw/jbe@0: local initiator = Initiator:new() bsw/jbe@0: initiator.initiative_id = initiative.id bsw/jbe@0: initiator.member_id = app.session.member.id bsw@10: initiator.accepted = true bsw/jbe@0: initiator:save() bsw/jbe@0: bsw@944: if not is_polling then bsw@944: local supporter = Supporter:new() bsw@944: supporter.initiative_id = initiative.id bsw@944: supporter.member_id = app.session.member.id bsw@944: supporter.draft_id = draft.id bsw@944: supporter:save() bsw@944: end bsw/jbe@0: bsw/jbe@0: slot.put_into("notice", _"Initiative successfully created") bsw/jbe@0: bsw/jbe@0: request.redirect{ bsw/jbe@0: module = "initiative", bsw/jbe@0: view = "show", bsw/jbe@0: id = initiative.id jbe@326: }