diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/GenericArticleBody.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/ArticleTextBody.java
similarity index 53%
rename from ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/GenericArticleBody.java
rename to ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/ArticleTextBody.java
index 06d075a91..8202dcfdf 100755
--- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/GenericArticleBody.java
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/ArticleTextBody.java
@@ -30,11 +30,14 @@ import com.arsdigita.cms.ItemSelectionModel;
import org.librecms.contenttypes.Article;
import com.arsdigita.cms.ui.workflow.WorkflowLockedComponentAccess;
+import com.arsdigita.kernel.KernelConfig;
import org.libreccm.cdi.utils.CdiUtil;
import org.libreccm.l10n.LocalizedString;
import org.librecms.contentsection.ContentItemRepository;
+import java.util.Locale;
+
/**
* Displays the current text body of the article and allows the user to edit it,
* by uploading a file or entering text in a text box.
@@ -45,29 +48,32 @@ import org.librecms.contentsection.ContentItemRepository;
* @author Stanislav Freidin (sfreidin@arsdigita.com)
* @author Jens Pelzetter
*/
-public class GenericArticleBody extends TextAssetBody {
+public class ArticleTextBody extends TextBody {
- protected AuthoringKitWizard authoringKitWizard;
- protected ItemSelectionModel itemSelectionModel;
+ private final AuthoringKitWizard authoringKitWizard;
+ private final ItemSelectionModel itemSelectionModel;
+ private final StringParameter selectedLanguageParam;
/**
* Construct a new GenericArticleBody component
*
- * @param itemSelectionModel The {@link ItemSelectionModel} which will be
- * responsible for loading the current item
+ * @param itemSelectionModel The {@link ItemSelectionModel} which will be
+ * responsible for loading the current item
*
- * @param authoringKitWizard The parent wizard which contains the form. The
- * form may use the wizard's methods, such as
- * stepForward and stepBack, in its process
- * listener.
+ * @param authoringKitWizard The parent wizard which contains the form.
+ * The form may use the wizard's methods, such
+ * as stepForward and stepBack, in its process
+ * listener.
+ * @param selectedLanguageParam
*/
- public GenericArticleBody(final ItemSelectionModel itemSelectionModel,
- final AuthoringKitWizard authoringKitWizard,
- final StringParameter selectedLanguageParam) {
+ public ArticleTextBody(final ItemSelectionModel itemSelectionModel,
+ final AuthoringKitWizard authoringKitWizard,
+ final StringParameter selectedLanguageParam) {
- super(new ItemAssetModel(null), selectedLanguageParam);
+ super(itemSelectionModel, selectedLanguageParam);
this.itemSelectionModel = itemSelectionModel;
this.authoringKitWizard = authoringKitWizard;
+ this.selectedLanguageParam = selectedLanguageParam;
// Rest the component when it is hidden
authoringKitWizard
@@ -91,6 +97,7 @@ public class GenericArticleBody extends TextAssetBody {
* Adds the options for the mime type select widget of
* GenericArticleForm and sets the default mime type.
*
+ * @param mimeSelect
*/
@Override
protected void setMimeTypeOptions(final SingleSelect mimeSelect) {
@@ -99,39 +106,26 @@ public class GenericArticleBody extends TextAssetBody {
}
/**
- * Create a new text asset and associate it with the current item
+ * Updates the text for the currently selected locale.
*
* @param state the current page state
- *
- * @return a valid TextAsset
+ * @param text the new text for the currently selected locale
*/
@Override
- protected LocalizedString createTextAsset(final PageState state) {
+ protected void updateText(final PageState state,
+ final String text) {
- final Article article = getGenericArticle(state);
- final LocalizedString text = article.getText();
+ final Article article = getSelectedArticle(state);
+ final String selectedLanguage = (String) state.getValue(
+ selectedLanguageParam);
+ final Locale selectedLocale;
+ if (selectedLanguage == null) {
+ selectedLocale = KernelConfig.getConfig().getDefaultLocale();
+ } else {
+ selectedLocale = new Locale(selectedLanguage);
+ }
- // no need - cg. Text doesn't need a security context,
- // and ownership of text is recorded in text_pages
- // t.setParent(item);
- return text;
- }
-
- /**
- * Set additional parameters of a brand new text asset, such as the parent
- * ID, after the asset has been successfully uploaded
- *
- * @param state the current page state
- * @param text the new TextAsset
- */
- @Override
- protected void updateTextAsset(final PageState state,
- final LocalizedString text) {
-
- final Article article = getGenericArticle(state);
-
- // a.setParent(t);
- article.setText(text);
+ article.getText().addValue(selectedLocale, text);
final ContentItemRepository itemRepo = CdiUtil
.createCdiUtil()
.findBean(ContentItemRepository.class);
@@ -139,59 +133,37 @@ public class GenericArticleBody extends TextAssetBody {
}
/**
- * Get the current GenericArticle
+ * Get the current {@link Article}
*
- * @param state
+ * @param state The current page state.
+ *
+ * @return The currently selected article.
*/
- protected Article getGenericArticle(final PageState state) {
+ protected Article getSelectedArticle(final PageState state) {
return (Article) itemSelectionModel.getSelectedObject(state);
}
@Override
- protected String getTextAssetName() {
- return "text";
+ protected String getTextPropertyName() {
+ return "text";
}
@Override
- public LocalizedString getTextAsset(final PageState state) {
- throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
- }
+ public String getText(final PageState state) {
- /**
- * An ACSObjectSelectionModel that selects the current text asset for the
- * text page
- */
- private static class ItemAssetModel extends ItemSelectionModel {
+ final Article article = getSelectedArticle(state);
- private RequestLocal requestLocal;
-
- public ItemAssetModel(final LongParameter parameter) {
-
- super(parameter);
-
- requestLocal = new RequestLocal() {
-
- @Override
- protected Object initialValue(final PageState state) {
-// final Article t
-// = (Article) ((ItemSelectionModel) getSingleSelectionModel())
-// .getSelectedObject(state);
-// Assert.exists(t);
-// return t.getTextAsset();
-
- throw new UnsupportedOperationException("ToDo");
- }
-
- };
- }
-
-
- @Override
- public boolean isSelected(PageState s) {
- return (getSelectedObject(s) != null);
+ final String selectedLanguage = (String) state
+ .getValue(selectedLanguageParam);
+ final Locale selectedLocale;
+ if (selectedLanguage == null) {
+ selectedLocale = KernelConfig.getConfig().getDefaultLocale();
+ } else {
+ selectedLocale = new Locale(selectedLanguage);
}
+ return article.getText().getValue(selectedLocale);
}
}
diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/PageFileForm.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/PageFileForm.java
new file mode 100644
index 000000000..7a9928c98
--- /dev/null
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/PageFileForm.java
@@ -0,0 +1,269 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.arsdigita.cms.ui.authoring;
+
+import com.arsdigita.bebop.BoxPanel;
+import com.arsdigita.bebop.Form;
+import com.arsdigita.bebop.FormData;
+import com.arsdigita.bebop.FormProcessException;
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.RequestLocal;
+import com.arsdigita.bebop.SaveCancelSection;
+import com.arsdigita.bebop.event.FormProcessListener;
+import com.arsdigita.bebop.event.FormSectionEvent;
+import com.arsdigita.bebop.event.FormValidationListener;
+import com.arsdigita.bebop.form.FormErrorDisplay;
+import com.arsdigita.bebop.parameters.NotNullValidationListener;
+import com.arsdigita.cms.ItemSelectionModel;
+import com.arsdigita.cms.ui.FileUploadSection;
+import com.arsdigita.globalization.GlobalizedMessage;
+import com.arsdigita.util.UncheckedWrapperException;
+
+import org.libreccm.l10n.LocalizedString;
+import org.librecms.CmsConstants;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+
+import javax.activation.MimeType;
+
+/**
+ * A form for editing TextAsset items. Displays a "file upload" widget,
+ * auto-guesses mime type
+ */
+class PageFileForm extends Form implements FormProcessListener,
+ FormValidationListener {
+
+ private final TextBody textBody;
+
+ private SaveCancelSection saveCancelSection;
+ private FileUploadSection fileUploadSection;
+ // Variables saved by validate for processing
+ private RequestLocal fileUploadContent;
+ private RequestLocal fileUploadUsedINSO;
+ /**
+ * The text entry widget
+ */
+ public static final String TEXT_ENTRY = "text_entry";
+
+ /**
+ * Construct a new PageFileForm
+ *
+ * @param itemSelectionModel
+ */
+ public PageFileForm(final TextBody textBody) {
+
+ super("PageFileUpload", new BoxPanel(BoxPanel.VERTICAL));
+
+ this.textBody = textBody;
+
+ setMethod(Form.POST);
+ setEncType("multipart/form-data");
+
+ addWidgets();
+ }
+
+ private void addWidgets() {
+
+ fileUploadSection = new FileUploadSection(
+ new GlobalizedMessage("cms.ui.authoring.text.mime_type"),
+ "text",
+ textBody.getDefaultMimeType());
+
+ fileUploadSection
+ .getFileUploadWidget()
+ .addValidationListener(new NotNullValidationListener());
+ fileUploadSection
+ .getMimeTypeWidget()
+ .setDefaultValue(FileUploadSection.GUESS_MIME);
+ add(fileUploadSection);
+
+ saveCancelSection = new SaveCancelSection();
+ add(saveCancelSection);
+
+ final FormErrorDisplay errorDisplay = new FormErrorDisplay(this);
+ add(errorDisplay);
+
+ addValidationListener(this);
+ addProcessListener(this);
+
+ fileUploadContent = new RequestLocal();
+ fileUploadUsedINSO = new RequestLocal();
+
+ }
+
+ protected String getFileUploadContent(PageState state) {
+ return (String) fileUploadContent.get(state);
+ }
+
+ /**
+ * Make sure that files of this type can be uploaded
+ */
+ private void validateFileType(final MimeType mime, final boolean textType)
+ throws FormProcessException {
+ // boolean validType = textType || ((mime instanceof TextMimeType)
+ // && ((TextMimeType) mime).
+ // allowINSOConvert().booleanValue());
+ boolean validType = true; //ToDo
+ if (!validType) {
+ throw new FormProcessException(new GlobalizedMessage(
+ "cms.ui.authoring.invalid_file_type",
+ CmsConstants.CMS_BUNDLE));
+ }
+ // boolean insoWorks = MimeTypeStatus.getMimeTypeStatus().
+ // getInsoFilterWorks().intValue() == 1;
+ boolean insoWorks = true; //ToDo
+ if (!textType && !insoWorks) {
+ // Can't convert. inso filter is not working. Give message.
+ throw new FormProcessException(new GlobalizedMessage(
+ "cms.ui.authoring.couldnt_convert_missing_inso",
+ CmsConstants.CMS_BUNDLE));
+ }
+ }
+
+ /**
+ * read in the content of the file (in bytes).
+ */
+ private byte[] readFileBytes(final File file) throws FormProcessException {
+ byte[] fileBytes;
+ try (final FileInputStream fs = new FileInputStream(file)) {
+ fileBytes = new byte[fs.available()];
+ fs.read(fileBytes);
+ } catch (IOException ex) {
+ throw new FormProcessException(new GlobalizedMessage(
+ "cms.ui.authoring.unable_to_load_file",
+ CmsConstants.CMS_BUNDLE));
+ }
+ return fileBytes;
+ }
+
+ /**
+ * Convert bytes to String, possibly using INSO filter to convert to HTML
+ * type
+ */
+ private String convertBytes(final byte[] fileBytes, final boolean textType,
+ final boolean[] usedInso) throws
+ FormProcessException {
+ String fileContent;
+ // If mime type is not text type, try to convert to html
+ if (!textType) {
+ fileContent = new String(fileBytes);
+ if (fileContent != null) {
+ // Converted successfully, flag type should be html
+ usedInso[0] = true;
+ } else {
+ throw new FormProcessException(new GlobalizedMessage(
+ "cms.ui.authoring.couldnt_convert_inso_failed",
+ CmsConstants.CMS_BUNDLE));
+ }
+ } else {
+ // Text type, no need to convert
+ final String enc = "UTF-8";
+ try {
+ fileContent = new String(fileBytes, enc);
+ } catch (UnsupportedEncodingException ex) {
+ throw new UncheckedWrapperException(
+ "cannot convert to encoding " + enc, ex);
+ }
+ usedInso[0] = false;
+ }
+ return fileContent;
+ }
+
+ /**
+ * Extract the contents of the HTML Body tag. (Done to prevent base and
+ * other header tags from interfering with page display).
+ */
+ private String extractHTMLBody(final String htmlText) throws
+ FormProcessException {
+ final String lowerCase = htmlText.toLowerCase();
+ int bodyStart = lowerCase.indexOf("
- * Unlike most other authoring components, this component does not require the
- * asset to exist. If the asset does not exist (i.e., if
- * !m_assetModel.isSelected(state)), the upload and editing forms
- * will create a new asset and set it in the model by calling
- * setSelectedObject on the asset selection model. Child classes
- * should override the {@link #createTextAsset(PageState)} method in to create a
- * valid text asset.
- *
- * This component is used primarily in {@link GenericArticleBody} and
- * {@link com.arsdigita.cms.ui.templates.TemplateBody}
- *
- * Note: In CCM NG (version 7 and newer) {@code TextAsset} does not
- * longer exist. Instead fields of type {@link LocalizedString} are used. This
- * class has been adapted to use {@link LocalizedString}. The name of the class
- * etc. has been kept to make the migration easier.
- *
- * @author Stanislav Freidin (sfreidin@arsdigita.com)
- * @version Jens Pelzetter
- */
-public abstract class TextAssetBody
- extends SecurityPropertyEditor
- implements Resettable, AuthoringStepComponent, RequestListener {
-
- public static final String FILE_UPLOAD = "file";
- public static final String TEXT_ENTRY = "text";
-
- private static final String STREAMLINED = "_streamlined";
- private static final String STREAMLINED_DONE = "1";
- private static final CMSConfig CMS_CONFIG = CMSConfig.getConfig();
-
- private final StringParameter streamlinedCreationParam;
- private final StringParameter selectedLanguageParam;
- private ItemSelectionModel assetModel;
-
- /**
- * Construct a new GenericArticleBody component
- *
- * @param assetModel The {@link ItemSelectionModel} which will be
- * responsible for maintaining the current asset
- * @param selectedLanguageParam
- */
- public TextAssetBody(final ItemSelectionModel assetModel,
- final StringParameter selectedLanguageParam) {
- this(assetModel, null, selectedLanguageParam);
- }
-
- /**
- * Construct a new GenericArticleBody component
- *
- * @param assetModel The {@link ItemSelectionModel} which will be
- * responsible for maintaining the current asset
- * @param authoringKitWizard The parent wizard which contains the form. The
- * form may use the wizard's methods, such as
- * stepForward and stepBack, in its process
- * listener.
- * @param selectedLangugeParam
- */
- public TextAssetBody(final ItemSelectionModel assetModel,
- final AuthoringKitWizard authoringKitWizard,
- final StringParameter selectedLangugeParam) {
-
- super();
- this.assetModel = assetModel;
-
- if (authoringKitWizard == null) {
- streamlinedCreationParam = new StringParameter("item_body_done");
- } else {
- streamlinedCreationParam = new StringParameter(
- String.format("%s_body_done",
- authoringKitWizard
- .getContentType()
- .getContentItemClass()
- .getName()));
- }
-
- this.selectedLanguageParam = selectedLangugeParam;
-
- if (!CMS_CONFIG.isHideTextAssetUploadFile()) {
- final PageFileForm pageFileForm = getPageFileForm();
- addFileWidgets(pageFileForm);
- add(FILE_UPLOAD,
- new GlobalizedMessage("cms.ui.upload", CmsConstants.CMS_BUNDLE),
- pageFileForm,
- pageFileForm.getSaveCancelSection().getCancelButton());
- }
-
- final PageTextForm pageTextForm = new PageTextForm();
- addTextWidgets(pageTextForm);
- add(TEXT_ENTRY,
- new GlobalizedMessage("cms.ui.edit", CmsConstants.CMS_BUNDLE),
- pageTextForm,
- pageTextForm.getSaveCancelSection().getCancelButton());
-
- // Specify full path to properties of the text asset
- final DomainObjectPropertySheet sheet = getBodyPropertySheet(assetModel);
- sheet.add(new GlobalizedMessage("cms.ui.authoring.body",
- CmsConstants.CMS_BUNDLE),
- getTextAssetName());
-
- setDisplayComponent(sheet);
-
- getDisplayPane().setClassAttr("invertedPropertyDisplay");
-
- }
-
- /**
- * Determines the name of the property holding the text.
- *
- * @return The name of the property holding the text.
- */
- protected abstract String getTextAssetName();
-
- protected DomainObjectPropertySheet getBodyPropertySheet(
- final ItemSelectionModel assetModel) {
-
- return new TextAssetBodyPropertySheet(assetModel,
- selectedLanguageParam);
- }
-
- /**
- * Adds the options for the mime type select widget of
- * GenericArticleForm and sets the default mime type.
- *
- */
- protected void setMimeTypeOptions(SingleSelect mimeSelect) {
- FileUploadSection.addMimeOptions(mimeSelect, "text");
- mimeSelect.setOptionSelected("text/html");
- }
-
- /**
- * To be overwritten by subclasses, should return the field.
- *
- * @param state
- */
- public abstract LocalizedString getTextAsset(final PageState state);
-
- /**
- * Reset this component to its original state
- *
- * @param state the current page state
- */
- @Override
- public void reset(final PageState state) {
- showDisplayPane(state);
- }
-
- // Create a text asset if it does not exist.
- // This should probably be a method in GenericArticle ?
- protected LocalizedString createOrGetTextAsset(
- final ItemSelectionModel assetModel,
- final PageState state) {
- // Get the text asset or create a new one
- LocalizedString text = getTextAsset(state);
-
- if (text == null) {
- text = createTextAsset(state);
-
- }
-
- return text;
- }
-
- /**
- * Create a brand new TextAsset. Child classes should override
- * this method to do the right thing. The default implementation creates a
- * parent-less TextAsset with a unique name.
- *
- * @param state the current page state
- *
- * @return a valid TextAsset
- */
- protected abstract LocalizedString createTextAsset(PageState state);
-
- /**
- * Set additional parameters of a brand new text asset, such as the parent
- * ID, after the asset has been successfully uploaded
- *
- * @param state the current page state
- * @param text the new TextAsset
- */
- protected abstract void updateTextAsset(PageState state,
- LocalizedString text);
-
- /**
- * Return the ItemSelectionModel which will be used to maintain
- * the current text asset
- *
- * @return
- */
- public ItemSelectionModel getAssetSelectionModel() {
- return assetModel;
- }
-
- /**
- * Forward to the next step if the streamlined creation parameter is turned
- * on _and_ the streamlined_creation global state parameter is set to
- * 'active'
- *
- * @param state the PageState
- */
- protected void maybeForwardToNextStep(final PageState state) {
- if (ContentItemPage.isStreamlinedCreationActive(state)
- && !STREAMLINED_DONE.
- equals(state.getValue(streamlinedCreationParam))) {
- state.setValue(streamlinedCreationParam, STREAMLINED_DONE);
- fireCompletionEvent(state);
- }
- }
-
- /**
- * Cancel streamlined creation for this step if the streamlined creation
- * parameter is turned on _and_ the streamlined_creation global state param
- * is set to 'active'
- *
- * @param state the PageState
- */
- protected void cancelStreamlinedCreation(final PageState state) {
- if (ContentItemPage.isStreamlinedCreationActive(state)) {
- state.setValue(streamlinedCreationParam, STREAMLINED_DONE);
- }
- }
-
- /**
- * Open the edit component if the streamlined creation parameter is turned
- * on _and_ the streamlined_creation global state param is set to 'active'
- *
- * @param event
- */
- @Override
- public void pageRequested(RequestEvent event) {
-
- final PageState state = event.getPageState();
-
- if (ContentItemPage.isStreamlinedCreationActive(state)
- && !STREAMLINED_DONE.
- equals(state.getValue(streamlinedCreationParam))) {
- showComponent(state, TEXT_ENTRY);
- }
- //}
-
- }
-
- /**
- * This is the form that is used to upload files. This method can be used so
- * that a subclass can use their own subclass of PageFileForm.
- *
- * @return
- */
- protected PageFileForm getPageFileForm() {
- return new PageFileForm();
- }
-
- /**
- * A form for editing TextAsset items. Displays a "file upload" widget,
- * auto-guesses mime type
- */
- public class PageFileForm extends Form
- implements FormProcessListener, FormValidationListener {
-
- private SaveCancelSection saveCancelSection;
- private FileUploadSection fileUploadSection;
- // Variables saved by validate for processing
- private RequestLocal fileUploadContent;
- private RequestLocal fileUploadUsedINSO;
- /**
- * The text entry widget
- */
- public static final String TEXT_ENTRY = "text_entry";
-
- /**
- * Construct a new PageFileForm
- */
- public PageFileForm() {
- super("PageFileUpload", new BoxPanel(BoxPanel.VERTICAL));
- setMethod(Form.POST);
- setEncType("multipart/form-data");
- }
-
- protected String getFileUploadContent(PageState state) {
- return (String) fileUploadContent.get(state);
- }
-
- /**
- * Make sure that files of this type can be uploaded
- */
- private void validateFileType(final MimeType mime,
- final boolean textType)
- throws FormProcessException {
-
-// boolean validType = textType || ((mime instanceof TextMimeType)
-// && ((TextMimeType) mime).
-// allowINSOConvert().booleanValue());
- boolean validType = true; //ToDo
-
- if (!validType) {
- throw new FormProcessException(new GlobalizedMessage(
- "cms.ui.authoring.invalid_file_type",
- CmsConstants.CMS_BUNDLE));
- }
-
-// boolean insoWorks = MimeTypeStatus.getMimeTypeStatus().
-// getInsoFilterWorks().intValue() == 1;
- boolean insoWorks = true; //ToDo
-
- if (!textType && !insoWorks) {
- // Can't convert. inso filter is not working. Give message.
- throw new FormProcessException(new GlobalizedMessage(
- "cms.ui.authoring.couldnt_convert_missing_inso",
- CmsConstants.CMS_BUNDLE));
- }
- }
-
- /**
- * read in the content of the file (in bytes).
- */
- private byte[] readFileBytes(final File file)
- throws FormProcessException {
-
- byte[] fileBytes;
- try (final FileInputStream fs = new FileInputStream(file)) {
- fileBytes = new byte[fs.available()];
- fs.read(fileBytes);
- } catch (IOException ex) {
- throw new FormProcessException(new GlobalizedMessage(
- "cms.ui.authoring.unable_to_load_file",
- CmsConstants.CMS_BUNDLE));
- }
- return fileBytes;
- }
-
- /**
- * Convert bytes to String, possibly using INSO filter to convert to
- * HTML type
- */
- private String convertBytes(final byte[] fileBytes,
- final boolean textType,
- final boolean[] usedInso)
- throws FormProcessException {
- String fileContent;
- // If mime type is not text type, try to convert to html
- if (!textType) {
- fileContent = new String(fileBytes);
- if (fileContent != null) {
- // Converted successfully, flag type should be html
- usedInso[0] = true;
- } else {
- throw new FormProcessException(
- new GlobalizedMessage(
- "cms.ui.authoring.couldnt_convert_inso_failed",
- CmsConstants.CMS_BUNDLE));
- }
- } else {
- // Text type, no need to convert
- final String enc = "UTF-8";
- try {
- fileContent = new String(fileBytes, enc);
- } catch (UnsupportedEncodingException ex) {
- throw new UncheckedWrapperException(
- "cannot convert to encoding "
- + enc, ex);
- }
- usedInso[0] = false;
- }
- return fileContent;
- }
-
- /**
- * Extract the contents of the HTML Body tag. (Done to prevent base and
- * other header tags from interfering with page display).
- */
- private String extractHTMLBody(final String htmlText)
- throws FormProcessException {
-
- final String lowerCase = htmlText.toLowerCase();
- int bodyStart = lowerCase.indexOf("
+ * Unlike most other authoring components, this component does not require the
+ * asset to exist. If the asset does not exist (i.e., if
+ * !m_assetModel.isSelected(state)), the upload and editing forms
+ * will create a new asset and set it in the model by calling
+ * setSelectedObject on the asset selection model. Child classes
+ * should override the {@link #createTextAsset(PageState)} method in to create a
+ * valid text asset.
+ *
+ * This component is used primarily in {@link GenericArticleBody} and
+ * {@link com.arsdigita.cms.ui.templates.TemplateBody}
+ *
+ * Note: In CCM NG (version 7 and newer) {@code TextAsset} does not
+ * longer exist. Instead fields of type {@link LocalizedString} are used. This
+ * class has been adapted to use {@link LocalizedString}. The name of the class
+ * etc. has been kept to make the migration easier.
+ *
+ * @author Stanislav Freidin (sfreidin@arsdigita.com)
+ * @version Jens Pelzetter
+ */
+public abstract class TextBody
+ extends SecurityPropertyEditor
+ implements Resettable, AuthoringStepComponent, RequestListener {
+
+ public static final String FILE_UPLOAD = "file";
+ public static final String TEXT_ENTRY = "text";
+
+ private static final String STREAMLINED_DONE = "1";
+ private static final CMSConfig CMS_CONFIG = CMSConfig.getConfig();
+
+ private final StringParameter streamlinedCreationParam;
+ private final StringParameter selectedLanguageParam;
+ private final ItemSelectionModel itemSelectionModel;
+
+ /**
+ * Construct a new GenericArticleBody component
+ *
+ * @param assetModel The {@link ItemSelectionModel} which will be
+ * responsible for maintaining the current
+ * asset
+ * @param selectedLanguageParam Parameter for the currently selected locale.
+ */
+ public TextBody(final ItemSelectionModel assetModel,
+ final StringParameter selectedLanguageParam) {
+
+ this(assetModel, null, selectedLanguageParam);
+ }
+
+ /**
+ * Construct a new GenericArticleBody component
+ *
+ * @param itemSelectionModel The {@link ItemSelectionModel} which will be
+ * responsible for maintaining the current asset
+ * @param authoringKitWizard The parent wizard which contains the form.
+ * The form may use the wizard's methods, such
+ * as stepForward and stepBack, in its process
+ * listener.
+ * @param selectedLangugeParam Parameter for the currently selected locale.
+ */
+ public TextBody(final ItemSelectionModel itemSelectionModel,
+ final AuthoringKitWizard authoringKitWizard,
+ final StringParameter selectedLangugeParam) {
+
+ super();
+ this.itemSelectionModel = itemSelectionModel;
+
+ if (authoringKitWizard == null) {
+ streamlinedCreationParam = new StringParameter("item_body_done");
+ } else {
+ streamlinedCreationParam = new StringParameter(
+ String.format("%s_body_done",
+ authoringKitWizard
+ .getContentType()
+ .getContentItemClass()
+ .getName()));
+ }
+
+ this.selectedLanguageParam = selectedLangugeParam;
+
+ if (!CMS_CONFIG.isHideTextAssetUploadFile()) {
+ final PageFileForm pageFileForm = getPageFileForm();
+ add(FILE_UPLOAD,
+ new GlobalizedMessage("cms.ui.upload", CmsConstants.CMS_BUNDLE),
+ pageFileForm,
+ pageFileForm.getSaveCancelSection().getCancelButton());
+ }
+
+ final PageTextForm pageTextForm = new PageTextForm(this);
+ add(TEXT_ENTRY,
+ new GlobalizedMessage("cms.ui.edit", CmsConstants.CMS_BUNDLE),
+ pageTextForm,
+ pageTextForm.getSaveCancelSection().getCancelButton());
+
+ // Specify full path to properties of the text asset
+ final DomainObjectPropertySheet sheet = getTextBodyPropertySheet(
+ itemSelectionModel);
+ sheet.add(new GlobalizedMessage("cms.ui.article.text",
+ CmsConstants.CMS_BUNDLE),
+ getTextPropertyName());
+
+ setDisplayComponent(sheet);
+
+ getDisplayPane().setClassAttr("invertedPropertyDisplay");
+
+ }
+
+ /**
+ * Determines the name of the property holding the text.
+ *
+ * @return The name of the property holding the text.
+ */
+ protected abstract String getTextPropertyName();
+
+ protected DomainObjectPropertySheet getTextBodyPropertySheet(
+ final ItemSelectionModel itemSelectionModel) {
+
+ final DomainObjectPropertySheet sheet = new DomainObjectPropertySheet(
+ itemSelectionModel);
+
+ return sheet;
+
+// return new TextBodyPropertySheet(itemSelectionModel,
+// selectedLanguageParam);
+ }
+
+ /**
+ * Adds the options for the mime type select widget of
+ * GenericArticleForm and sets the default mime type.
+ *
+ * @param mimeSelect
+ */
+ protected void setMimeTypeOptions(final SingleSelect mimeSelect) {
+ FileUploadSection.addMimeOptions(mimeSelect, "text");
+ mimeSelect.setOptionSelected("text/html");
+ }
+
+ /**
+ * To be overwritten by subclasses, should return the text for the currently
+ * selected locale.
+ *
+ * @param state The current page state
+ *
+ * @return The text of the currently selected locale.
+ */
+ public abstract String getText(final PageState state);
+
+ /**
+ * Reset this component to its original state
+ *
+ * @param state the current page state
+ */
+ @Override
+ public void reset(final PageState state) {
+ showDisplayPane(state);
+ }
+
+ /**
+ * Update the text for the currently selected locale.
+ *
+ * @param state the current page state
+ * @param text the new next text for the currently selected locale.
+ */
+ protected abstract void updateText(PageState state, String text);
+
+ /**
+ * Return the ItemSelectionModel which will be used to maintain
+ * the current text asset
+ *
+ * @return
+ */
+ public ItemSelectionModel getItemSelectionModel() {
+ return itemSelectionModel;
+ }
+
+ /**
+ * Forward to the next step if the streamlined creation parameter is turned
+ * on _and_ the streamlined_creation global state parameter is set to
+ * 'active'
+ *
+ * @param state the PageState
+ */
+ protected void maybeForwardToNextStep(final PageState state) {
+ if (ContentItemPage.isStreamlinedCreationActive(state)
+ && !STREAMLINED_DONE.
+ equals(state.getValue(streamlinedCreationParam))) {
+ state.setValue(streamlinedCreationParam, STREAMLINED_DONE);
+ fireCompletionEvent(state);
+ }
+ }
+
+ /**
+ * Cancel streamlined creation for this step if the streamlined creation
+ * parameter is turned on _and_ the streamlined_creation global state param
+ * is set to 'active'
+ *
+ * @param state the PageState
+ */
+ protected void cancelStreamlinedCreation(final PageState state) {
+ if (ContentItemPage.isStreamlinedCreationActive(state)) {
+ state.setValue(streamlinedCreationParam, STREAMLINED_DONE);
+ }
+ }
+
+ /**
+ * Open the edit component if the streamlined creation parameter is turned
+ * on _and_ the streamlined_creation global state param is set to 'active'
+ *
+ * @param event
+ */
+ @Override
+ public void pageRequested(final RequestEvent event) {
+
+ final PageState state = event.getPageState();
+
+ if (ContentItemPage.isStreamlinedCreationActive(state)
+ && !STREAMLINED_DONE.
+ equals(state.getValue(streamlinedCreationParam))) {
+ showComponent(state, TEXT_ENTRY);
+ }
+ //}
+
+ }
+
+ /**
+ * This is the form that is used to upload files. This method can be used so
+ * that a subclass can use their own subclass of PageFileForm.
+ *
+ * @return The form for uploading a text.
+ */
+ protected PageFileForm getPageFileForm() {
+ return new PageFileForm(this);
+ }
+
+ protected String getDefaultMimeType() {
+ return "text/plain";
+ }
+
+ /**
+ * Registers global state parameter for cancelling streamlined creation
+ */
+ @Override
+ public void register(final Page page) {
+ super.register(page);
+ page.addGlobalStateParam(streamlinedCreationParam);
+ page.addRequestListener(this);
+ }
+
+}
diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/TextAssetBodyPropertySheet.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/TextBodyPropertySheet.java
similarity index 93%
rename from ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/TextAssetBodyPropertySheet.java
rename to ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/TextBodyPropertySheet.java
index 78300f2aa..1bbfac4a4 100755
--- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/TextAssetBodyPropertySheet.java
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/TextBodyPropertySheet.java
@@ -42,17 +42,17 @@ import org.libreccm.l10n.LocalizedString;
* it because it uses so many private inner classes
*
*/
-public class TextAssetBodyPropertySheet extends DomainObjectPropertySheet {
+public class TextBodyPropertySheet extends DomainObjectPropertySheet {
/**
* Construct a new TextAssetBodyPropertySheet
*
- * @param objModel The selection model which feeds domain objects to this
- * property sheet.
+ * @param objModel The selection model which feeds domain
+ * objects to this property sheet.
* @param selectedLanguageParam
*
*/
- public TextAssetBodyPropertySheet(
+ public TextBodyPropertySheet(
final ItemSelectionModel objModel,
final StringParameter selectedLanguageParam) {
@@ -62,8 +62,8 @@ public class TextAssetBodyPropertySheet extends DomainObjectPropertySheet {
}
// Build up the object properties model from the iterator over all properties
- private static class TextAssetBodyPropertiesModel implements
- PropertySheetModel {
+ private static class TextAssetBodyPropertiesModel
+ implements PropertySheetModel {
// public final static String MIME_TYPE_KEY
// = TextAssetBodyLabelCellRenderer.MIME_TYPE_KEY;
@@ -140,8 +140,8 @@ public class TextAssetBodyPropertySheet extends DomainObjectPropertySheet {
public PropertySheetModel makeModel(final PropertySheet sheet,
final PageState state) {
- TextAssetBodyPropertySheet propSheet
- = (TextAssetBodyPropertySheet) sheet;
+ TextBodyPropertySheet propSheet
+ = (TextBodyPropertySheet) sheet;
throw new UnsupportedOperationException("ToDo");
}
diff --git a/ccm-cms/src/main/java/org/librecms/contenttypes/Article.java b/ccm-cms/src/main/java/org/librecms/contenttypes/Article.java
index ecace1344..5101b08e2 100644
--- a/ccm-cms/src/main/java/org/librecms/contenttypes/Article.java
+++ b/ccm-cms/src/main/java/org/librecms/contenttypes/Article.java
@@ -19,6 +19,7 @@
package org.librecms.contenttypes;
import com.arsdigita.cms.contenttypes.ui.ArticlePropertiesStep;
+import com.arsdigita.cms.ui.authoring.ArticleTextBody;
import com.arsdigita.cms.ui.authoring.PageCreateForm;
import java.io.Serializable;
@@ -57,7 +58,15 @@ import org.librecms.contentsection.ContentItem;
descriptionBundle = "org.librecms.CmsResources",
descriptionKey = "cms.contenttypes.shared.basic_properties"
+ ".description",
- order = 1)
+ order = 1),
+ @AuthoringStep(
+ component = ArticleTextBody.class,
+ labelBundle = "org.librecms.CmsResources",
+ labelKey = "cms.contenttypes.shared.body_text.title",
+ descriptionBundle = "org.librecms.CmsResources",
+ descriptionKey = "cms.contenttypes.shared.body_text.description",
+ order = 2
+ )
})
public class Article extends ContentItem implements Serializable {
diff --git a/ccm-cms/src/main/resources/org/librecms/CmsResources.properties b/ccm-cms/src/main/resources/org/librecms/CmsResources.properties
index 50423f1a1..2b67a44e2 100644
--- a/ccm-cms/src/main/resources/org/librecms/CmsResources.properties
+++ b/ccm-cms/src/main/resources/org/librecms/CmsResources.properties
@@ -347,3 +347,7 @@ cms.contenttypes.ui.event.event_type=Event type
cms.contenttypes.ui.event.link_to_map=Link to map
cms.contenttypes.ui.event.cost=Cost
cms.contenttypes.ui.event.end_date_after_start_date=The end date must be later then the start date
+cms.ui.upload=Upload
+cms.ui.authoring.body=Text
+cms.ui.article.text=Text
+cms.ui.authoring.edit_body_text=Edit text
diff --git a/ccm-cms/src/main/resources/org/librecms/CmsResources_de.properties b/ccm-cms/src/main/resources/org/librecms/CmsResources_de.properties
index 97dbb719a..994468bee 100644
--- a/ccm-cms/src/main/resources/org/librecms/CmsResources_de.properties
+++ b/ccm-cms/src/main/resources/org/librecms/CmsResources_de.properties
@@ -344,3 +344,7 @@ cms.contenttypes.ui.event.event_type=Art der Veranstaltung
cms.contenttypes.ui.event.link_to_map=Link zur Karte
cms.contenttypes.ui.event.cost=Kosten
cms.contenttypes.ui.event.end_date_after_start_date=Das End-Datum muss nach dem Start-Datum liegen.
+cms.ui.upload=Hochladen
+cms.ui.authoring.body=Text
+cms.ui.article.text=Text
+cms.ui.authoring.edit_body_text=Text bearbeiten
diff --git a/ccm-cms/src/main/resources/org/librecms/CmsResources_fr.properties b/ccm-cms/src/main/resources/org/librecms/CmsResources_fr.properties
index e81598c41..dd8807e92 100644
--- a/ccm-cms/src/main/resources/org/librecms/CmsResources_fr.properties
+++ b/ccm-cms/src/main/resources/org/librecms/CmsResources_fr.properties
@@ -303,3 +303,7 @@ cms.contenttypes.ui.event.event_type=Event type
cms.contenttypes.ui.event.link_to_map=Link to map
cms.contenttypes.ui.event.cost=Cost
cms.contenttypes.ui.event.end_date_after_start_date=The end date must be later then the start date
+cms.ui.upload=Upload
+cms.ui.authoring.body=Text
+cms.ui.article.text=Text
+cms.ui.authoring.edit_body_text=Edit text