1. Project Clover database Tue Dec 20 2016 21:24:09 CET
  2. Package com.xpn.xwiki.web

File EditAction.java

 

Coverage histogram

../../../../img/srcFileCovDistChart8.png
54% of files have more coverage

Code metrics

34
77
7
1
269
135
33
0.43
11
7
4.71

Classes

Class Line # Actions
EditAction 40 77 0% 33 32
0.728813672.9%
 

Contributing tests

No tests hitting this source file were found.

Source view

1    /*
2    * See the NOTICE file distributed with this work for additional
3    * information regarding copyright ownership.
4    *
5    * This is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU Lesser General Public License as
7    * published by the Free Software Foundation; either version 2.1 of
8    * the License, or (at your option) any later version.
9    *
10    * This software is distributed in the hope that it will be useful,
11    * but WITHOUT ANY WARRANTY; without even the implied warranty of
12    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13    * Lesser General Public License for more details.
14    *
15    * You should have received a copy of the GNU Lesser General Public
16    * License along with this software; if not, write to the Free
17    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19    */
20    package com.xpn.xwiki.web;
21   
22    import javax.script.ScriptContext;
23   
24    import org.apache.commons.lang3.StringUtils;
25    import org.apache.commons.lang3.math.NumberUtils;
26    import org.slf4j.Logger;
27    import org.slf4j.LoggerFactory;
28    import org.xwiki.rendering.syntax.Syntax;
29   
30    import com.xpn.xwiki.XWikiContext;
31    import com.xpn.xwiki.XWikiException;
32    import com.xpn.xwiki.doc.XWikiDocument;
33    import com.xpn.xwiki.doc.XWikiLock;
34   
35    /**
36    * Initializes a document before it is edited.
37    *
38    * @version $Id: e7f56dfa8a588e50f2a0a1e67c898e332083bb0f $
39    */
 
