PageRenderTime 53ms CodeModel.GetById 11ms app.highlight 36ms RepoModel.GetById 1ms app.codeStats 0ms

/modules/mod_comment/mod_comment.erl

https://code.google.com/p/zotonic/
Erlang | 185 lines | 140 code | 19 blank | 26 comment | 2 complexity | dbf31403573d365d24c795809c918e7c MD5 | raw file
  1%% @author Marc Worrell <marc@worrell.nl>
  2%% @copyright 2010 Marc Worrell
  3%% Date: 2010-01-15
  4%% @doc Simple comment module. Adds comments to any rsc.
  5
  6%% Copyright 2010 Marc Worrell
  7%%
  8%% Licensed under the Apache License, Version 2.0 (the "License");
  9%% you may not use this file except in compliance with the License.
 10%% You may obtain a copy of the License at
 11%% 
 12%%     http://www.apache.org/licenses/LICENSE-2.0
 13%% 
 14%% Unless required by applicable law or agreed to in writing, software
 15%% distributed under the License is distributed on an "AS IS" BASIS,
 16%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 17%% See the License for the specific language governing permissions and
 18%% limitations under the License.
 19
 20-module(mod_comment).
 21-author("Marc Worrell <marc@worrell.nl>").
 22
 23-mod_title("Comments").
 24-mod_description("Comments for pages. Implements a simple comment system with comments stored locally.").
 25
 26%% gen_server exports
 27-export([init/1]).
 28
 29%% interface functions
 30-export([
 31    event/2,
 32    observe_search_query/2
 33]).
 34
 35-include_lib("zotonic.hrl").
 36
 37
 38%% @doc Handle the submit event of a new comment
 39event({submit, {newcomment, Args}, TriggerId, _TargetId}, Context) ->
 40    {id, Id} = proplists:lookup(id, Args),
 41    case z_auth:is_auth(Context) of
 42        false ->
 43            Name = z_context:get_q_validated("name", Context),
 44            Email = z_context:get_q_validated("mail", Context);
 45        true ->
 46            Name = "",
 47            Email = ""
 48    end,
 49    Message = z_context:get_q_validated("message", Context),
 50    case m_comment:insert(Id, Name, Email, Message, Context) of
 51        {ok, CommentId} ->
 52            CommentsListElt = proplists:get_value(comments_list, Args, "comments-list"),
 53            CommentTemplate = proplists:get_value(comment_template, Args, "_comments_comment.tpl"),
 54            Comment = m_comment:get(CommentId, Context),
 55            Props = [
 56                {id, Id},
 57                {comment, Comment},
 58                {creator, m_rsc:p(Id, creator_id, Context)},
 59                {hidden, true}
 60            ],
 61            Html = z_template:render(CommentTemplate, Props, Context),
 62            Context1 = z_render:insert_bottom(CommentsListElt, Html, Context),
 63            Context2 = z_render:wire([
 64                            {set_value, [{selector, "#"++TriggerId++" textarea[name=\"message\"]"}, {value, ""}]},
 65                            {set_value, [{selector, "#"++TriggerId++" input[name=\"message\"]"}, {value, ""}]},
 66                            {fade_in, [{target, "comment-"++integer_to_list(CommentId)}]}
 67                        ], Context1),
 68            case z_convert:to_bool(proplists:get_value(do_redirect, Args, true)) of
 69                true -> z_render:wire({redirect, [{location, "#comment-"++integer_to_list(CommentId)}]}, Context2);
 70                false -> Context2
 71            end;
 72        {error, _} ->
 73            Context
 74    end.
 75
 76
 77%% @doc Return the list of recent comments.  Returned values are the complete records.
 78observe_search_query({search_query, {recent_comments, []}, OffsetLimit}, Context) ->
 79    m_comment:search({recent_comments, []}, OffsetLimit, Context);
 80observe_search_query(_, _Context) ->
 81    undefined.
 82
 83
 84%% @doc Check the installation of the comment table. A bit more complicated because 0.1 and 0.2 had a table
 85%% in the default installer, this module installs a different table.
 86init(Context) ->
 87    ok = z_db:transaction(fun install1/1, Context),
 88    z_depcache:flush(Context),
 89    ok.
 90    
 91    install1(Context) ->
 92        ok = remove_old_comment_rsc_fields(Context),
 93        ok = remove_old_rating_table(Context),
 94        ok = install_comment_table(z_db:table_exists(comment, Context), Context),
 95        ok.
 96
 97
 98remove_old_rating_table(Context) ->
 99    case z_db:table_exists(rating, Context) of
