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