PageRenderTime 60ms CodeModel.GetById 16ms app.highlight 40ms RepoModel.GetById 1ms app.codeStats 0ms

/src/install/z_install_data.erl

http://github.com/zotonic/zotonic
Erlang | 304 lines | 212 code | 49 blank | 43 comment | 6 complexity | 754219aa56cd64d1be4158a19f375fa3 MD5 | raw file
  1%% @author Marc Worrell <marc@worrell.nl>
  2%% @copyright 2009-2016 Marc Worrell, Arjan Scherpenisse
  3%%
  4%% @doc Initialize the database with start data.
  5
  6%% Copyright 2009-2016 Marc Worrell, Arjan Scherpenisse
  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(z_install_data).
 21-author("Marc Worrell <marc@worrell.nl").
 22
 23%% interface functions
 24-export([
 25         install/2,
 26         install_category/1,
 27         install_modules/1
 28]).
 29
 30-include_lib("zotonic.hrl").
 31
 32%% @doc Insert boot data into the database.
 33%% @spec install(Host::atom(), Connection) -> ok
 34install(Site, Context) ->
 35    lager:info("~p: Install start.", [Site]),
 36    ok = install_category(Context),
 37    ok = install_rsc(Context),
 38    ok = install_identity(Context),
 39    ok = install_predicate(Context),
 40    ok = install_skeleton_modules(Context),
 41    z_db:equery("SELECT setval('rsc_id_seq', m) FROM (select 1 + max(id) as m from rsc) sub", Context),
 42    lager:info("~p: Install done.", [Site]),
 43    ok.
 44
 45%% @doc Install all modules for the site.
 46%% The list of modules is read from either the site config file, 
 47%% under the key <tt>install_modules</tt>.
 48-spec install_modules(#context{}) -> ok.
 49install_modules(Context) ->
 50    Site = z_context:site(Context),
 51    {ok, Config} = z_sites_manager:get_site_config(Site),
 52    Modules = [Site | proplists:get_value(install_modules, Config, [])],
 53    [install_module(M, Context) || M <- Modules],
 54    ok.
 55
 56%% @doc Install all skeleton modules for the site.
 57%% If the <tt>install_modules</tt> is not defined then the standard list
 58%% of modules from the skeleton is installed.
 59-spec install_skeleton_modules(#context{}) -> ok.
 60install_skeleton_modules(Context) ->
 61    Site = Context#context.site,
 62    {ok, Config} = z_sites_manager:get_site_config(Site),
 63    case proplists:get_value(install_modules, Config, []) of
 64        [] ->
 65            install_module({skeleton, proplists:get_value(skeleton, Config)}, Context),
 66            ok;
 67        _ ->
 68            ok
 69    end.
 70
 71install_module({skeleton, undefined}, _C) ->
 72    ok;
 73install_module({skeleton, S}, C) ->
 74    [install_module(M, C) || M <- get_skeleton_modules(S)];
 75install_module(M, Context) when is_atom(M); is_binary(M); is_list(M) ->
 76    case z_db:equery("update module set is_active = true where name = $1", [M], Context) of
 77        {ok, 1} = R ->
 78            R;
 79        {ok, 0} ->
 80            {ok, 1} = z_db:equery("insert into module (name, is_active) values ($1, true)", [M], Context)
 81    end.
 82
 83-spec get_skeleton_modules(Skeleton::atom()) -> list().
 84get_skeleton_modules(empty) ->
 85    [
 86     mod_base,
 87     mod_menu,
 88     mod_oauth,
 89     mod_search,
 90     mod_oembed,
 91     mod_signal,
 92     mod_mqtt,
 93     mod_logging,
 94     mod_l10n,
 95
 96     mod_authentication,
 97     mod_acl_adminonly,
 98     mod_editor_tinymce,
 99
100     mod_admin,
101     mod_admin_category,
102     mod_admin_config,
103     mod_admin_identity,
104     mod_admin_modules,
105     mod_admin_predicate,
106
107     mod_media_exif
108    ];
109get_skeleton_modules(blog) ->
110    [
111     mod_base,
112     mod_base_site,
113     mod_menu,
114     mod_oauth,
115     mod_search,
116     mod_oembed,
117     mod_atom_feed,
118     mod_translation,
119     mod_signal,
120     mod_logging,
121     mod_mqtt,
122     mod_l10n,
123
124     mod_seo,
125     mod_seo_sitemap,
126
127     mod_authentication,
128     mod_acl_adminonly,
129     mod_editor_tinymce,
130
131     mod_admin,
132     mod_admin_category,
133     mod_admin_config,
134     mod_admin_identity,
135     mod_admin_modules,
136     mod_admin_predicate,
137
138     mod_media_exif,
139
140     mod_comment,
141     mod_bootstrap
142    ];
143get_skeleton_modules(_) ->
144    %% nodb | undefined | OtherUnknown -> []
145    []. 
146
147
148install_category(C) ->
149    lager:info("Inserting categories"),
150    %% The egg has to lay a fk-checked chicken here, so the insertion order is sensitive.
151
152    %% 1. Insert the categories "meta" and "category" 
153    {ok, 2} = z_db:equery("
154                    insert into hierarchy (name, id, parent_id, nr, lvl, lft, rght) 
155                    values
156                        ('$category', 115, null, 90000000, 1, 90000000, 92000000),
157                        ('$category', 116, null, 91000000, 2, 91000000, 91000000)
158                    ", C),
159
160    %% make "category" a sub-category of "meta"
161    {ok, 1} = z_db:equery("update hierarchy set parent_id = 115 where id = 116", C),
162
163    %% "http://purl.org/dc/terms/DCMIType" ?
164    {ok, 1} = z_db:equery("
165            insert into rsc (id, is_protected, visible_for, category_id, name, uri, props)
166            values (116, true, 0, 116, 'category', $1, $2)
167            ", [    undefined, 
168                    ?DB_PROPS([{title, {trans, [{en, <<"Category">>}, {nl, <<"Categorie">>}]}}])
169                ], C),
170
171    {ok, 1} = z_db:equery("
172            insert into rsc (id, is_protected, visible_for, category_id, name, uri, props)
173            values (115, true, 0, 116, 'meta', $1, $2)
174            ", [    undefined, 
175                    ?DB_PROPS([{title, {trans, [{en, <<"Meta">>}, {nl, <<"Meta">>}]}}])
176                ], C),
177    
178    %% Now that we have the category "category" we can insert all other categories.
179    Cats = [
180        {101,undefined,  1,1,1,1, other,       true,  undefined,                                   [{title, {trans, [{en, <<"Uncategorized">>}, {nl, <<"Zonder categorie">>}]}}] },
181
182        {104,undefined,  2,1,2,4, text,        false, "http://purl.org/dc/dcmitype/Text",          [{title, {trans, [{en, <<"Text">>}, {nl, <<"Tekst">>}]}}] },
183            {106,104,    3,2,3,3, article,     false, undefined,                                   [{title, {trans, [{en, <<"Article">>}, {nl, <<"Artikel">>}]}}] },
184                {109,106,4,3,4,4, news,        false, undefined,                                   [{title, {trans, [{en, <<"News">>}, {nl, <<"Nieuws">>}]}}] },
185
186        {102,undefined,  5,1,5,5, person,      true,  undefined,                                   [{title, {trans, [{en, <<"Person">>}, {nl, <<"Persoon">>}]}}] },
187
188        {119,undefined,  6,1,6,7, location,    false, undefined,                                   [{title, {trans, [{en, <<"Location">>}, {nl, <<"Locatie">>}]}}] },
189            {107,119,    7,2,7,7, website,     false, undefined,                                   [{title, {trans, [{en, <<"Website">>}, {nl, <<"Website">>}]}}] },
190
191        {108, undefined, 8,1,8,8, event,       false, "http://purl.org/dc/dcmitype/Event",         [{title, {trans, [{en, <<"Event">>}, {nl, <<"Evenement">>}]}}] },
192
193        {103,undefined,  9,1,9,9, artifact,    false, "http://purl.org/dc/dcmitype/PhysicalObject",[{title, {trans, [{en, <<"Artifact">>}, {nl, <<"Artefact">>}]}}] },
194
195        {110,undefined,  10,1,10,14, media,       true,  "http://purl.org/dc/dcmitype/Image",         [{title, {trans, [{en, <<"Media">>}, {nl, <<"Media">>}]}}] }, 
196            {111,110,    11,2,11,11, image,       true,  "http://purl.org/dc/dcmitype/StillImage",    [{title, {trans, [{en, <<"Image">>}, {nl, <<"Afbeelding">>}]}}] },
197            {112,110,    12,2,12,12, video,       true,  "http://purl.org/dc/dcmitype/MovingImage",   [{title, {trans, [{en, <<"Video">>}, {nl, <<"Video">>}]}}] },
198            {113,110,    13,2,13,13, audio,       true,  "http://purl.org/dc/dcmitype/Sound",         [{title, {trans, [{en, <<"Audio">>}, {nl, <<"Geluid">>}]}}] },
199            {114,110,    14,2,14,14, document,    true,  undefined,							         [{title, {trans, [{en, <<"Document">>}, {nl, <<"Document">>}]}}] },
200
201        {120,undefined,  15,1,15,16, collection,  false, "http://purl.org/dc/dcmitype/Collection",    [{title, {trans, [{en, <<"Collection">>}, {nl, <<"Collectie">>}]}}] },
202            {121,120,    16,2,16,16, 'query',     false, "http://purl.org/dc/dcmitype/Dataset",       [{title, {trans, [{en, <<"Search query">>}, {nl, <<"Zoekopdracht">>}]}}] },
203
204        {122,undefined,  17,1,17,18, categorization,true,undefined,                                   [{title, {trans, [{en, <<"Categorization">>}, {nl, <<"Categorisatie">>}]}}] },
205            {123,122,    18,2,18,18, keyword,     true,  undefined,                                   [{title, {trans, [{en, <<"Keyword">>}, {nl, <<"Trefwoord">>}]}}] },
206
207        % 115. Meta (see above)
208            % 116. Category (see above)
209            {117,115,    92,2,92,92, predicate,   true,  undefined,                                   [{title, {trans, [{en, <<"Predicate">>},     {nl, <<"Predikaat">>}]}}] }
210        
211        % Next id: 124
212    ],
213
214    InsertCatFun = fun({Id, ParentId, Nr, Lvl, Left, Right, Name, Protected, Uri, Props}) ->
215        {ok, 1} = z_db:equery("
216                insert into rsc (id, visible_for, category_id, is_protected, name, uri, props)
217                values ($1, 0, 116, $2, $3, $4, $5)
218                ", [ Id, Protected, Name, Uri, ?DB_PROPS(Props) ], C),
219        {ok, 1} = z_db:equery("
220                insert into hierarchy (name, id, parent_id, nr, lvl, lft, rght)
221                values ('$category', $1, $2, $3, $4, $5, $6)", 
222                [Id, ParentId, Nr*1000000, Lvl, Left*1000000, Right*1000000-1], C)
223    end,
224    lists:foreach(InsertCatFun, Cats),
225    ok.
226    
227
228%% @doc Install some initial resources, most important is the system administrator
229%% @todo Add the hostname to the uri
230install_rsc(C) ->
231    lager:info("Inserting base resources (admin, etc.)"),
232    Rsc = [
233        % id  vsfr  cat   protect name,         props
234        [   1,  0,  102,  true,    "administrator",   ?DB_PROPS([{title,<<"Site Administrator">>}]) ]
235    ],
236    
237    [ {ok,1} = z_db:equery("
238            insert into rsc (id, visible_for, category_id, is_protected, name, props)
239            values ($1, $2, $3, $4, $5, $6)
240            ", R, C) || R <- Rsc ],
241    {ok, _} = z_db:equery("update rsc set creator_id = 1, modifier_id = 1, is_published = true", C),
242    ok.
243
244
245%% @doc Install the admin user as an user.  Uses the hard coded password "admin" when no password defined in the environment.
246install_identity(C) ->
247    lager:info("Inserting username for the admin"),
248    Hash = m_identity:hash([]),
249    {ok, 1} = z_db:equery("
250        insert into identity (rsc_id, type, key, is_unique, propb)
251        values (1, 'username_pw', 'admin', true, $1)", [{term, Hash}], C),
252    ok.
253    
254
255%% @doc Install some initial predicates, this list should be extended with common and useful predicates
256%% See http://dublincore.org/documents/dcmi-terms/
257%% @todo Extend and check this list.  Add allowed from/to categories.
258install_predicate(C) ->
259    lager:info("Inserting predicates"),
260    Preds = [
261        % id   protect name       uri                                                  props
262        [ 300, true,   "about",    "http://www.w3.org/1999/02/22-rdf-syntax-ns#about",  ?DB_PROPS([{reversed, false},{title, {trans, [{en,"About"},    {nl,"Over"}]}}])],
263        [ 301, true,   "author",   "http://purl.org/dc/terms/creator",                  ?DB_PROPS([{reversed, false},{title, {trans, [{en,"Author"},   {nl,"Auteur"}]}}])],
264        [ 303, true,   "relation", "http://purl.org/dc/terms/relation",                 ?DB_PROPS([{reversed, false},{title, {trans, [{en,"Relation"}, {nl,"Relatie"}]}}])],
265        [ 304, true,   "depiction","http://xmlns.com/foaf/0.1/depiction",               ?DB_PROPS([{reversed, false},{title, {trans, [{en,"Depiction"},{nl,"Afbeelding"}]}}])],
266        [ 308, true,   "subject",  "http://purl.org/dc/elements/1.1/subject",           ?DB_PROPS([{reversed, false},{title, {trans, [{en,"Keyword"},  {nl,"Trefwoord"}]}}])],
267        [ 309, true,   "hasdocument", "http://zotonic.net/predicate/hasDocument",       ?DB_PROPS([{reversed, false},{title, {trans, [{en,"Document"}, {nl,"Document"}]}}])],
268		[ 310, true,   "haspart",  "http://purl.org/dc/terms/hasPart",					?DB_PROPS([{reversed, false},{title, {trans, [{en,"Contains"}, {nl,"Bevat"}]}}])]
269    ],
270
271    CatId   = z_db:q1("select id from rsc where name = 'predicate'", C),
272    
273    [ {ok,1} = z_db:equery("
274            insert into rsc (id, visible_for, is_protected, name, uri, props, category_id, is_published, creator_id, modifier_id)
275            values ($1, 0, $2, $3, $4, $5, $6, true, 1, 1)
276            ", R ++ [CatId], C) || R <- Preds],
277
278    ObjSubj = [
279        [300, true,  104], %  text   -> about     -> _
280        [301, false, 102], %  _      -> author    -> person
281        [304, false, 110], %  _      -> depiction -> image
282
283        [308, true,  104], %  text     -> subject   -> _
284        [308, true,  102], %  person   -> subject   -> _
285        [308, true,  119], %  location -> subject   -> _
286        [308, true,  108], %  event    -> subject   -> _
287        [308, true,  103], %  artifact -> subject   -> _
288        [308, true,  110], %  media    -> subject   -> _
289        [308, true,  114], %  collection -> subject   -> _
290        [308, false, 123], %  _      -> subject   -> keyword
291
292        [309, true,  102], %  person   -> document -> _
293        [309, true,  103], %  artifact -> document -> _
294        [309, true,  104], %  text     -> document -> _
295        [309, true,  119], %  location -> document -> _
296        [309, false, 114], %  _        -> document -> media
297
298        [310, true,  120]  %  collection -> haspart -> _
299    ],
300    
301    [ {ok, 1} = z_db:equery("
302            insert into predicate_category (predicate_id, is_subject, category_id) 
303            values ($1, $2, $3)", OS, C) || OS <- ObjSubj ],
304    ok.