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.commons; 029 030import org.opencms.configuration.CmsParameterConfiguration; 031import org.opencms.file.CmsProperty; 032import org.opencms.file.CmsPropertyDefinition; 033import org.opencms.file.CmsResource; 034import org.opencms.file.CmsResourceFilter; 035import org.opencms.file.CmsUser; 036import org.opencms.i18n.CmsEncoder; 037import org.opencms.jsp.CmsJspActionElement; 038import org.opencms.main.CmsException; 039import org.opencms.main.CmsLog; 040import org.opencms.main.OpenCms; 041import org.opencms.security.CmsRole; 042import org.opencms.util.CmsStringUtil; 043import org.opencms.workplace.CmsWorkplaceSettings; 044import org.opencms.workplace.I_CmsDialogHandler; 045import org.opencms.workplace.explorer.CmsExplorerTypeSettings; 046 047import java.util.Iterator; 048import java.util.List; 049 050import org.apache.commons.logging.Log; 051 052import jakarta.servlet.http.HttpServletRequest; 053import jakarta.servlet.http.HttpServletResponse; 054import jakarta.servlet.jsp.JspException; 055import jakarta.servlet.jsp.PageContext; 056 057/** 058 * Provides methods for the customized property dialog.<p> 059 * 060 * This is a special dialog that is used for the different resource types in the workplace.<p> 061 * For the xmlpage resource type, this class is extended in the editor subpackage.<p> 062 * 063 * The following files use this class: 064 * <ul> 065 * <li>/commons/property_custom.jsp 066 * </ul> 067 * <p> 068 * 069 * @since 6.0.0 070 */ 071public class CmsPropertyCustom extends CmsPropertyAdvanced { 072 073 /** Value for the action: edit the properties. */ 074 public static final int ACTION_EDIT = 500; 075 076 /** The log object for this class. */ 077 private static final Log LOG = CmsLog.getLog(CmsPropertyCustom.class); 078 079 /** Helper object holding the information about the customized properties. */ 080 private CmsExplorerTypeSettings m_explorerTypeSettings; 081 082 /** Flag to determine if navigation properties are shown. */ 083 private boolean m_showNavigation; 084 085 /** 086 * Public constructor with JSP action element.<p> 087 * 088 * @param jsp an initialized JSP action element 089 */ 090 public CmsPropertyCustom(CmsJspActionElement jsp) { 091 092 super(jsp); 093 } 094 095 /** 096 * Public constructor with JSP variables.<p> 097 * 098 * @param context the JSP page context 099 * @param req the JSP request 100 * @param res the JSP response 101 */ 102 public CmsPropertyCustom(PageContext context, HttpServletRequest req, HttpServletResponse res) { 103 104 this(new CmsJspActionElement(context, req, res)); 105 } 106 107 /** 108 * Performs the edit properties action, will be called by the JSP page.<p> 109 * 110 * @param request the HttpServletRequest 111 * @throws JspException if problems including sub-elements occur 112 */ 113 @Override 114 public void actionEdit(HttpServletRequest request) throws JspException { 115 116 // save initialized instance of this class in request attribute for included sub-elements 117 getJsp().getRequest().setAttribute(SESSION_WORKPLACE_CLASS, this); 118 try { 119 // save the changes only if resource is properly locked 120 if (isEditable()) { 121 performEditOperation(request); 122 } 123 } catch (Throwable e) { 124 // Cms error defining property, show error dialog 125 includeErrorpage(this, e); 126 } 127 } 128 129 /** 130 * Creates the HTML String for the edit properties form.<p> 131 * 132 * @return the HTML output String for the edit properties form 133 */ 134 @Override 135 public String buildEditForm() { 136 137 StringBuffer result = new StringBuffer(2048); 138 139 // check if the properties are editable 140 boolean editable = isEditable(); 141 142 // create the column heads 143 result.append("<table border=\"0\" style=\"width:100%\">\n"); 144 result.append("<tr>\n"); 145 result.append("\t<td class=\"textbold\" nowrap>"); 146 result.append(key(Messages.GUI_PROPERTY_0)); 147 result.append("</td>\n"); 148 result.append("\t<td class=\"textbold\">"); 149 result.append(key(Messages.GUI_PROPERTY_VALUE_0)); 150 result.append("</td>\n"); 151 // empty column for the checkboxes 152 result.append("\t<td class=\"textbold\" style=\"white-space: nowrap;\">"); 153 result.append(" "); 154 result.append("</td>\n"); 155 result.append("</tr>\n"); 156 result.append("<tr><td><span style=\"height: 6px;\"></span></td></tr>\n"); 157 158 // create the text property input rows from explorer type settings 159 result.append(buildTextInput(editable)); 160 161 // show navigation properties if enabled in explorer type settings 162 if (showNavigation()) { 163 result.append(buildNavigationProperties(editable)); 164 } 165 result.append("</table>"); 166 167 return result.toString(); 168 } 169 170 /** 171 * Builds the JavaScript to set the property form values delayed.<p> 172 * 173 * The values of the properties are not inserted directly in the <input> tag, 174 * because there is a display issue when the property values are very long. 175 * This method creates JavaScript to set the property input field values delayed. 176 * On the JSP, the code which is created from this method has to be executed delayed after 177 * the creation of the html form, e.g. in the <body> tag with the attribute 178 * onload="window.setTimeout('doSet()',50);".<p> 179 * 180 * @return the JavaScript to set the property form values delayed 181 */ 182 @Override 183 public String buildSetFormValues() { 184 185 StringBuffer result = new StringBuffer(1024); 186 Iterator<String> i = getExplorerTypeSettings().getProperties().iterator(); 187 // iterate over the customized properties 188 while (i.hasNext()) { 189 String curProperty = i.next(); 190 if (getActiveProperties().containsKey(curProperty)) { 191 CmsProperty property = getActiveProperties().get(curProperty); 192 String propValue = property.getValue(); 193 if (propValue != null) { 194 propValue = propValue.trim(); 195 propValue = CmsStringUtil.escapeJavaScript(propValue); 196 // create the JS output for a single property 197 result.append("\tdocument.getElementById(\""); 198 result.append(PREFIX_VALUE); 199 result.append(curProperty); 200 result.append("\").value = \""); 201 result.append(propValue); 202 result.append("\";\n"); 203 } 204 } 205 } 206 // check if the navigation text property value has to be added 207 if (showNavigation() && getActiveProperties().containsKey(CmsPropertyDefinition.PROPERTY_NAVTEXT)) { 208 CmsProperty property = getActiveProperties().get(CmsPropertyDefinition.PROPERTY_NAVTEXT); 209 String propValue = property.getValue(); 210 if (propValue != null) { 211 propValue = propValue.trim(); 212 propValue = CmsStringUtil.escapeJavaScript(propValue); 213 // create the JS output for a single property 214 result.append("\tdocument.getElementById(\""); 215 result.append(PREFIX_VALUE); 216 result.append(CmsPropertyDefinition.PROPERTY_NAVTEXT); 217 result.append("\").value = \""); 218 result.append(propValue); 219 result.append("\";\n"); 220 } 221 } 222 return result.toString(); 223 } 224 225 /** 226 * Builds a button row with an "ok", a "cancel" and an "advanced" button.<p> 227 * 228 * @param okAttributes additional attributes for the "ok" button 229 * @param cancelAttributes additional attributes for the "cancel" button 230 * @param advancedAttributes additional attributes for the "advanced" button 231 * @return the button row 232 */ 233 @Override 234 public String dialogButtonsOkCancelAdvanced( 235 String okAttributes, 236 String cancelAttributes, 237 String advancedAttributes) { 238 239 if (isEditable()) { 240 int okButton = BUTTON_OK; 241 if ((getParamDialogmode() != null) && getParamDialogmode().startsWith(MODE_WIZARD)) { 242 // in wizard mode, display finish button instead of ok button 243 okButton = BUTTON_FINISH; 244 } 245 // hide "advanced" button 246 if (isHideButtonAdvanced()) { 247 return dialogButtons( 248 new int[] {okButton, BUTTON_CANCEL}, 249 new String[] {okAttributes, cancelAttributes}); 250 } 251 // show "advanced" button 252 return dialogButtons( 253 new int[] {okButton, BUTTON_CANCEL, BUTTON_ADVANCED}, 254 new String[] {okAttributes, cancelAttributes, advancedAttributes}); 255 } else { 256 // hide "advanced" button 257 if (isHideButtonAdvanced()) { 258 return dialogButtons(new int[] {BUTTON_CLOSE}, new String[] {cancelAttributes}); 259 } 260 // show "advanced" button 261 return dialogButtons( 262 new int[] {BUTTON_CLOSE, BUTTON_ADVANCED}, 263 new String[] {cancelAttributes, advancedAttributes}); 264 } 265 } 266 267 /** 268 * Returns the explorer type settings for the current resource type.<p> 269 * 270 * @return the explorer type settings for the current resource type 271 */ 272 public CmsExplorerTypeSettings getExplorerTypeSettings() { 273 274 return m_explorerTypeSettings; 275 } 276 277 /** 278 * Sets the explorer type settings for the current resource type.<p> 279 * 280 * @param typeSettings the explorer type settings for the current resource type 281 */ 282 public void setExplorerTypeSettings(CmsExplorerTypeSettings typeSettings) { 283 284 m_explorerTypeSettings = typeSettings; 285 } 286 287 /** 288 * Sets if navigation properties are shown.<p> 289 * 290 * @param showNav true, if navigation properties are shown, otherwise false 291 */ 292 public void setShowNavigation(boolean showNav) { 293 294 m_showNavigation = showNav; 295 } 296 297 /** 298 * Returns if navigation properties are shown.<p> 299 * 300 * @return true, if navigation properties are shown, otherwise false 301 */ 302 public boolean showNavigation() { 303 304 return m_showNavigation; 305 } 306 307 /** 308 * Builds the HTML code for the special properties of an xmlpage resource.<p> 309 * 310 * @param editable indicates if the properties are editable 311 * @return the HTML code for the special properties of a file resource 312 */ 313 protected StringBuffer buildNavigationProperties(boolean editable) { 314 315 StringBuffer result = new StringBuffer(1024); 316 317 // create "disabled" attribute if properties are not editable 318 String disabled = ""; 319 if (!editable) { 320 disabled = " disabled=\"disabled\""; 321 } 322 323 // create "add to navigation" checkbox 324 result.append(buildTableRowStart(key(Messages.GUI_PROPERTY_ADD_TO_NAV_0))); 325 result.append( 326 "<input type=\"checkbox\" name=\"enablenav\" id=\"enablenav\" value=\"true\" onClick=\"toggleNav();\""); 327 if (getActiveProperties().containsKey(CmsPropertyDefinition.PROPERTY_NAVTEXT) 328 || getActiveProperties().containsKey(CmsPropertyDefinition.PROPERTY_NAVPOS)) { 329 result.append(" checked=\"checked\""); 330 } 331 result.append(disabled); 332 result.append(">"); 333 result.append("</td>\n"); 334 result.append("\t<td class=\"textcenter\">"); 335 result.append(" "); 336 result.append(buildTableRowEnd()); 337 338 // create NavText input row 339 result.append( 340 buildPropertyEntry(CmsPropertyDefinition.PROPERTY_NAVTEXT, key(Messages.GUI_LABEL_NAVTEXT_0), editable)); 341 342 // create NavPos select box row 343 result.append(buildTableRowStart(key(Messages.GUI_CHNAV_INSERT_AFTER_0))); 344 result.append( 345 CmsChnav.buildNavPosSelector( 346 getCms(), 347 getParamResource(), 348 disabled + " id=\"navpos\" class=\"maxwidth noborder\"", 349 getMessages())); 350 // get the old NavPos value and store it in hidden field 351 String navPos = null; 352 try { 353 navPos = getCms().readPropertyObject( 354 getParamResource(), 355 CmsPropertyDefinition.PROPERTY_NAVPOS, 356 false).getValue(); 357 } catch (CmsException e) { 358 // should usually never happen 359 if (LOG.isInfoEnabled()) { 360 LOG.info(e.getLocalizedMessage()); 361 } 362 } 363 if (navPos == null) { 364 navPos = ""; 365 } 366 result.append("<input type=\"hidden\" name=\""); 367 result.append(PREFIX_HIDDEN); 368 result.append(CmsPropertyDefinition.PROPERTY_NAVPOS); 369 result.append("\" value=\""); 370 result.append(navPos); 371 result.append("\">"); 372 result.append("</td>\n"); 373 result.append("\t<td class=\"textcenter\">"); 374 result.append(" "); 375 result.append(buildTableRowEnd()); 376 377 return result; 378 } 379 380 /** 381 * Builds the html for a single text input property row.<p> 382 * 383 * The html does not include the value of the created property, 384 * the values are set delayed (see buildSetFormValues() for details).<p> 385 * 386 * @param propertyName the name of the property 387 * @param propertyTitle the nice name of the property 388 * @param editable indicates if the properties are editable 389 * @return the html for a single text input property row 390 */ 391 protected StringBuffer buildPropertyEntry(String propertyName, String propertyTitle, boolean editable) { 392 393 StringBuffer result = new StringBuffer(256); 394 // create "disabled" attribute if properties are not editable 395 String disabled = ""; 396 if (!editable) { 397 disabled = " disabled=\"disabled\""; 398 } 399 result.append(buildTableRowStart(propertyTitle)); 400 // the property is used, so create text field with checkbox and hidden field 401 CmsProperty currentProperty = getActiveProperties().get(propertyName); 402 String propValue = ""; 403 if (currentProperty != null) { 404 propValue = currentProperty.getValue(); 405 } 406 if (propValue != null) { 407 propValue = propValue.trim(); 408 } 409 propValue = CmsEncoder.escapeXml(propValue); 410 411 // create text input field 412 result.append("<input type=\"text\" class=\"maxwidth\""); 413 result.append(" name=\""); 414 result.append(PREFIX_VALUE); 415 result.append(propertyName); 416 result.append("\" id=\""); 417 result.append(PREFIX_VALUE); 418 result.append(propertyName); 419 result.append("\""); 420 if (editable) { 421 result.append(" onKeyup=\"checkValue('"); 422 result.append(propertyName); 423 result.append("');\""); 424 } 425 result.append(disabled); 426 result.append(">"); 427 428 // create hidden field for value 429 result.append("<input type=\"hidden\" name=\""); 430 result.append(PREFIX_HIDDEN); 431 result.append(propertyName); 432 result.append("\" id=\""); 433 result.append(PREFIX_HIDDEN); 434 result.append(propertyName); 435 result.append("\" value=\""); 436 result.append(propValue); 437 result.append("\">"); 438 result.append("</td>\n"); 439 result.append("\t<td class=\"propertydialog-checkboxcell\">"); 440 441 // create activate/deactivate checkbox 442 result.append("<input type=\"checkbox\" name=\""); 443 result.append(PREFIX_USEPROPERTY); 444 result.append(propertyName); 445 result.append("\" id=\""); 446 result.append(PREFIX_USEPROPERTY); 447 result.append(propertyName); 448 result.append("\" value=\"true\""); 449 if (CmsStringUtil.isNotEmpty(propValue)) { 450 result.append(" checked=\"checked\""); 451 } 452 if (editable) { 453 result.append(" onClick=\"toggleDelete('"); 454 result.append(propertyName); 455 result.append("');\""); 456 } 457 result.append(disabled + ">"); 458 459 result.append(buildTableRowEnd()); 460 return result; 461 } 462 463 /** 464 * Builds the HTML for the end of a table row for a single property.<p> 465 * 466 * @return the HTML code for a table row end 467 */ 468 protected String buildTableRowEnd() { 469 470 return "</td>\n</tr>\n"; 471 } 472 473 /** 474 * Builds the HTML for the start of a table row for a single property.<p> 475 * 476 * @param propertyName the name of the current property 477 * @return the HTML code for the start of a table row 478 */ 479 protected StringBuffer buildTableRowStart(String propertyName) { 480 481 StringBuffer result = new StringBuffer(96); 482 result.append("<tr>\n"); 483 result.append("\t<td style=\"white-space: nowrap;\" unselectable=\"on\">"); 484 result.append(propertyName); 485 result.append("</td>\n"); 486 result.append("\t<td class=\"maxwidth\">"); 487 return result; 488 } 489 490 /** 491 * Builds the HTML for the common text input property values stored in the String array "PROPERTIES".<p> 492 * 493 * @param editable indicates if the properties are editable 494 * @return the HTML code for the common text input fields 495 */ 496 protected StringBuffer buildTextInput(boolean editable) { 497 498 StringBuffer result = new StringBuffer(256); 499 Iterator<String> i = getExplorerTypeSettings().getProperties().iterator(); 500 // iterate over the properties 501 while (i.hasNext()) { 502 String curProperty = i.next(); 503 result.append(buildPropertyEntry(curProperty, curProperty, editable)); 504 } 505 return result; 506 } 507 508 /** 509 * Initializes the explorer type settings for the current resource type.<p> 510 */ 511 protected void initExplorerTypeSettings() { 512 513 try { 514 CmsResource res = getCms().readResource(getParamResource(), CmsResourceFilter.ALL); 515 if (res.isFolder()) { 516 if (!getParamResource().endsWith("/")) { 517 // append folder separator to resource name 518 setParamResource(getParamResource() + "/"); 519 } 520 } 521 String resTypeName = OpenCms.getResourceManager().getResourceType(res.getTypeId()).getTypeName(); 522 // get settings for resource type 523 setExplorerTypeSettings(getSettingsForType(resTypeName)); 524 setShowNavigation(getExplorerTypeSettings().isShowNavigation()); 525 } catch (Throwable e) { 526 // error reading file, show error dialog 527 try { 528 includeErrorpage(this, e); 529 } catch (JspException exc) { 530 LOG.error( 531 Messages.get().getBundle().key(Messages.LOG_ERROR_INCLUDE_FAILED_1, FILE_DIALOG_SCREEN_ERRORPAGE)); 532 } 533 } 534 } 535 536 /** 537 * @see org.opencms.workplace.CmsWorkplace#initWorkplaceRequestValues(org.opencms.workplace.CmsWorkplaceSettings, jakarta.servlet.http.HttpServletRequest) 538 */ 539 @Override 540 protected void initWorkplaceRequestValues(CmsWorkplaceSettings settings, HttpServletRequest request) { 541 542 // fill the parameter values in the get/set methods 543 fillParamValues(request); 544 // get the explorer type settings for the current resource 545 initExplorerTypeSettings(); 546 // set the dialog type 547 setParamDialogtype(DIALOG_TYPE); 548 boolean isPopup = Boolean.valueOf(getParamIsPopup()).booleanValue(); 549 // set the action for the JSP switch 550 if (DIALOG_SHOW_DEFAULT.equals(getParamAction())) { 551 // save changed properties and redirect to the default OpenCms dialog 552 setAction(ACTION_DEFAULT); 553 try { 554 actionEdit(request); 555 sendForward(CmsPropertyAdvanced.URI_PROPERTY_DIALOG, paramsAsParameterMap()); 556 return; 557 } catch (Exception e) { 558 // should usually never happen 559 if (LOG.isInfoEnabled()) { 560 LOG.info(e.getLocalizedMessage()); 561 } 562 } 563 } else if (DIALOG_SAVE_EDIT.equals(getParamAction())) { 564 // save the edited properties 565 if (isPopup) { 566 setAction(ACTION_CLOSEPOPUP_SAVE); 567 } else { 568 setAction(ACTION_SAVE_EDIT); 569 } 570 } else if (DIALOG_CANCEL.equals(getParamAction())) { 571 // save the edited properties 572 if (isPopup) { 573 setAction(ACTION_CLOSEPOPUP); 574 } else { 575 setAction(ACTION_CANCEL); 576 } 577 } else { 578 setAction(ACTION_EDIT); 579 String resName = CmsResource.getName(getParamResource()); 580 if (CmsResource.isTemporaryFileName(resName)) { 581 resName = resName.substring(1); 582 } 583 setParamTitle(key(Messages.GUI_PROPERTIES_1, new Object[] {resName})); 584 } 585 } 586 587 /** 588 * Checks the optional parameters of the handler configuration. <p> 589 * 590 * Decides if the "advanced" button should be shown or not. 591 * The "advanced" button is shown if no parameters are given (default) 592 * or the "hideadvanced" attribute is set to false. The "advanced" button 593 * is hidden only, if "hideadvanced" is true and the user is not a member 594 * of the specified user groups. 595 * 596 * @return false if the "advanced" button is shown (default) <br> 597 * true if the "advanced" button is hidden 598 */ 599 protected boolean isHideButtonAdvanced() { 600 601 I_CmsDialogHandler handler = OpenCms.getWorkplaceManager().getDialogHandler(getDialogHandler()); 602 CmsParameterConfiguration handlerParams = handler.getConfiguration(); 603 if ((handlerParams != null) && handlerParams.containsKey(PARAM_HIDEADVANCED)) { 604 // checks if "hideadvanced" is set to true 605 boolean isHideAdvancedSet = false; 606 List<String> hAdvanced = handlerParams.getList(PARAM_HIDEADVANCED); 607 if (!hAdvanced.isEmpty()) { 608 isHideAdvancedSet = Boolean.valueOf(hAdvanced.get(0)).booleanValue(); 609 } 610 if (isHideAdvancedSet) { 611 // if user has the role root admin 612 if (OpenCms.getRoleManager().hasRole(getCms(), CmsRole.ROOT_ADMIN)) { 613 return false; 614 } 615 if (handlerParams.containsKey(PARAM_SHOWGROUP)) { 616 // check if user is one of the configured groups 617 CmsUser currentUser = getCms().getRequestContext().getCurrentUser(); 618 List<String> confGroups = handlerParams.getList(PARAM_SHOWGROUP); 619 for (String groupName : confGroups) { 620 try { 621 if (getCms().userInGroup(currentUser.getName(), groupName)) { 622 return false; 623 } 624 } catch (CmsException e) { 625 LOG.error(e.getLocalizedMessage(), e); 626 } 627 } 628 } 629 return true; 630 } 631 } 632 return false; 633 } 634 635 /** 636 * Performs the editing of the resources properties.<p> 637 * 638 * @param request the HttpServletRequest 639 * @return true, if the properties were successfully changed, otherwise false 640 * @throws CmsException if editing is not successful 641 */ 642 protected boolean performEditOperation(HttpServletRequest request) throws CmsException { 643 644 boolean useTempfileProject = Boolean.valueOf(getParamUsetempfileproject()).booleanValue(); 645 try { 646 if (useTempfileProject) { 647 switchToTempProject(); 648 } 649 // write the common properties defined in the explorer type settings 650 Iterator<String> i = getExplorerTypeSettings().getProperties().iterator(); 651 // iterate over the properties 652 while (i.hasNext()) { 653 String curProperty = i.next(); 654 String paramValue = request.getParameter(PREFIX_VALUE + curProperty); 655 String oldValue = request.getParameter(PREFIX_HIDDEN + curProperty); 656 writeProperty(curProperty, paramValue, oldValue); 657 } 658 659 // write the navigation properties if enabled 660 if (showNavigation()) { 661 // get the navigation enabled parameter 662 String paramValue = request.getParameter("enablenav"); 663 String oldValue = null; 664 if (Boolean.valueOf(paramValue).booleanValue()) { 665 // navigation enabled, update params 666 paramValue = request.getParameter("navpos"); 667 if (!"-1".equals(paramValue) && !String.valueOf(Float.MAX_VALUE).equals(paramValue)) { 668 // update the property only when it is different from "-1" (meaning no change) 669 oldValue = request.getParameter(PREFIX_HIDDEN + CmsPropertyDefinition.PROPERTY_NAVPOS); 670 writeProperty(CmsPropertyDefinition.PROPERTY_NAVPOS, paramValue, oldValue); 671 } 672 paramValue = request.getParameter(PREFIX_VALUE + CmsPropertyDefinition.PROPERTY_NAVTEXT); 673 oldValue = request.getParameter(PREFIX_HIDDEN + CmsPropertyDefinition.PROPERTY_NAVTEXT); 674 writeProperty(CmsPropertyDefinition.PROPERTY_NAVTEXT, paramValue, oldValue); 675 } else { 676 // navigation disabled, delete property values 677 writeProperty(CmsPropertyDefinition.PROPERTY_NAVPOS, null, null); 678 writeProperty(CmsPropertyDefinition.PROPERTY_NAVTEXT, null, null); 679 } 680 } 681 } finally { 682 if (useTempfileProject) { 683 switchToCurrentProject(); 684 } 685 } 686 return true; 687 } 688 689 /** 690 * Writes a property value for a resource, if the value was changed.<p> 691 * 692 * If a property definition for the resource does not exist, 693 * it is automatically created by this method.<p> 694 * 695 * @param propName the name of the property 696 * @param propValue the new value of the property 697 * @param oldValue the old value of the property 698 * @throws CmsException if something goes wrong 699 */ 700 protected void writeProperty(String propName, String propValue, String oldValue) throws CmsException { 701 702 // get the current property object 703 CmsProperty currentProperty = getActiveProperties().get(propName); 704 if (currentProperty == null) { 705 // new property, create new property object 706 currentProperty = new CmsProperty(); 707 currentProperty.setName(propName); 708 } else { 709 // clone the property, because the original property is frozen 710 currentProperty = currentProperty.cloneAsProperty(); 711 } 712 713 // check if there is a parameter value for the current property 714 boolean emptyParam = true; 715 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(propValue)) { 716 emptyParam = false; 717 } 718 719 if (emptyParam) { 720 // parameter is empty, check if the property has to be deleted 721 if (getActiveProperties().containsKey(propName)) { 722 // lock resource if autolock is enabled 723 checkLock(getParamResource()); 724 // determine the value to delete 725 if (currentProperty.getStructureValue() != null) { 726 currentProperty.setStructureValue(CmsProperty.DELETE_VALUE); 727 currentProperty.setResourceValue(null); 728 } else { 729 currentProperty.setResourceValue(CmsProperty.DELETE_VALUE); 730 currentProperty.setStructureValue(null); 731 } 732 // write the updated property object 733 getCms().writePropertyObject(getParamResource(), currentProperty); 734 } 735 } else { 736 // parameter is not empty, check if the value has changed 737 if (!propValue.equals(oldValue)) { 738 // lock resource if autolock is enabled 739 checkLock(getParamResource()); 740 if ((currentProperty.getStructureValue() == null) && (currentProperty.getResourceValue() == null)) { 741 // new property, determine setting from OpenCms workplace configuration 742 if (OpenCms.getWorkplaceManager().isDefaultPropertiesOnStructure()) { 743 currentProperty.setStructureValue(propValue); 744 currentProperty.setResourceValue(null); 745 } else { 746 currentProperty.setResourceValue(propValue); 747 currentProperty.setStructureValue(null); 748 } 749 } else if (currentProperty.getStructureValue() != null) { 750 // structure value has to be updated 751 currentProperty.setStructureValue(propValue); 752 currentProperty.setResourceValue(null); 753 } else { 754 // resource value has to be updated 755 currentProperty.setResourceValue(propValue); 756 currentProperty.setStructureValue(null); 757 } 758 // set auto-creation of the property to true 759 currentProperty.setAutoCreatePropertyDefinition(true); 760 // write the updated property object 761 getCms().writePropertyObject(getParamResource(), currentProperty); 762 } 763 } 764 } 765}