/modules/mod_survey/support/mod_survey_schema.erl

http://github.com/zotonic/zotonic · Erlang · 151 lines · 104 code · 25 blank · 22 comment · 2 complexity · b668a7f1debce7e908346d5b3b3bd0f8 MD5 · raw file

  1. %% @author Arjan Scherpenisse <arjan@scherpenisse.net>
  2. %% @copyright 2011 Arjan Scherpenisse <arjan@scherpenisse.net>
  3. %% Date: 2011-10-13
  4. %% @doc Schema definition for the survey module.
  5. %% Copyright 2011 Arjan Scherpenisse
  6. %%
  7. %% Licensed under the Apache License, Version 2.0 (the "License");
  8. %% you may not use this file except in compliance with the License.
  9. %% You may obtain a copy of the License at
  10. %%
  11. %% http://www.apache.org/licenses/LICENSE-2.0
  12. %%
  13. %% Unless required by applicable law or agreed to in writing, software
  14. %% distributed under the License is distributed on an "AS IS" BASIS,
  15. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. %% See the License for the specific language governing permissions and
  17. %% limitations under the License.
  18. -module(mod_survey_schema).
  19. -author("Arjan Scherpenisse <arjan@scherpenisse.net>").
  20. -include_lib("include/zotonic.hrl").
  21. -include("../survey.hrl").
  22. -export([
  23. manage_schema/2,
  24. survey_to_blocks/2
  25. ]).
  26. %% @doc Install tables used for storing survey results
  27. manage_schema(install, Context) ->
  28. %% This is a workaround for async initialization of the database tables; see github issues #734, #497
  29. install_survey_answer_table(z_context:prune_for_spawn(Context)),
  30. #datamodel{
  31. categories=[
  32. {survey, undefined, [{title, <<"Survey">>}]},
  33. {poll, survey, [{title, <<"Poll">>}]}
  34. ]};
  35. manage_schema({upgrade, 2}, Context) ->
  36. % Replace all survey properties with blocks
  37. {Low, High} = m_category:get_range_by_name(survey, Context),
  38. Ids = z_db:q("select id from rsc where pivot_category_nr >= $1 and pivot_category_nr <= $2", [Low, High], Context),
  39. [
  40. survey_to_blocks(Id, Context) || {Id} <- Ids
  41. ],
  42. ok;
  43. manage_schema({upgrade, 3}, Context) ->
  44. [] = z_db:q("alter table survey_answer add column is_anonymous boolean not null default false", Context),
  45. ok.
  46. install_survey_answer_table(Context) ->
  47. case z_db:table_exists(survey_answer, Context) of
  48. false ->
  49. z_db:create_table(survey_answer, [
  50. #column_def{name=id, type="serial", is_nullable=false},
  51. #column_def{name=survey_id, type="integer", is_nullable=false},
  52. #column_def{name=user_id, type="integer", is_nullable=true},
  53. #column_def{name=persistent, type="character varying", length=32, is_nullable=true},
  54. #column_def{name=is_anonymous, type="boolean", is_nullable=false, default="false"},
  55. #column_def{name=question, type="character varying", length=32, is_nullable=false},
  56. #column_def{name=name, type="character varying", length=32, is_nullable=false},
  57. #column_def{name=value, type="character varying", length=80, is_nullable=true},
  58. #column_def{name=text, type="bytea", is_nullable=true},
  59. #column_def{name=created, type="timestamp with time zone", is_nullable=true}
  60. ], Context),
  61. % Add some indices and foreign keys, ignore errors
  62. z_db:equery("create index fki_survey_answer_survey_id on survey_answer(survey_id)", Context),
  63. z_db:equery("alter table survey_answer add
  64. constraint fk_survey_answer_survey_id foreign key (survey_id) references rsc(id)
  65. on update cascade on delete cascade", Context),
  66. z_db:equery("create index fki_survey_answer_user_id on survey_answer(user_id)", Context),
  67. z_db:equery("alter table survey_answer add
  68. constraint fk_survey_answer_user_id foreign key (user_id) references rsc(id)
  69. on update cascade on delete cascade", Context),
  70. %% For aggregating answers to survey questions (group by name)
  71. z_db:equery("create index survey_answer_survey_name_key on survey_answer(survey_id, name)", Context),
  72. z_db:equery("create index survey_answer_survey_question_key on survey_answer(survey_id, question)", Context),
  73. z_db:equery("create index survey_answer_survey_user_key on survey_answer(survey_id, user_id)", Context),
  74. z_db:equery("create index survey_answer_survey_persistent_key on survey_answer(survey_id, persistent)", Context);
  75. true ->
  76. ok
  77. end.
  78. survey_to_blocks(Id, Context) ->
  79. case m_rsc:p_no_acl(Id, survey, Context) of
  80. undefined ->
  81. ok;
  82. {survey, QIds, Qs} ->
  83. QBlocks = [
  84. question_to_block(proplists:get_value(QId, Qs))
  85. || QId <- QIds
  86. ],
  87. CurrBlocks = to_list(m_rsc:p_no_acl(Id, blocks, Context)),
  88. m_rsc_update:update(Id,
  89. [
  90. {survey, undefined},
  91. {blocks, CurrBlocks++QBlocks}
  92. ],
  93. z_acl:sudo(Context)),
  94. ok
  95. end.
  96. to_list(undefined) -> [];
  97. to_list(<<>>) -> [];
  98. to_list(L) when is_list(L) -> L.
  99. question_to_block(#survey_question{type=likert} = Q) -> survey_q_likert:to_block(Q);
  100. question_to_block(#survey_question{type=longanswer} = Q) -> survey_q_long_answer:to_block(Q);
  101. question_to_block(#survey_question{type=matching} = Q) -> survey_q_matching:to_block(Q);
  102. question_to_block(#survey_question{type=narrative} = Q) -> survey_q_narrative:to_block(Q);
  103. question_to_block(#survey_question{type=pagebreak} = Q) -> survey_q_page_break:to_block(Q);
  104. question_to_block(#survey_question{type=shortanswer} = Q) -> survey_q_short_answer:to_block(Q);
  105. question_to_block(#survey_question{type=thurstone} = Q) -> survey_q_thurstone:to_block(Q);
  106. question_to_block(#survey_question{type=truefalse} = Q) -> survey_q_truefalse:to_block(Q);
  107. question_to_block(#survey_question{type=yesno} = Q) -> survey_q_yesno:to_block(Q);
  108. question_to_block(#survey_question{type=multiple_choice} = Q) -> survey_q_multiple_choice:to_block(Q);
  109. question_to_block(#survey_question{type=subhead, name=Name, question=Q}) ->
  110. [
  111. {type, header},
  112. {name, z_convert:to_binary(Name)},
  113. {header, z_convert:to_binary(Q)}
  114. ];
  115. question_to_block(#survey_question{type=prompt, name=Name, question=Q}) ->
  116. [
  117. {type, text},
  118. {name, z_convert:to_binary(Name)},
  119. {body, z_convert:to_binary(["<p>",Q,"</p>"])}
  120. ];
  121. question_to_block(#survey_question{type=textblock, name=Name, question=Q}) ->
  122. [
  123. {type, text},
  124. {name, z_convert:to_binary(Name)},
  125. {body, z_convert:to_binary(["<p>",Q,"</p>"])}
  126. ].