001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (https://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software GmbH & Co. KG, please see the 018 * company website: https://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: https://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.workplace.editors; 029 030import org.opencms.file.CmsFile; 031import org.opencms.file.CmsObject; 032import org.opencms.file.CmsPropertyDefinition; 033import org.opencms.file.CmsResource; 034import org.opencms.file.CmsResourceFilter; 035import org.opencms.i18n.CmsLocaleManager; 036import org.opencms.jsp.CmsJspActionElement; 037import org.opencms.main.CmsException; 038import org.opencms.main.CmsLog; 039import org.opencms.util.CmsStringUtil; 040import org.opencms.workplace.CmsDialog; 041import org.opencms.workplace.CmsWorkplaceSettings; 042import org.opencms.xml.page.CmsXmlPage; 043import org.opencms.xml.page.CmsXmlPageFactory; 044 045import java.util.ArrayList; 046import java.util.Collections; 047import java.util.Iterator; 048import java.util.List; 049import java.util.Locale; 050 051import org.apache.commons.logging.Log; 052 053import jakarta.servlet.http.HttpServletRequest; 054import jakarta.servlet.http.HttpServletResponse; 055import jakarta.servlet.jsp.JspException; 056import jakarta.servlet.jsp.PageContext; 057 058/** 059 * Provides methods for the editor elements dialog.<p> 060 * 061 * The following files use this class: 062 * <ul> 063 * <li>/jsp/editors/dialogs/elements.html 064 * </ul> 065 * <p> 066 * 067 * @since 6.0.0 068 */ 069public class CmsDialogElements extends CmsDialog { 070 071 /** Value for the action: update the elements of the page. */ 072 public static final int ACTION_UPDATE_ELEMENTS = 210; 073 074 /** The dialog type. */ 075 public static final String DIALOG_TYPE = "elementselector"; 076 077 /** Request parameter value for the action: update the elements of the page. */ 078 public static final String DIALOG_UPDATE_ELEMENTS = "updateelements"; 079 080 /** Prefix for the html input field for the body. */ 081 public static final String PREFIX_PARAM_BODY = "element-"; 082 083 /** The log object for this class. */ 084 private static final Log LOG = CmsLog.getLog(CmsDialogElements.class); 085 086 /** Stores the element to change to after an element update operation. */ 087 private String m_changeElement; 088 089 /** List used to store information of all possible elements of the page. */ 090 private List<CmsDialogElement> m_elementList; 091 092 /** The element locale. */ 093 private Locale m_elementLocale; 094 095 // Special parameters used by this dialog 096 /** The element language parameter. */ 097 private String m_paramElementlanguage; 098 099 /** The element name parameter. */ 100 private String m_paramElementname; 101 102 /** The temporary file parameter. */ 103 private String m_paramTempFile; 104 105 /** 106 * Public constructor.<p> 107 * 108 * @param jsp an initialized JSP action element 109 */ 110 public CmsDialogElements(CmsJspActionElement jsp) { 111 112 super(jsp); 113 m_changeElement = ""; 114 } 115 116 /** 117 * Public constructor with JSP variables.<p> 118 * 119 * @param context the JSP page context 120 * @param req the JSP request 121 * @param res the JSP response 122 */ 123 public CmsDialogElements(PageContext context, HttpServletRequest req, HttpServletResponse res) { 124 125 this(new CmsJspActionElement(context, req, res)); 126 m_changeElement = ""; 127 } 128 129 /** 130 * Creates a list of possible elements of a template from the template property "template-elements" 131 * and the elements available in the provided xmlPage.<p> 132 * 133 * @param cms the CmsObject 134 * @param xmlPage the resource to read the elements from 135 * @param xmlPageUri the URI of the resource to read the template property from 136 * @param locale the current element locale 137 * @return the list of elements in a String array with element name, nice name (if present) and mandatory flag 138 */ 139 public static List<CmsDialogElement> computeElements( 140 CmsObject cms, 141 CmsXmlPage xmlPage, 142 String xmlPageUri, 143 Locale locale) { 144 145 List<CmsDialogElement> result = new ArrayList<CmsDialogElement>(); 146 147 if (xmlPage != null) { 148 List<String> elementNames = xmlPage.getNames(locale); 149 150 Iterator<String> i = elementNames.iterator(); 151 while (i.hasNext()) { 152 String name = i.next(); 153 CmsDialogElement element = new CmsDialogElement(name, null, false, false, true); 154 result.add(element); 155 } 156 } 157 158 String currentTemplate = null; 159 try { 160 currentTemplate = cms.readPropertyObject( 161 xmlPageUri, 162 CmsPropertyDefinition.PROPERTY_TEMPLATE, 163 true).getValue(); 164 } catch (CmsException e) { 165 if (LOG.isWarnEnabled()) { 166 LOG.warn(e.getLocalizedMessage(), e); 167 } 168 } 169 if ((currentTemplate != null) && (currentTemplate.length() > 0)) { 170 // template found, check template-elements property 171 String elements = null; 172 try { 173 // read the property from the template file 174 elements = cms.readPropertyObject( 175 currentTemplate, 176 CmsPropertyDefinition.PROPERTY_TEMPLATE_ELEMENTS, 177 false).getValue(null); 178 } catch (CmsException e) { 179 if (LOG.isWarnEnabled()) { 180 LOG.warn(e.getLocalizedMessage(), e); 181 } 182 } 183 if (elements != null) { 184 // elements are defined on template file, merge with available elements 185 List<String> tokens = CmsStringUtil.splitAsList(elements, ',', true); 186 Iterator<String> it = tokens.iterator(); 187 while (it.hasNext()) { 188 String currentElement = it.next(); 189 String niceName = null; 190 boolean mandatory = false; 191 int sepIndex = currentElement.indexOf("|"); 192 if (sepIndex != -1) { 193 // nice name found for current element, extract it 194 niceName = currentElement.substring(sepIndex + 1); 195 currentElement = currentElement.substring(0, sepIndex); 196 } 197 if (currentElement.endsWith("*")) { 198 // element is mandatory 199 mandatory = true; 200 currentElement = currentElement.substring(0, currentElement.length() - 1); 201 } 202 203 CmsDialogElement element = new CmsDialogElement(currentElement, niceName, mandatory, true, false); 204 if (result.contains(element)) { 205 element.setExisting(true); 206 result.remove(element); 207 } 208 result.add(element); 209 } 210 } 211 } 212 213 Collections.sort(result); 214 return result; 215 } 216 217 /** 218 * Creates a list of possible elements of a template from the template property "template-elements" 219 * and the elements available in the provided resource file.<p> 220 * 221 * @param cms the CmsObject 222 * @param xmlPageUri the resource to read the elements from 223 * @param locale the current element locale 224 * @return the list of elements in a String array with element name, nice name (if present) and mandatory flag 225 */ 226 public static List<CmsDialogElement> computeElements(CmsObject cms, String xmlPageUri, Locale locale) { 227 228 CmsXmlPage page = null; 229 try { 230 // read the xmlpage file 231 CmsFile pageFile = cms.readFile(xmlPageUri, CmsResourceFilter.IGNORE_EXPIRATION); 232 page = CmsXmlPageFactory.unmarshal(cms, pageFile); 233 } catch (CmsException e) { 234 LOG.warn(Messages.get().getBundle().key(Messages.LOG_READ_XMLPAGE_FAILED_1, xmlPageUri), e); 235 // xmlpage will be null, only "template-elements" property on template will be checked 236 } 237 return computeElements(cms, page, xmlPageUri, locale); 238 } 239 240 /** 241 * Updates the enabled/diabled status of all elements of the current page.<p> 242 * 243 * @throws JspException if there is an error including the error page 244 */ 245 public void actionUpdateElements() throws JspException { 246 247 try { 248 List<CmsDialogElement> elementList = computeElements(); 249 CmsFile file = getCms().readFile(getParamTempfile(), CmsResourceFilter.IGNORE_EXPIRATION); 250 CmsXmlPage page = CmsXmlPageFactory.unmarshal(getCms(), file); 251 boolean foundMandatory = false; 252 m_changeElement = ""; 253 Iterator<CmsDialogElement> i = elementList.iterator(); 254 while (i.hasNext()) { 255 // get the current list element 256 CmsDialogElement element = i.next(); 257 if (element.isMandantory() 258 || element.getName().equals(getParamElementname()) 259 || Boolean.valueOf( 260 getJsp().getRequest().getParameter(PREFIX_PARAM_BODY + element.getName())).booleanValue()) { 261 if (!element.isExisting()) { 262 // create element in order to enable it properly 263 page.addValue(element.getName(), getElementLocale()); 264 } 265 page.setEnabled(element.getName(), getElementLocale(), true); 266 if (element.isMandantory() && !foundMandatory) { 267 m_changeElement = element.getName(); 268 foundMandatory = true; 269 } 270 } else { 271 if (element.isExisting()) { 272 // remove element if it is already existing 273 page.removeValue(element.getName(), getElementLocale()); 274 } 275 } 276 } 277 // write the temporary file 278 file.setContents(page.marshal()); 279 getCms().writeFile(file); 280 // set the javascript functions which should be executed 281 if (page.isEnabled(getParamElementname(), getElementLocale())) { 282 m_changeElement = getParamElementname(); 283 } else if (!foundMandatory) { 284 if (elementList.size() > 0) { 285 m_changeElement = elementList.get(0).getName(); 286 } 287 } 288 } catch (Throwable e) { 289 // show error dialog 290 setParamMessage(Messages.get().getBundle(getLocale()).key(Messages.ERR_UPDATE_ELEMENTS_0)); 291 includeErrorpage(this, e); 292 } 293 } 294 295 /** 296 * Builds the html String for a form list of all possible page elements.<p> 297 * 298 * @return the html String for a form list 299 */ 300 public String buildElementList() { 301 302 StringBuffer retValue = new StringBuffer(512); 303 retValue.append("<table border=\"0\">\n"); 304 retValue.append("<tr>\n"); 305 retValue.append( 306 "\t<td class=\"textbold\" unselectable=\"on\">" 307 + key(Messages.GUI_EDITOR_DIALOG_ELEMENTS_PAGEELEMENT_0) 308 + "</td>\n"); 309 retValue.append( 310 "\t<td class=\"textbold\" unselectable=\"on\"> " 311 + key(Messages.GUI_EDITOR_DIALOG_ELEMENTS_ENABLED_0) 312 + " </td>\n"); 313 retValue.append("</tr>\n"); 314 retValue.append("<tr><td colspan=\"2\"><span style=\"height: 6px;\"></span></td></tr>\n"); 315 316 try { 317 318 // get the list of all possible elements 319 List<CmsDialogElement> elementList = computeElements(); 320 321 // get all present bodies from the temporary file 322 CmsFile file = getCms().readFile(getParamTempfile(), CmsResourceFilter.IGNORE_EXPIRATION); 323 CmsXmlPage page = CmsXmlPageFactory.unmarshal(getCms(), file); 324 325 // show all possible elements 326 Iterator<CmsDialogElement> i = elementList.iterator(); 327 while (i.hasNext()) { 328 // get the current list element 329 CmsDialogElement element = i.next(); 330 // build an element row 331 retValue.append("<tr>\n"); 332 retValue.append("\t<td style=\"white-space: nowrap;\" unselectable=\"on\">" + element.getNiceName()); 333 retValue.append("</td>\n"); 334 retValue.append("\t<td class=\"textcenter\" unselectable=\"on\"><input type=\"checkbox\" name=\""); 335 retValue.append(PREFIX_PARAM_BODY); 336 retValue.append(element.getName()); 337 retValue.append("\" value=\"true\""); 338 339 if ((!page.hasValue(element.getName(), getElementLocale()) && element.isMandantory()) 340 || page.isEnabled(element.getName(), getElementLocale())) { 341 retValue.append(" checked=\"checked\""); 342 } 343 if (element.isMandantory() || element.getName().equals(getParamElementname())) { 344 retValue.append(" disabled=\"disabled\""); 345 } 346 retValue.append(">"); 347 retValue.append("<script >registerElement(\""); 348 349 retValue.append(element.getName()); 350 retValue.append("\", "); 351 retValue.append(page.isEnabled(element.getName(), getElementLocale())); 352 retValue.append(");</script>"); 353 354 retValue.append("</td>\n"); 355 retValue.append("</tr>\n"); 356 } 357 358 } catch (CmsException e) { 359 // should usually never happen 360 if (LOG.isInfoEnabled()) { 361 LOG.info(e.getLocalizedMessage(), e); 362 } 363 } 364 365 retValue.append("</table>\n"); 366 return retValue.toString(); 367 } 368 369 /** 370 * Creates a list of possible elements of a template from the template property "template-elements".<p> 371 * 372 * @return the list of elements in a String array with element name, nice name (if present) and mandatory flag 373 */ 374 public List<CmsDialogElement> computeElements() { 375 376 if (m_elementList == null) { 377 m_elementList = computeElements(getCms(), getParamTempfile(), getElementLocale()); 378 } 379 return m_elementList; 380 } 381 382 /** 383 * Returns the element name that has to be changed.<p> 384 * 385 * @return the element name that has to be changed 386 */ 387 public String getChangeElement() { 388 389 return m_changeElement; 390 } 391 392 /** 393 * Returns the current element locale.<p> 394 * 395 * @return the current element locale 396 */ 397 public Locale getElementLocale() { 398 399 if (m_elementLocale == null) { 400 m_elementLocale = CmsLocaleManager.getLocale(getParamElementlanguage()); 401 } 402 return m_elementLocale; 403 } 404 405 /** 406 * Returns the current element language.<p> 407 * 408 * @return the current element language 409 */ 410 public String getParamElementlanguage() { 411 412 return m_paramElementlanguage; 413 } 414 415 /** 416 * Returns the current element name.<p> 417 * 418 * @return the current element name 419 */ 420 public String getParamElementname() { 421 422 return m_paramElementname; 423 } 424 425 /** 426 * Returns the name of the temporary file.<p> 427 * 428 * @return the name of the temporary file 429 */ 430 public String getParamTempfile() { 431 432 return m_paramTempFile; 433 } 434 435 /** 436 * Sets the current element language.<p> 437 * 438 * @param elementLanguage the current element language 439 */ 440 public void setParamElementlanguage(String elementLanguage) { 441 442 m_paramElementlanguage = elementLanguage; 443 } 444 445 /** 446 * Sets the current element name.<p> 447 * 448 * @param elementName the current element name 449 */ 450 public void setParamElementname(String elementName) { 451 452 m_paramElementname = elementName; 453 } 454 455 /** 456 * Sets the name of the temporary file.<p> 457 * 458 * @param fileName the name of the temporary file 459 */ 460 public void setParamTempfile(String fileName) { 461 462 m_paramTempFile = fileName; 463 } 464 465 /** 466 * @see org.opencms.workplace.CmsWorkplace#initWorkplaceRequestValues(org.opencms.workplace.CmsWorkplaceSettings, jakarta.servlet.http.HttpServletRequest) 467 */ 468 @Override 469 protected void initWorkplaceRequestValues(CmsWorkplaceSettings settings, HttpServletRequest request) { 470 471 // fill the parameter values in the get/set methods 472 fillParamValues(request); 473 // set the dialog type 474 setParamDialogtype(DIALOG_TYPE); 475 // set the action for the JSP switch 476 if (DIALOG_UPDATE_ELEMENTS.equals(getParamAction())) { 477 setAction(ACTION_UPDATE_ELEMENTS); 478 } else { 479 setAction(ACTION_DEFAULT); 480 // build title for delete dialog 481 setParamTitle( 482 key( 483 Messages.GUI_EDITOR_DIALOG_ELEMENTS_TITLE_1, 484 new Object[] {CmsResource.getName(getParamResource())})); 485 } 486 } 487}