7bd4dba2705e9175747641df246df4cad605966d
[mir.git] / source / mircoders / servlet / ServletModuleContent.java
1 /*
2  * Copyright (C) 2001, 2002 The Mir-coders group
3  *
4  * This file is part of Mir.
5  *
6  * Mir is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * Mir is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Mir; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  * In addition, as a special exception, The Mir-coders gives permission to link
21  * the code of this program with  any library licensed under the Apache Software License,
22  * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library
23  * (or with modified versions of the above that use the same license as the above),
24  * and distribute linked combinations including the two.  You must obey the
25  * GNU General Public License in all respects for all of the code used other than
26  * the above mentioned libraries.  If you modify this file, you may extend this
27  * exception to your version of the file, but you are not obligated to do so.
28  * If you do not wish to do so, delete this exception statement from your version.
29  */
30
31 package mircoders.servlet;
32
33 import mir.entity.adapter.EntityAdapter;
34 import mir.entity.adapter.EntityAdapterEngine;
35 import mir.entity.adapter.EntityAdapterModel;
36 import mir.generator.Generator;
37 import mir.log.LoggerWrapper;
38 import mir.misc.StringUtil;
39 import mir.servlet.ServletModule;
40 import mir.servlet.ServletModuleExc;
41 import mir.servlet.ServletModuleFailure;
42 import mir.util.*;
43 import mircoders.entity.EntityContent;
44 import mircoders.entity.EntityUsers;
45 import mircoders.global.MirGlobal;
46 import mircoders.module.ModuleContent;
47 import mircoders.storage.DatabaseContent;
48 import mircoders.storage.DatabaseContentToTopics;
49
50 import javax.servlet.http.HttpServletRequest;
51 import javax.servlet.http.HttpServletResponse;
52 import java.util.*;
53
54 /**
55  * Article admin interface code
56  */
57
58 public class ServletModuleContent extends ServletModule {
59   private static ServletModuleContent instance = new ServletModuleContent();
60   public static ServletModule getInstance() { return instance; }
61   private static ModuleContent contentModule;
62
63   private ServletModuleContent() {
64     super();
65
66     propagatedParameters.add("selectarticleurl");
67
68     logger = new LoggerWrapper("ServletModule.Content");
69
70     try {
71       definition = "content";
72       contentModule = new ModuleContent();
73       mainModule = contentModule;
74     }
75     catch (Throwable e) {
76       logger.fatal("ServletModuleContent could not be initialized: " + e.toString());
77     }
78   }
79
80   public void search(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc, ServletModuleFailure {
81     try {
82       HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
83       SQLQueryBuilder queryBuilder = new SQLQueryBuilder();
84       String searchField = requestParser.getParameterWithDefault("searchfield", "");
85       String searchValue = requestParser.getParameterWithDefault("searchvalue", "").trim();
86       String searchOrder = requestParser.getParameterWithDefault("searchorder", "");
87       String searchispublished = requestParser.getParameterWithDefault("searchispublished", "");
88       String searchArticleType = requestParser.getParameterWithDefault("searcharticletype", "");
89
90       if (searchValue.length()>0) {
91         if (searchField.equals("id"))
92           queryBuilder.appendAndCondition(
93             "id='"+JDBCStringRoutines.escapeStringLiteral(searchValue)+"'");
94         else if (searchField.equals("contents"))
95           queryBuilder.appendAndCondition(
96             "(lower(content_data) like " + "'%" + JDBCStringRoutines.escapeStringLiteral(searchValue.toLowerCase()) + "%')"+
97             " or (lower(description) like " + "'%" + JDBCStringRoutines.escapeStringLiteral(searchValue.toLowerCase()) + "%')");
98         else
99           queryBuilder.appendAndCondition(
100             "lower("+ searchField + ") like " +
101             "'%" + JDBCStringRoutines.escapeStringLiteral(searchValue.toLowerCase()) + "%'");
102       }
103
104       if (searchispublished.length()>0) {
105         if (searchispublished.equals("0"))
106           queryBuilder.appendAndCondition("is_published='f'");
107         else
108           queryBuilder.appendAndCondition("is_published='t'");
109       }
110
111       if (searchArticleType.length()>0) {
112         queryBuilder.appendAndCondition("to_article_type="+Integer.parseInt(searchArticleType));
113       }
114
115       if (searchOrder.length()>0) {
116         if (searchOrder.equals("datedesc"))
117           queryBuilder.appendDescendingOrder("webdb_create");
118         else if (searchOrder.equals("dateasc"))
119           queryBuilder.appendAscendingOrder("webdb_create");
120         else if (searchOrder.equals("title"))
121           queryBuilder.appendAscendingOrder("title");
122         else if (searchOrder.equals("creator"))
123           queryBuilder.appendAscendingOrder("creator");
124       }
125
126       returnList(aRequest, aResponse, queryBuilder.getWhereClause(), queryBuilder.getOrderByClause(), 0);
127     }
128     catch (Throwable e) {
129       throw new ServletModuleFailure(e);
130     }
131   }
132
133   public void add(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc {
134     editObject(aRequest, aResponse, null);
135   }
136
137   public void insert(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc {
138     try {
139       Map withValues = getIntersectingValues(aRequest, DatabaseContent.getInstance());
140
141       String now = StringUtil.date2webdbDate(new GregorianCalendar());
142       withValues.put("date", now);
143       withValues.put("publish_path", StringUtil.webdbDate2path(now));
144       withValues.put("to_publisher", ServletHelper.getUser(aRequest).getId());
145       withValues.put("is_produced", "0");
146       if (!withValues.containsKey("is_published"))
147         withValues.put("is_published","0");
148       if (!withValues.containsKey("is_html"))
149         withValues.put("is_html","0");
150
151       String webdbCreate = (String) withValues.get("webdb_create");
152       if (webdbCreate==null || webdbCreate.trim().length()==0)
153         withValues.remove("webdb_create");
154
155       String id = mainModule.add(withValues);
156       logAdminUsage(aRequest, id, "object added");
157
158       DatabaseContentToTopics.getInstance().setTopics(id, aRequest.getParameterValues("to_topic"));
159
160       editObject(aRequest, aResponse, id);
161     }
162     catch (Throwable e) {
163       throw new ServletModuleFailure(e);
164     }
165   }
166
167   public void edit(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc {
168     String idParam = aRequest.getParameter("id");
169     if (idParam == null)
170       throw new ServletModuleExc("Invalid call: id not supplied ");
171     editObject(aRequest, aResponse, idParam);
172   }
173
174   /**
175    * Attaches media to an article
176    */
177   public void attach(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc {
178     String  mediaIdParam = aRequest.getParameter("mid");
179     String  articleId = aRequest.getParameter("articleid");
180     if (articleId == null || mediaIdParam==null)
181       throw new ServletModuleExc("smod content :: attach :: articleid/mid missing");
182     // check if mediaIdParam and articleid are correct integers
183     try
184     {
185       Integer.parseInt(mediaIdParam);
186       Integer.parseInt(articleId);
187     }
188     catch(NumberFormatException e)
189     {
190       throw new ServletModuleExc("smod content :: attach :: invalid articleid/mid");
191     }
192     
193     if (!MirGlobal.accessControl().article().mayEditArticle(ServletHelper.getUser(aRequest), articleId))
194       throw new ServletModuleExc("Article has been locked");
195
196     try {
197       EntityContent entContent = (EntityContent) mainModule.getById(articleId);
198       entContent.attach(mediaIdParam);
199     }
200     catch(Throwable e) {
201       throw new ServletModuleFailure(e);
202     }
203
204     logAdminUsage(aRequest, articleId, "media " + mediaIdParam + " attached");
205
206     editObject(aRequest, aResponse, articleId);
207   }
208
209   /**
210    * Deattaches media from an article
211    */
212   public void dettach(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc {
213     String  articleId = aRequest.getParameter("articleid");
214     String  midParam = aRequest.getParameter("mid");
215     if (articleId == null)
216       throw new ServletModuleExc("smod content :: dettach :: articleid missing");
217     if (midParam == null)
218       throw new ServletModuleExc("smod content :: dettach :: mid missing");
219
220     if (!MirGlobal.accessControl().article().mayEditArticle(ServletHelper.getUser(aRequest), articleId))
221       throw new ServletModuleExc("Article has been locked");
222
223     try {
224       EntityContent entContent = (EntityContent)mainModule.getById(articleId);
225       entContent.dettach(articleId, midParam);
226     }
227     catch(Throwable e) {
228       throw new ServletModuleFailure(e);
229     }
230
231     logAdminUsage(aRequest, articleId, "media " + midParam + " deattached");
232
233     editObject(aRequest, aResponse, articleId);
234   }
235
236   /**
237    * Locks an article
238    */
239   public void lock(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc
240   {
241     HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
242
243     String idParam = requestParser.getParameter("id");
244     if (idParam == null)
245       throw new ServletModuleExc("Wrong call: (id) is missing");
246
247     EntityUsers user = ServletHelper.getUser(aRequest);
248
249     if (!MirGlobal.accessControl().article().mayLockArticle(user, idParam))
250       throw new ServletModuleExc("Unable to lock");
251
252     contentModule.lockArticle(idParam, user.getId(), false);
253
254     editObject(aRequest, aResponse, idParam);
255   }
256
257   /**
258    * Unlocks an article
259    */
260   public void unlock(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc
261   {
262     HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
263
264     String idParam = requestParser.getParameter("id");
265     if (idParam == null)
266       throw new ServletModuleExc("Wrong call: (id) is missing");
267
268     EntityUsers user = ServletHelper.getUser(aRequest);
269
270     if (!MirGlobal.accessControl().article().mayUnlockArticle(user, idParam))
271       throw new ServletModuleExc("Unable to unlock");
272
273     contentModule.unlockArticle(idParam, user.getId(), false);
274
275     editObject(aRequest, aResponse, idParam);
276   }
277
278   /**
279    * Forcelocks an article
280    */
281   public void forcelock(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc {
282     HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
283
284     String idParam = requestParser.getParameter("id");
285     if (idParam == null)
286       throw new ServletModuleExc("Wrong call: (id) is missing");
287
288     EntityUsers user = ServletHelper.getUser(aRequest);
289
290     if (!MirGlobal.accessControl().article().mayForceLockArticle(user, idParam))
291       throw new ServletModuleExc("Unable to force lock");
292
293     contentModule.lockArticle(idParam, user.getId(), true);
294
295     editObject(aRequest, aResponse, idParam);
296   }
297
298   /**
299    * Stores an article
300    */
301   public void update(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc {
302     try {
303       HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
304
305       String idParam = requestParser.getParameter("id");
306       if (idParam == null)
307         throw new ServletModuleExc("Wrong call: (id) is missing");
308
309       if (!MirGlobal.accessControl().article().mayEditArticle(ServletHelper.getUser(aRequest), idParam))
310         throw new ServletModuleExc("Article has been locked");
311
312       Map withValues = getIntersectingValues(aRequest, DatabaseContent.getInstance());
313
314       withValues.put("is_produced", "0");
315       if (!withValues.containsKey("is_published"))
316         withValues.put("is_published","0");
317       if (!withValues.containsKey("is_html"))
318         withValues.put("is_html","0");
319
320       String webdbCreate = (String) withValues.get("webdb_create");
321       if (webdbCreate==null || webdbCreate.trim().length()==0)
322         withValues.remove("webdb_create");
323
324       String id = mainModule.set(withValues);
325
326       logAdminUsage(aRequest, id, "object modified");
327
328       DatabaseContentToTopics.getInstance().setTopics(aRequest.getParameter("id"), aRequest.getParameterValues("to_topic"));
329
330       if (MirGlobal.accessControl().article().mayUnlockArticle(ServletHelper.getUser(aRequest), idParam) &&
331          (requestParser.getParameterWithDefault("unlock", "0").equals("1"))) {
332         contentModule.unlockArticle(id, ServletHelper.getUser(aRequest).getId(), false);
333       }
334
335       editObject(aRequest, aResponse, idParam);
336     }
337     catch (Throwable e) {
338       throw new ServletModuleFailure(e);
339     }
340   }
341
342
343   /**
344    * Returns the basic article editing form.
345    *
346    * @param id identifier of the article. <code>null</code>, means show an
347    *     empty form to add a new article.
348    */
349   public void editObject(HttpServletRequest aRequest, HttpServletResponse aResponse, String id)
350       throws ServletModuleExc {
351     try {
352       HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
353       Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, new Locale[] { getLocale(aRequest), getFallbackLocale(aRequest)});
354       EntityAdapterModel model = MirGlobal.localizer().dataModel().adapterModel();
355       Object article;
356       URLBuilder urlBuilder = new URLBuilder();
357
358       urlBuilder.setValue("module", "Content");
359       urlBuilder.setValue("do", "edit");
360       urlBuilder.setValue("id", id);
361       urlBuilder.setValue("returnurl", requestParser.getParameter("returnurl"));
362
363       if (id!=null) {
364         responseData.put("new", Boolean.FALSE);
365         article = model.makeEntityAdapter("content", mainModule.getById(id));
366
367         EntityUsers user = ServletHelper.getUser(aRequest);
368
369         responseData.put("mayEdit", new Boolean(MirGlobal.accessControl().article().mayEditArticle(user, id)));
370         responseData.put("mayLock", new Boolean(MirGlobal.accessControl().article().mayLockArticle(user, id)));
371         responseData.put("mayForceLock", new Boolean(MirGlobal.accessControl().article().mayForceLockArticle(user, id)));
372         responseData.put("mayUnlock", new Boolean(MirGlobal.accessControl().article().mayUnlockArticle(user, id)));
373       }
374       else {
375         List fields = DatabaseContent.getInstance().getFieldNames();
376         responseData.put("new", Boolean.TRUE);
377         Map emptyArticle = new HashMap();
378         Iterator i = fields.iterator();
379         while (i.hasNext()) {
380           emptyArticle.put(i.next(), null);
381         }
382
383         emptyArticle.put("to_topics", null);
384
385         MirGlobal.localizer().adminInterface().initializeArticle(emptyArticle);
386         article = emptyArticle;
387
388         responseData.put("mayEdit", Boolean.TRUE);
389         responseData.put("mayLock", Boolean.FALSE);
390         responseData.put("mayForceLock", Boolean.FALSE);
391         responseData.put("mayUnlock", Boolean.FALSE);
392
393       }
394       responseData.put("article", article);
395
396       List topicsList = new ArrayList();
397
398       String[] topicCategories = configuration.getStringArray("Mir.Localizer.Admin.TopicLists");
399
400       if (topicCategories.length==0 ) {
401         Map categoryMap = new HashMap();
402         categoryMap.put("key", "topic");
403         categoryMap.put("listtype", "0");
404         categoryMap.put("listparameter", "3");
405         categoryMap.put("items", EntityAdapterEngine.retrieveAdapterList(model, "topic", "", "title", -1, 0));
406         topicsList.add(categoryMap);
407       }
408       else {
409         for (int i = 0; i < topicCategories.length; i++) {
410           try {
411             Map categoryMap = new HashMap();
412             List parts = StringRoutines.splitString(topicCategories[i], ":");
413
414             String key = null;
415             String listtype = "0";
416             String listparameter = "5";
417             String where = "";
418             String order = "";
419
420             if (parts.size() > 0)
421               key = (String) parts.get(0);
422             if (parts.size() > 1)
423               listtype = (String) parts.get(1);
424             if (parts.size() > 2)
425               listparameter = (String) parts.get(2);
426             if (parts.size() > 3)
427               where = (String) parts.get(3);
428             if (parts.size() > 4)
429               order = (String) parts.get(4);
430
431             if (key != null) {
432               categoryMap.put("key", key);
433               categoryMap.put("listtype", listtype);
434               categoryMap.put("listparameter", listparameter);
435               categoryMap.put("items", EntityAdapterEngine.retrieveAdapterList(model, "topic", where, order, -1, 0));
436               topicsList.add(categoryMap);
437             }
438           }
439           catch (Throwable t) {
440             logger.error("error while preparing topics: " + t.toString());
441           }
442         }
443       }
444
445       responseData.put("topics", topicsList);
446
447       responseData.put("returnurl", requestParser.getParameter("returnurl"));
448       responseData.put("thisurl", urlBuilder.getQuery());
449
450       ServletHelper.generateResponse(aResponse.getWriter(), responseData, editGenerator);
451     }
452     catch (Throwable e) {
453       throw new ServletModuleFailure(e);
454     }
455   }
456
457   public void selectparent(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc {
458     try {
459       HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
460       URLBuilder urlBuilder = new URLBuilder();
461
462       urlBuilder.setValue("module", "Content");
463       urlBuilder.setValue("do", "setparent");
464       urlBuilder.setValue("childid", requestParser.getParameter("id"));
465       urlBuilder.setValue("returnurl", requestParser.getParameter("returnurl"));
466
467       returnList(aRequest, aResponse, "", "", 0,
468           Collections.singletonMap("selectarticleurl", urlBuilder.getQuery()));
469     }
470     catch (Throwable e) {
471       throw new ServletModuleFailure(e);
472     }
473   }
474
475   public void listchildren(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc {
476     try {
477       HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
478       String articleId = requestParser.getParameter("article_id");
479
480       if (articleId == null)
481         throw new ServletModuleExc("ServletModuleContent.listchildren: article_id not set!");
482
483       returnList(aRequest, aResponse, "to_content = " + articleId, "webdb_create desc", 0);
484     }
485     catch (Throwable e) {
486       throw new ServletModuleFailure(e);
487     }
488   }
489
490   public void setparent(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc {
491     HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
492     String articleId = requestParser.getParameter("childid");
493     String parentId  = requestParser.getParameter("id");
494     String returnUrl = requestParser.getParameter("returnurl");
495
496     if (!MirGlobal.accessControl().article().mayEditArticle(ServletHelper.getUser(aRequest), articleId))
497       throw new ServletModuleExc("Article has been locked");
498
499     try {
500       EntityContent article = (EntityContent) mainModule.getById(articleId);
501       article.setFieldValue("to_content", parentId);
502       article.setProduced(false);
503       article.update();
504       logAdminUsage(aRequest, articleId, "parent set to " + parentId);
505     }
506     catch(Throwable e) {
507       logger.error("ServletModuleContent.setparent: " + e.getMessage());
508       throw new ServletModuleFailure(e);
509     }
510
511     ServletHelper.redirect(aResponse, returnUrl);
512   }
513
514   public void clearparent(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc {
515     HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
516     String articleId = requestParser.getParameter("id");
517     String returnUrl = requestParser.getParameter("returnurl");
518
519     try {
520       EntityContent article = (EntityContent) mainModule.getById(articleId);
521       article.setFieldValue("to_content", null);
522       article.setProduced(false);
523       article.update();
524       logAdminUsage(aRequest, articleId, "parent cleared");
525     }
526     catch(Throwable e) {
527       e.printStackTrace(logger.asPrintWriter(LoggerWrapper.DEBUG_MESSAGE));
528       logger.error("ServletModuleContent.clearparent: " + e.getMessage());
529
530       throw new ServletModuleFailure("ServletModuleContent.clearparent: " + e.getMessage(), e);
531     }
532
533     ServletHelper.redirect(aResponse, returnUrl);
534   }
535
536   public void showPreview(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc {
537     try {
538       HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
539       String articleId = requestParser.getParameter("id");
540       EntityAdapter article = model.makeEntityAdapter("content", mainModule.getById(articleId));
541       String preview = requestParser.getParameterWithDefault("preview", "default");
542
543       Map generationValues = new HashMap();
544       Generator generator =
545           MirGlobal.localizer().adminInterface().prepareArticlePreview(preview, article, generationValues);
546
547       generator.generate(aResponse.getWriter(), generationValues, logger);
548     }
549     catch (Exception e) {
550       throw new ServletModuleFailure(e);
551     }
552   }
553 }