Bugfix for Foundry: FormItem did not work due to missing hidden fields for the page state

git-svn-id: https://svn.libreccm.org/ccm/trunk@3725 8810af33-2d31-482b-a856-94f89814c4df
master
jensp 2015-11-14 11:22:15 +00:00
parent e34ac38a63
commit 6976da93ab
3 changed files with 155 additions and 59 deletions

View File

@ -18,7 +18,6 @@
*/
package com.arsdigita.cms.formbuilder;
import com.arsdigita.bebop.Component;
import com.arsdigita.bebop.Form;
import com.arsdigita.bebop.Page;
@ -56,15 +55,15 @@ import com.arsdigita.web.Web;
import java.math.BigDecimal;
public class FormItem extends ContentPage implements XMLGenerator {
public static final String BASE_DATA_OBJECT_TYPE =
"com.arsdigita.cms.formbuilder.FormItem";
public static final String BASE_DATA_OBJECT_TYPE
= "com.arsdigita.cms.formbuilder.FormItem";
public static final String REMOTE = "remote";
public static final String REMOTE_URL = "remoteUrl";
public static final String FORM = "form";
public static final String CSS = "css";
public FormItem() {
this(BASE_DATA_OBJECT_TYPE);
}
@ -73,7 +72,6 @@ public class FormItem extends ContentPage implements XMLGenerator {
super(typeName);
}
public FormItem(DataObject obj) {
super(obj);
}
@ -106,7 +104,7 @@ public class FormItem extends ContentPage implements XMLGenerator {
ItemCopier copier) {
if (property.getName().equals(FORM)) {
setAssociation(FORM, (new FormCopier())
.copyForm(((FormItem)src).getForm()));
.copyForm(((FormItem) src).getForm()));
return true;
}
@ -129,36 +127,35 @@ public class FormItem extends ContentPage implements XMLGenerator {
types.close();
return f;
}
throw new DataObjectNotFoundException(
throw new DataObjectNotFoundException(
(String) GlobalizationUtil
.globalize("cms.formbuilder.no_such_form").localize());
}
public PersistentForm getForm() {
return new PersistentForm((DataObject)get(FORM));
return new PersistentForm((DataObject) get(FORM));
}
/**
* This sets a string that can be used to locate a Cascading Style Sheet
* that can be used to style this item.
* This sets a string that can be used to locate a Cascading Style Sheet
* that can be used to style this item.
*/
public void setCSS(String css) {
set(CSS, css);
}
/**
* This returns a string that can be used to locate a
* Cascading Style Sheet that can be used to style this item.
* This returns null if no style sheet has been set.
* This returns a string that can be used to locate a Cascading Style Sheet
* that can be used to style this item. This returns null if no style sheet
* has been set.
*/
public String getCSS() {
return (String)get(CSS);
return (String) get(CSS);
}
/**
* Denotes whether the form is to submit locally or remotely.
* If the form is to be remotely submitted, no validation can be
* performed.
* Denotes whether the form is to submit locally or remotely. If the form is
* to be remotely submitted, no validation can be performed.
*/
public boolean isRemote() {
return Boolean.TRUE.equals(get(REMOTE));
@ -172,7 +169,7 @@ public class FormItem extends ContentPage implements XMLGenerator {
}
/**
* Specifies the URL to which this form will be POSTed.
* Specifies the URL to which this form will be POSTed.
*/
public String getRemoteURL() {
return (String) get(REMOTE_URL);
@ -185,28 +182,30 @@ public class FormItem extends ContentPage implements XMLGenerator {
set(REMOTE_URL, url);
}
protected Form instantiateForm(PersistentForm form,
protected Form instantiateForm(PersistentForm form,
boolean readOnly) {
form.setComponentAddObserver( new BaseAddObserver());
form.setComponentAddObserver(new BaseAddObserver());
Form c = (Form)form.createComponent();
Form c = (Form) form.createComponent();
c.addInitListener(new PlaceholdersInitListener());
c.setMethod(Form.GET);
if (readOnly) {
Traversal t = new Traversal() {
public void act(Component c) {
try {
Widget widget = (Widget)c;
widget.setDisabled();
widget.setReadOnly();
} catch (ClassCastException ex) {
// Nada
}
public void act(Component c) {
try {
Widget widget = (Widget) c;
widget.setDisabled();
widget.setReadOnly();
} catch (ClassCastException ex) {
// Nada
}
};
}
};
t.preorder(c);
}
return c;
}
@ -214,7 +213,7 @@ public class FormItem extends ContentPage implements XMLGenerator {
Element parent,
String useContext) {
PersistentForm form = getForm();
Component c = null;
Component c = null;
try {
c = instantiateForm(
form,
@ -234,7 +233,7 @@ public class FormItem extends ContentPage implements XMLGenerator {
if ("itemAdminSummary".equals(useContext)) {
// Chop off all the parameters to stop bebop stategetting confused
fake = p.process(new NoParametersHttpServletRequest(
state.getRequest()), state.getResponse());
state.getRequest()), state.getResponse());
} else {
// Really serving the user page, so need the params when
// processing the form
@ -247,7 +246,6 @@ public class FormItem extends ContentPage implements XMLGenerator {
Traversal t = new VisibleTraverse(fake);
t.preorder(c);
// Simply embed the bebop xml as a child of the cms:item tag
Element element = parent.newChildElement("cms:item", CMS.CMS_XML_NS);
generateXMLBody(fake, element, c);
@ -263,14 +261,13 @@ public class FormItem extends ContentPage implements XMLGenerator {
}
element.addAttribute(FormBuilderUtil.FORM_ACTION, action);
FormBuilderXMLRenderer renderer =
new FormBuilderXMLRenderer(element);
FormBuilderXMLRenderer renderer = new FormBuilderXMLRenderer(element);
renderer.setWrapAttributes(true);
renderer.setWrapRoot(false);
renderer.setRevisitFullObject(true);
renderer.setWrapObjects(false);
renderer.walk(this, SimpleXMLGenerator.ADAPTER_CONTEXT);
// then, if the component is actually a form, we need
@ -279,14 +276,14 @@ public class FormItem extends ContentPage implements XMLGenerator {
// that does not work because we don't pass in the page state
// although that can always we updated.
if (c instanceof Form) {
Element infoElement =
element.newChildElement(FormBuilderUtil.FORMBUILDER_FORM_INFO,
FormBuilderUtil.FORMBUILDER_XML_NS);
Form f = (Form)c;
Element infoElement = element.newChildElement(
FormBuilderUtil.FORMBUILDER_FORM_INFO,
FormBuilderUtil.FORMBUILDER_XML_NS);
Form f = (Form) c;
Traversal infoTraversal =
new ComponentTraverse(state, ((Form)c).getFormData(state),
infoElement);
Traversal infoTraversal = new ComponentTraverse(state, ((Form) c)
.getFormData(state),
infoElement);
infoTraversal.preorder(f);
}
@ -295,24 +292,26 @@ public class FormItem extends ContentPage implements XMLGenerator {
// do this by iterating through the form data but it does not
// seem like a good idea to just cut and paste the code out
// of the PageState class
fake.setControlEvent(c);
fake.generateXML(element.newChildElement
(FormBuilderUtil.FORMBUILDER_PAGE_STATE,
FormBuilderUtil.FORMBUILDER_XML_NS));
fake.setControlEvent(c);
fake.generateXML(element.newChildElement(
FormBuilderUtil.FORMBUILDER_PAGE_STATE,
FormBuilderUtil.FORMBUILDER_XML_NS));
}
protected void generateXMLBody(PageState state,
Element parent,
Component c) {
// this is a no-op
}
private class VisibleTraverse extends Traversal {
PageState m_state;
VisibleTraverse(PageState state) {
m_state = state;
}
public void act(Component c) {
try {
m_state.setVisible(c, true);
@ -320,5 +319,7 @@ public class FormItem extends ContentPage implements XMLGenerator {
// Nada
}
}
}
}

View File

@ -69,16 +69,16 @@
<xsl:param name="contentitem-tree" tunnel="yes"/>
<form method="post"
name="{./name}"
action="{if(./remote = 'true')
then ./remoteUrl
else ./@formAction}"
name="{$contentitem-tree/name}"
action="{if($contentitem-tree/remote = 'true')
then $contentitem-tree/remoteUrl
else $data-tree//cms:item/@formAction}"
accept-charset="utf-8">
<xsl:if test="not(./remote = 'true')">
<xsl:if test="not($contentitem-tree/remote = 'true')">
<input type="hidden"
value="visited"
name="{concat('form.', ./name)}"/>
name="{concat('form.', $contentitem-tree/name)}"/>
</xsl:if>
<xsl:for-each select="$contentitem-tree/form/component[
@ -97,7 +97,7 @@
</xsl:for-each>
<!-- Hidden internal information fields -->
<xsl:for-each select="./formbuilder:pageState/bebop:pageState">
<xsl:for-each select="$contentitem-tree/formbuilder:pageState/bebop:pageState">
<input type="hidden"
name="{./@name}"
value="{./@value}"/>

View File

@ -0,0 +1,95 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This file controls which CSS files are included for which application.
For more details please refer to the Foundry documentation which should
available at $address-of-your-ccm-installation/themes/foundry/doc/index.jsp
If you only provide a file (a path without a slash in it) Foundry expects
the css file to be found in the styles directory. If you provide a path
with at least one slash in it Foundry uses that relative to the themes root
directory.
For example the file public.css is expected to be found at
styles/public.css. The file /bootstrap/css/bootstrap.min.css is expected to
be found at bootstrap/css/bootstrap.min.css.
If you want to limit the CSS file to a specific media type you can use the
media attribute. In that case, the file is expected in the sub folder
of the styles folder with the name of the media type. For example
<css-file media="screen">portal.css</css-file>
In this case Foundry expects to find the portal.css file at
styles/screen/portal.css.
If you want to use the Less style language you can also set the attribute
less to true. If the also set the setting less-onthefly in conf/global.xml
to true, Foundry will include the Less JavaScript file and transform the
Less file on the fly to CSS if your are in the debug/development mode. If
you enable this feature you have to provide the filename without the
extension. Foundry will add the extension depending if the theme is viewed
in development or producation mode. In development mode, .less is added, in
producation mode .css.
The last attribute is the origin attribute. If set to internal the CSS
file is not loaded from the theme but from Foundry itself. In this theme
this feature is used for the CSS file for the admin applications.
-->
<css-files>
<!-- CSS file used for admin applications like the Content Centre -->
<application name="admin">
<css-file origin="internal">admin.css</css-file>
</application>
<application name="login">
<!-- CSS file used for the Login application -->
<css-file origin="internal">admin.css</css-file>
</application>
<application name="navigation">
<!--
Include CSS files for the navigation application. For our own
CSS file we are using the Less stylesheet language as described
above.
-->
<css-file>fancybox/jquery.fancybox.css?v=2.1.5</css-file>
<css-file>fancybox/helpers/jquery.fancybox-buttons.css?v=1.0.5</css-file>
<css-file>fancybox/helpers/jquery.fancybox-thumbs.css?v=1.0.7</css-file>
<css-file>font-awesome/css/font-awesome.min.css</css-file>
<css-file less="true">libre-blue-flex</css-file>
</application>
<application name="navigation" class="portalGridPage">
<!--
For a portalGridPage we use the same CSS files as for normal
navigation pages, but add the portal.css file.
-->
<css-file>fancybox/jquery.fancybox.css?v=2.1.5</css-file>
<css-file>fancybox/helpers/jquery.fancybox-buttons.css?v=1.0.5</css-file>
<css-file>fancybox/helpers/jquery.fancybox-thumbs.css?v=1.0.7</css-file>
<css-file>font-awesome/css/font-awesome.min.css</css-file>
<css-file media="screen">portal.css</css-file>
<css-file less="true">libre-blue-flex</css-file>
</application>
<application name="none" class="cms-admin">
<!-- Other admin applications -->
<css-file origin="internal">admin.css</css-file>
</application>
<application name="portal">
<!-- Portal pages -->
<css-file>fancybox/jquery.fancybox.css?v=2.1.5</css-file>
<css-file>fancybox/helpers/jquery.fancybox-buttons.css?v=1.0.5</css-file>
<css-file>fancybox/helpers/jquery.fancybox-thumbs.css?v=1.0.7</css-file>
<css-file>font-awesome/css/font-awesome.min.css</css-file>
<css-file origin="internal">portal.css</css-file>
<css-file less="true">libre-blue-flex</css-file>
</application>
<default>
<!--
If there is no entry for the current application we load the
default CSS files and our own.
-->
<css-file>fancybox/jquery.fancybox.css?v=2.1.5</css-file>
<css-file>fancybox/helpers/jquery.fancybox-buttons.css?v=1.0.5</css-file>
<css-file>fancybox/helpers/jquery.fancybox-thumbs.css?v=1.0.7</css-file>
<css-file>font-awesome/css/font-awesome.min.css</css-file>
<css-file less="true">libre-blue-flex</css-file>
</default>
</css-files>