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