40    public class EditAction extends XWikiAction
41    {
42    /**
43    * The object used for logging.
44    */
45    private static final Logger LOGGER = LoggerFactory.getLogger(EditAction.class);
46   
47    /**
48    * Default constructor.
49    */
 
50  58 toggle public EditAction()
51    {
52  58 this.waitForXWikiInitialization = false;
53    }
54   
 
55  126 toggle @Override
56    public String render(XWikiContext context) throws XWikiException
57    {
58  126 try {
59  126 XWikiDocument editedDocument = prepareEditedDocument(context);
60  126 maybeLockDocument(editedDocument, context);
61    } catch (XWikiException e) {
62  0 if (e.getCode() == XWikiException.ERROR_XWIKI_APP_DOCUMENT_NOT_EMPTY) {
63  0 context.put("exception", e);
64  0 return "docalreadyexists";
65    } else {
66  0 throw e;
67    }
68    }
69   
70    // Make sure object property fields are displayed in edit mode.
71    // See XWikiDocument#display(String, BaseObject, XWikiContext)
72    // TODO: Revisit the display mode after the inline action is removed. Is the display mode still needed when
73    // there is only one edit action?
74  126 context.put("display", "edit");
75  126 return "edit";
76    }
77   
78    /**
79    * Determines the edited document (translation) and updates it based on the template specified on the request and
80    * any additional request parameters that overwrite the default values from the template.
81    *
82    * @param context the XWiki context
83    * @return the edited document
84    * @throws XWikiException if something goes wrong
85    */
 
86  129 toggle protected XWikiDocument prepareEditedDocument(XWikiContext context) throws XWikiException
87    {
88    // Determine the edited document (translation).
89  129 XWikiDocument editedDocument = getEditedDocument(context);
90  129 EditForm editForm = (EditForm) context.getForm();
91   
92    // Update the edited document based on the template specified on the request.
93  129 editedDocument.readFromTemplate(editForm, context);
94   
95    // The default values from the template can be overwritten by additional request parameters.
96  129 updateDocumentTitleAndContentFromRequest(editedDocument, context);
97  129 editedDocument.readObjectsFromForm(editForm, context);
98   
99    // Set the current user as creator, author and contentAuthor when the edited document is newly created to avoid
100    // using XWikiGuest instead (because those fields were not previously initialized).
101  129 if (editedDocument.isNew()) {
102  72 editedDocument.setCreatorReference(context.getUserReference());
103  72 editedDocument.setAuthorReference(context.getUserReference());
104  72 editedDocument.setContentAuthorReference(context.getUserReference());
105    }
106   
107    // Expose the edited document on the XWiki context and the Velocity context.
108  129 putDocumentOnContext(editedDocument, context);
109   
110  129 return editedDocument;
111    }
112   
113    /**
114    * There are three important use cases:
115    * <ul>
116    * <li>editing or creating the original translation (for the default language)</li>
117    * <li>editing an existing document translation</li>
118    * <li>creating a new translation.</i>
119    * </ul>
120    * Most of the code deals with the really bad way the default language can be specified (empty string, 'default' or
121    * a real language code).
122    *
123    * @param context the XWiki context
124    * @return the edited document translation based on the language specified on the request
125    * @throws XWikiException if something goes wrong
126    */
 
127  129 toggle private XWikiDocument getEditedDocument(XWikiContext context) throws XWikiException
128    {
129  129 XWikiDocument doc = context.getDoc();
130  129 boolean hasTranslation = doc != context.get("tdoc");
131   
132    // We have to clone the context document because it is cached and the changes we are going to make are valid
133    // only for the duration of the current request.
134  129 doc = doc.clone();
135  129 context.put("doc", doc);
136   
137  129 EditForm editForm = (EditForm) context.getForm();
138  129 doc.readDocMetaFromForm(editForm, context);
139   
140  129 String language = context.getWiki().getLanguagePreference(context);
141  129 if (doc.isNew() && doc.getDefaultLanguage().equals("")) {
142  72 doc.setDefaultLanguage(language);
143    }
144   
145  129 String languageToEdit = StringUtils.isEmpty(editForm.getLanguage()) ? language : editForm.getLanguage();
146   
147    // If no specific language is set or if it is "default" then we edit the current doc.
148  129 if (languageToEdit == null || languageToEdit.equals("default")) {
149  0 languageToEdit = "";
150    }
151    // If the document is new or if the language to edit is the default language then we edit the default
152    // translation.
153  129 if (doc.isNew() || doc.getDefaultLanguage().equals(languageToEdit)) {
154  113 languageToEdit = "";
155    }
156    // If the doc does not exist in the language to edit and the language was not explicitly set in the URL then
157    // we edit the default document translation. This prevents use from creating unneeded translations.
158  129 if (!hasTranslation && StringUtils.isEmpty(editForm.getLanguage())) {
159  126 languageToEdit = "";
160    }
161   
162    // Initialize the translated document.
163  129 XWikiDocument tdoc;
164  129 if (languageToEdit.equals("")) {
165    // Edit the default document translation (default language).
166  129 tdoc = doc;
167  129 if (doc.isNew()) {
168  72 doc.setDefaultLanguage(language);
169  72 doc.setLanguage("");
170    }
171  0 } else if (!hasTranslation && context.getWiki().isMultiLingual(context)) {
172    // Edit a new translation.
173  0 tdoc = new XWikiDocument(doc.getDocumentReference());
174  0 tdoc.setLanguage(languageToEdit);
175  0 tdoc.setDefaultLocale(doc.getDefaultLocale());
176    // Mark the translation. It's important to know whether a document is a translation or not, especially
177    // for the sheet manager which needs to access the objects using the default document not one of its
178    // translations.
179  0 tdoc.setTitle(doc.getTitle());
180  0 tdoc.setContent(doc.getContent());
181  0 tdoc.setSyntax(doc.getSyntax());
182  0 tdoc.setAuthorReference(context.getUserReference());
183  0 tdoc.setStore(doc.getStore());
184    } else {
185    // Edit an existing translation. Clone the translated document object to be sure that the changes we are
186    // going to make will last only for the duration of the current request.
187  0 tdoc = ((XWikiDocument) context.get("tdoc")).clone();
188    }
189   
190  129 return tdoc;
191    }
192   
193    /**
194    * Updates the title and content of the given document with values taken from the 'title' and 'content' request
195    * parameters or based on the document section specified on the request.
196    *
197    * @param document the document whose title and content should be updated
198    * @param context the XWiki context
199    * @throws XWikiException if something goes wrong
200    */
 
201  129 toggle private void updateDocumentTitleAndContentFromRequest(XWikiDocument document, XWikiContext context)
202    throws XWikiException
203    {
204    // Check if section editing is enabled and if a section is specified.
205  129 boolean sectionEditingEnabled = context.getWiki().hasSectionEdit(context);
206  129 int sectionNumber = sectionEditingEnabled ? NumberUtils.toInt(context.getRequest().getParameter("section")) : 0;
207  129 getCurrentScriptContext().setAttribute("sectionNumber", sectionNumber, ScriptContext.ENGINE_SCOPE);
208   
209    // Update the edited content.
210  129 EditForm editForm = (EditForm) context.getForm();
211  129 if (editForm.getContent() != null) {
212  1 document.setContent(editForm.getContent());
213  128 } else if (sectionNumber > 0) {
214  0 document.setContent(document.getContentOfSection(sectionNumber));
215    }
216   
217    // Update the edited title.
218  129 if (editForm.getTitle() != null) {
219  31 document.setTitle(editForm.getTitle());
220  98 } else if (sectionNumber > 0) {
221    // The edited content is either the content of the specified section or the content provided on the
222    // request. We assume the content provided on the request is meant to overwrite the specified section.
223    // In both cases the document content is currently having one section, so we can take its title.
224  0 String sectionTitle = document.getDocumentSection(1).getSectionTitle();
225  0 if (StringUtils.isNotBlank(sectionTitle)) {
226    // We cannot edit the page title while editing a page section so this title is for display only.
227  0 String sectionPlainTitle = document.getRenderedContent(sectionTitle, document.getSyntax().toIdString(),
228    Syntax.PLAIN_1_0.toIdString(), context);
229  0 document.setTitle(localizePlainOrKey("core.editors.content.titleField.sectionEditingFormat",
230    document.getRenderedTitle(Syntax.PLAIN_1_0, context), sectionNumber, sectionPlainTitle));
231    }
232    }
233    }
234   
235    /**
236    * Exposes the given document in the XWiki context and the Velocity context under the 'tdoc' and 'cdoc' keys.
237    *
238    * @param document the document to expose
239    * @param context the XWiki context
240    */
 
241  129 toggle private void putDocumentOnContext(XWikiDocument document, XWikiContext context)
242    {
243  129 context.put("tdoc", document);
244    // Old XWiki applications that are still using the inline action might expect the cdoc (content document) to be
245    // properly set on the context. Let's expose the given document also as cdoc for backward compatibility.
246  129 context.put("cdoc", context.get("tdoc"));
247    }
248   
249    /**
250    * Locks the given document unless it is already locked by a different user and the current user didn't request to
251    * force the lock.
252    *
253    * @param document the document to lock
254    * @param context the XWiki context
255    */
 
256  126 toggle private void maybeLockDocument(XWikiDocument document, XWikiContext context)
257    {
258  126 try {
259  126 XWikiLock lock = document.getLock(context);
260  126 EditForm editForm = (EditForm) context.getForm();
261  126 if (lock == null || lock.getUserName().equals(context.getUser()) || editForm.isLockForce()) {
262  124 document.setLock(context.getUser(), context);
263    }
264    } catch (Exception e) {
265    // Lock should never make XWiki fail, but we should log any related information.
266  0 LOGGER.error("Exception while setting up lock", e);
267    }
268    }
269    }