PageRenderTime 38ms CodeModel.GetById 25ms app.highlight 10ms RepoModel.GetById 1ms app.codeStats 0ms

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