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