/modules/mod_atom_feed/resources/resource_atom_feed_search.erl

https://code.google.com/p/zotonic/ · Erlang · 110 lines · 69 code · 25 blank · 16 comment · 0 complexity · fb25b31f1b906c1732304652686a4cd5 MD5 · raw file

  1. %% @author Arjan Scherpenisse <arjan@scherpenisse.net>
  2. %% @copyright 2009 Arjan Scherpenisse
  3. %% Date: 2009-12-06
  4. %% @doc Serve an atom feed for a search query. Query arguments are like /api/search.
  5. %% Licensed under the Apache License, Version 2.0 (the "License");
  6. %% you may not use this file except in compliance with the License.
  7. %% You may obtain a copy of the License at
  8. %%
  9. %% http://www.apache.org/licenses/LICENSE-2.0
  10. %%
  11. %% Unless required by applicable law or agreed to in writing, software
  12. %% distributed under the License is distributed on an "AS IS" BASIS,
  13. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. %% See the License for the specific language governing permissions and
  15. %% limitations under the License.
  16. -module(resource_atom_feed_search).
  17. -author("Arjan Scherpenisse <arjan@scherpenisse.net>").
  18. -export([
  19. init/1,
  20. service_available/2,
  21. allowed_methods/2,
  22. encodings_provided/2,
  23. expires/2,
  24. content_types_provided/2,
  25. charsets_provided/2,
  26. provide_content/2
  27. ]).
  28. -include_lib("webmachine_resource.hrl").
  29. -include_lib("include/zotonic.hrl").
  30. %% Let cached versions expire in an hour.
  31. -define(MAX_AGE, 3600).
  32. init(DispatchArgs) ->
  33. {ok, DispatchArgs}.
  34. service_available(ReqData, DispatchArgs) when is_list(DispatchArgs) ->
  35. Context = z_context:new(ReqData, ?MODULE),
  36. Context1 = z_context:set(DispatchArgs, Context),
  37. Context2 = z_context:ensure_qs(Context1),
  38. ?WM_REPLY(true, Context2).
  39. allowed_methods(ReqData, Context) ->
  40. {['HEAD', 'GET'], ReqData, Context}.
  41. charsets_provided(ReqData, Context) ->
  42. {[{"utf-8", fun(X) -> X end}], ReqData, Context}.
  43. encodings_provided(ReqData, Context) ->
  44. {[
  45. {"identity", fun(X) -> X end},
  46. {"gzip", fun(X) -> zlib:gzip(X) end}
  47. ], ReqData, Context}.
  48. content_types_provided(ReqData, Context) ->
  49. {[{"application/atom+xml", provide_content}], ReqData, Context}.
  50. expires(ReqData, State) ->
  51. RD1 = wrq:set_resp_header("Cache-Control", "public, max-age="++integer_to_list(?MAX_AGE), ReqData),
  52. NowSecs = calendar:datetime_to_gregorian_seconds(calendar:universal_time()),
  53. {calendar:gregorian_seconds_to_datetime(NowSecs + ?MAX_AGE), RD1, State}.
  54. provide_content(ReqData, Context) ->
  55. Query0 = z_context:get_q_all(Context),
  56. try
  57. {FeedTitle, Query} = case proplists:get_value("feed_title", Query0) of
  58. undefined ->
  59. {"Latest updates", Query0};
  60. T ->
  61. {T, proplists:delete("feed_title", Query0)}
  62. end,
  63. Q = search_query:parse_request_args(Query),
  64. Q1 = Q ++ [{sort, "-rsc.modified"}],
  65. F = fun() ->
  66. S = z_search:search({'query', Q1}, Context),
  67. Vars = [{ids, S#search_result.result},
  68. {qtext, proplists:get_value(text, Q1)},
  69. {feed_title, FeedTitle},
  70. {updated, z_context:get(last_modified, Context)},
  71. {site_url, z_context:abs_url("", Context)}
  72. ],
  73. {Content, _Context1} = z_template:render_to_iolist("atom_feed_search.tpl", Vars, Context),
  74. Content
  75. end,
  76. Content = z_depcache:memo(F, {atom_feed_search, Q}, ?MAX_AGE, [], Context),
  77. {Content, ReqData, Context}
  78. catch
  79. _: {error, {unknown_query_term, E}} ->
  80. ReqData1 = wrq:set_resp_body("Unknown query term: " ++ E, ReqData),
  81. {{halt, 400}, ReqData1, Context};
  82. _: {case_clause, {error, {error, error, _, _E, _}}} ->
  83. ReqData1 = wrq:set_resp_body("Unknown error.", ReqData),
  84. {{halt, 400}, ReqData1, Context}
  85. end.