100        false ->
101            ok;
102        true ->
103            case z_db:column_names(rating, Context) of
104                [comment_id,created,id,ip_address,rsc_id,visitor_id] ->
105                    z_db:q("drop table rating", Context),
106                    ok;
107                _ ->
108                    ok
109            end
110    end.
111
112install_comment_table(true, Context) ->
113    % Check for old table
114    case z_db:column_names(comment, Context) of
115        [created,creator_id,id,ip_address,notify_id,props,rating,rsc_id] ->
116            z_db:q("drop table comment", Context),
117            install_comment_table(false, Context);
118        [created,id,email,gravatar_code,ip_address,is_visible,keep_informed,
119         name,props,rsc_id,user_agent,user_id,visitor_id] ->
120            z_db:q("alter table comment drop column visitor_id cascade, "
121                   "add column persistent_id character varying (32), "
122                   "add constraint fk_comment_persistent_id foreign key (persistent_id) "
123                   "  references persistent(id) on delete set null on update cascade", Context),
124            z_db:q("create index fki_comment_persistent_id on comment(persistent_id)", Context),
125            ok;
126        _ ->
127            % todo: add list of current fields here
128            ok
129    end;
130install_comment_table(false, Context) ->
131    z_db:q("
132        create table comment (
133            id serial not null,
134            is_visible boolean not null default true,
135            rsc_id int not null,
136            user_id int,
137            persistent_id character varying(32),
138            gravatar_code character varying(40) not null default ''::character varying,
139            email character varying(80) not null default ''::character varying,
140            name character varying(80) not null default ''::character varying,
141            user_agent character varying(250) not null default ''::character varying,
142            ip_address character varying(40) not null default ''::character varying,
143            keep_informed boolean not null default false,
144            props bytea,
145            created timestamp with time zone not null default now(),
146            
147            constraint comment_pkey primary key (id),
148            constraint fk_comment_rsc_id foreign key (rsc_id)
149                references rsc(id)
150                on delete cascade on update cascade,
151            constraint fk_comment_user_id foreign key (user_id)
152                references rsc(id)
153                on delete set null on update cascade,
154            constraint fk_comment_persistent_id foreign key (persistent_id)
155                references persistent(id)
156                on delete set null on update cascade
157        )
158    ", Context),
159    Indices = [
160        {"fki_comment_rsc_id", "rsc_id"},
161        {"fki_comment_user_id", "user_id"},
162        {"fki_comment_persistent_id", "persistent_id"},
163        {"fki_comment_ip_address", "ip_address"},
164        {"comment_rsc_created_key", "rsc_id, created"},
165        {"comment_created_key", "created"}
166    ],
167    [ z_db:q("create index "++Name++" on comment ("++Cols++")", Context) || {Name, Cols} <- Indices ],
168    ok.
169
170
171%% @doc In the 0.1.0 and 0.2.0 releases we had some pivot information in the rsc table. Remove this.
172remove_old_comment_rsc_fields(Context) ->
173    Cols = z_db:column_names(rsc, Context),
174    R = [],
175    R1 = case lists:member(comment_by, Cols) of true -> ["drop column comment_by"|R]; false -> R end,
176    R2 = case lists:member(comments, Cols) of true -> ["drop column comments"|R1]; false -> R1 end,
177    R3 = case lists:member(rating, Cols) of true -> ["drop column rating"|R2]; false -> R2 end,
178    R4 = case lists:member(rating_count, Cols) of true -> ["drop column rating_count"|R3]; false -> R3 end,
179    case R4 of
180        [] ->
181            ok;
182        L -> 
183            z_db:q("alter table rsc " ++ string:join(L, ", "), Context),
184            ok
185    end.