ccm-core & ccm-cms incorporating
r1637 | chrisg23 | 2007-09-17 12:14:27 +0200 (Mo, 17 Sep 2007) Sourceforge patch 1796099 - allow URL Generators to be registered for specific content types. Requires upgrade script to be run: ccm-run ccm-cms --from-version 6.5.2 --to-version 6.5.3! ------------------------------------------------------------------------ r1638 | chrisg23 | 2007-09-17 13:48:34 +0200 (Mo, 17 Sep 2007) Sourceforge patch 1796156 - allow notes to be shown on basic properties authoring step ------------------------------------------------------------------------ r1639 | chrisg23 | 2007-09-17 15:20:13 +0200 (Mo, 17 Sep 2007) Sourceforge patch 1781131 - workaround to bypass query filtering bug if permission filtering folder contents ------------------------------------------------------------------------ r1641 | chrisg23 | 2007-09-17 15:46:27 +0200 (Mo, 17 Sep 2007) | 1 line Geänderte Pfade: M /trunk/ccm-core/src/com/arsdigita/notification/Notification.java Sourceforge patch 1714842 - if message delete has been specified for a notification, only delete it when the last referring notification is deleted (several notification records may refer to the same message) ------------------------------------------------------------------------ r1642 | chrisg23 | 2007-09-17 16:05:26 +0200 (Mo, 17 Sep 2007) | 1 line Sourceforge patch 1727634 - retain specified ordering when paging through folder contents (previously every time you changed to a new page it reverted to default name ordering) ------------------------------------------------------------------------ r1643 | chrisg23 | 2007-09-17 16:19:06 +0200 (Mo, 17 Sep 2007) | 1 line Sourceforge patch 1783195 - IMPORTANT BUGFIX - if you use fixed length lifecycles with expiry notifications then you are probably affected by this - notifications are not created and sent if you have relied on the default end date set by the lifecycle, only if you explicitly entered a date on the publish form. To fix the timebomb of items that are due to expire without notification, there is a command line program in package uk.gov.westsussex.wsgfl.jobs called CreateMissingNotificationPhases. Package is in ccm-wsx-wsgfl-custom module in contrib area of the repository. To use this, it is best to copy the job class and the accompanying pdl file query-missing-notification-phases to your own custom application, or else install ccm-wsx-wsgfl-custom but strip away everything except those 2 files and the initialiser - removing all bits of the initialiser except the data init. Do not add ccm-wsx-wsgfl-custom to your instance as it is, at it overrides some files in the default Aplaws installation git-svn-id: https://svn.libreccm.org/ccm/trunk@13 8810af33-2d31-482b-a856-94f89814c4dfmaster
parent
576ecedbd1
commit
5dcbb5e070
|
|
@ -2,11 +2,11 @@
|
|||
<ccm:application xmlns:ccm="http://ccm.redhat.com/ccm-project"
|
||||
name="ccm-cms"
|
||||
prettyName="Red Hat CCM Content Management System"
|
||||
version="6.5.2"
|
||||
release="4"
|
||||
version="6.5.3"
|
||||
release="1"
|
||||
webapp="ROOT">
|
||||
<ccm:dependencies>
|
||||
<ccm:requires name="ccm-core" version="6.5.2" relation="ge"/>
|
||||
<ccm:requires name="ccm-core" version="6.5.5" relation="ge"/>
|
||||
</ccm:dependencies>
|
||||
<ccm:contacts>
|
||||
<ccm:contact uri="http://www.redhat.com/software/ccm" type="website"/>
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ model com.arsdigita.cms.workflow;
|
|||
|
||||
import com.arsdigita.workflow.simple.*;
|
||||
import com.arsdigita.kernel.ACSObject;
|
||||
import com.arsdigita.cms.ContentType;
|
||||
|
||||
object type CMSTask extends UserTask {
|
||||
composite CMSTaskType [1..1] taskType = join cms_tasks.task_type_id to cms_task_types.task_type_id;
|
||||
|
|
@ -36,6 +37,7 @@ object type CMSTaskType {
|
|||
object type TaskEventURLGenerator {
|
||||
Integer [1..1] generatorID = cms_task_url_generators.generator_id INTEGER;
|
||||
String [1..1] event = cms_task_url_generators.event VARCHAR(100);
|
||||
ContentType [0..1] contentType = join cms_task_url_generators.content_type to content_types.type_id;
|
||||
String [1..1] urlGeneratorClass = cms_task_url_generators.classname VARCHAR(128);
|
||||
|
||||
object key (generatorID);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
alter table CMS_TASK_URL_GENERATORS
|
||||
add (content_type INTEGER);
|
||||
|
||||
alter table cms_task_url_generators add
|
||||
constraint cms_tas_url_gen_con_ty_f_lz1y5 foreign key (content_type)
|
||||
references content_types(type_id);
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
--
|
||||
-- Copyright (C) 2007 Chris Gilbert. All Rights Reserved.
|
||||
--
|
||||
-- This library is free software; you can redistribute it and/or
|
||||
-- modify it under the terms of the GNU Lesser General Public License
|
||||
-- as published by the Free Software Foundation; either version 2.1 of
|
||||
-- the License, or (at your option) any later version.
|
||||
--
|
||||
-- This library is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
-- Lesser General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU Lesser General Public
|
||||
-- License along with this library; if not, write to the Free Software
|
||||
-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
--
|
||||
-- $Id: oracle-se-6.5.2-6.5.3.sql 293 2005-02-22 15:10:39Z cgilbert $
|
||||
-- $DateTime: 2004/08/16 18:10:38 $
|
||||
|
||||
PROMPT Red Hat Enterprise CMS 6.5.2 -> 6.5.3 Upgrade Script (Oracle)
|
||||
|
||||
@@ ../default/upgrade/6.5.2-6.5.3/cms_task_url_generators_upgrade.sql
|
||||
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
--
|
||||
-- Copyright (C) 2007 Chris Gilbert All Rights Reserved.
|
||||
--
|
||||
-- This library is free software; you can redistribute it and/or
|
||||
-- modify it under the terms of the GNU Lesser General Public License
|
||||
-- as published by the Free Software Foundation; either version 2.1 of
|
||||
-- the License, or (at your option) any later version.
|
||||
--
|
||||
-- This library is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
-- Lesser General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU Lesser General Public
|
||||
-- License along with this library; if not, write to the Free Software
|
||||
-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
--
|
||||
-- $DateTime: 2004/08/17 23:15:09 $
|
||||
|
||||
\echo Red Hat Enterprise CMS 6.5.2 -> 6.5.3 Upgrade Script (PostgreSQL)
|
||||
|
||||
begin;
|
||||
|
||||
\i ../default/upgrade/6.5.2-6.5.3/cms_task_url_generators_upgrade.sql
|
||||
|
||||
commit;
|
||||
|
|
@ -29,5 +29,8 @@
|
|||
<version from="6.5.0" to="6.5.1">
|
||||
<script sql="ccm-cms/upgrade/::database::-6.5.0-6.5.1.sql"/>
|
||||
</version>
|
||||
<version from="6.5.2" to="6.5.3">
|
||||
<script sql="ccm-cms/upgrade/::database::-6.5.2-6.5.3.sql"/>
|
||||
</version>
|
||||
|
||||
</upgrade>
|
||||
|
|
|
|||
|
|
@ -26,8 +26,10 @@ import com.arsdigita.domain.DataObjectNotFoundException;
|
|||
import com.arsdigita.domain.DomainObjectFactory;
|
||||
import com.arsdigita.domain.DomainCollectionIterator;
|
||||
import com.arsdigita.kernel.ACSObject;
|
||||
import com.arsdigita.kernel.Party;
|
||||
import com.arsdigita.kernel.User;
|
||||
import com.arsdigita.kernel.permissions.PermissionService;
|
||||
import com.arsdigita.kernel.permissions.PrivilegeDescriptor;
|
||||
import com.arsdigita.persistence.DataCollection;
|
||||
import com.arsdigita.persistence.DataObject;
|
||||
import com.arsdigita.persistence.DataQuery;
|
||||
|
|
@ -235,14 +237,13 @@ public class Folder extends ContentItem {
|
|||
* @return child items of this folder
|
||||
*/
|
||||
public ItemCollection getItems(boolean bSort) {
|
||||
final DataQuery query = SessionManager.getSession().retrieveQuery
|
||||
(ITEMS_QUERY);
|
||||
|
||||
query.setParameter(PARENT, getID());
|
||||
DataQueryDataCollectionAdapter adapter = new DataQueryDataCollectionAdapter(ITEMS_QUERY, ITEM);
|
||||
adapter.setParameter(PARENT, getID());
|
||||
Assert.unequal(PENDING, getVersion());
|
||||
query.setParameter(VERSION, getVersion());
|
||||
adapter.setParameter(VERSION, getVersion());
|
||||
|
||||
return new ItemCollection(query, bSort);
|
||||
return new ItemCollection(adapter, bSort);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -593,12 +594,30 @@ public class Folder extends ContentItem {
|
|||
private DataQuery m_query;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param adapter an adapter constructed using the query name rather than a
|
||||
* DataQuery object. This constructor must be used if there is any
|
||||
* intention to permission filter the results as only a DataQueryDataCollectionAdapter
|
||||
* constructed using query name has the bug fix to allow permission filtering
|
||||
*
|
||||
* @param bSort whether to sort the collection by isFolder and ID
|
||||
*/
|
||||
public ItemCollection (DataQueryDataCollectionAdapter adapter, boolean bSort) {
|
||||
super(adapter);
|
||||
doAlias(adapter);
|
||||
init(adapter, bSort);
|
||||
}
|
||||
|
||||
public ItemCollection (DataQueryDataCollectionAdapter adapter) {
|
||||
this(adapter, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param query the Data Query to use to retrieve the collection
|
||||
* @param bSort whether to sort the collection by isFolder and ID
|
||||
*/
|
||||
|
||||
//ideally, we wouldn't sort the collection by default and only provide
|
||||
//one constructor. But, that would break the existing API
|
||||
public ItemCollection(DataQuery query, boolean bSort) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (C) 2007 Chris Gilbert All Rights Reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
package com.arsdigita.cms.ui.authoring;
|
||||
|
||||
import com.arsdigita.bebop.Component;
|
||||
import com.arsdigita.cms.ItemSelectionModel;
|
||||
|
||||
/**
|
||||
* class used for decoupled display components that caters
|
||||
* for a callback to provide them with a handle on the ItemSelectionModel
|
||||
* @author chris.gilbert@westsussex.gov.uk
|
||||
*
|
||||
*/
|
||||
public interface AdditionalDisplayComponent extends Component {
|
||||
|
||||
public void setItemSelectionModel (ItemSelectionModel model);
|
||||
|
||||
}
|
||||
|
|
@ -18,6 +18,11 @@
|
|||
*/
|
||||
package com.arsdigita.cms.ui.authoring;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import com.arsdigita.bebop.Component;
|
||||
import com.arsdigita.bebop.Page;
|
||||
import com.arsdigita.bebop.PageState;
|
||||
import com.arsdigita.bebop.event.ActionEvent;
|
||||
|
|
@ -63,6 +68,23 @@ public class SimpleEditStep extends SecurityPropertyEditor
|
|||
private static final String STREAMLINED = "_streamlined";
|
||||
private static final String STREAMLINED_DONE = "1";
|
||||
|
||||
private static List s_additionalDisplayComponents = new ArrayList();
|
||||
|
||||
/**
|
||||
* allow additional display components to be added to all implementations
|
||||
* of SimpleEditStep. This allows shared optional packages such as notes to
|
||||
* display information on the initial authoring page of all content types without
|
||||
* causing dependencies from ccm-cms.
|
||||
*
|
||||
* Any additional components must be added before the edit step is created.
|
||||
* An initialiser is a suitable location
|
||||
*
|
||||
* @param c
|
||||
*/
|
||||
public static void addAdditionalDisplayComponent(AdditionalDisplayComponent c) {
|
||||
s_additionalDisplayComponents.add(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new SimpleEditStep component
|
||||
*
|
||||
|
|
@ -104,6 +126,15 @@ public class SimpleEditStep extends SecurityPropertyEditor
|
|||
showDisplayPane(state);
|
||||
}
|
||||
});
|
||||
|
||||
Iterator it = s_additionalDisplayComponents.iterator();
|
||||
while (it.hasNext()) {
|
||||
|
||||
AdditionalDisplayComponent component = (AdditionalDisplayComponent)it.next();
|
||||
component.setItemSelectionModel(itemModel);
|
||||
addDisplayComponent(component);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -32,9 +32,12 @@ import com.arsdigita.bebop.SimpleContainer;
|
|||
import com.arsdigita.bebop.Table;
|
||||
import com.arsdigita.bebop.event.ActionEvent;
|
||||
import com.arsdigita.bebop.event.ActionListener;
|
||||
import com.arsdigita.bebop.event.ChangeEvent;
|
||||
import com.arsdigita.bebop.event.ChangeListener;
|
||||
import com.arsdigita.bebop.event.TableActionAdapter;
|
||||
import com.arsdigita.bebop.event.TableActionEvent;
|
||||
import com.arsdigita.bebop.event.TableActionListener;
|
||||
import com.arsdigita.bebop.parameters.StringParameter;
|
||||
import com.arsdigita.bebop.table.AbstractTableModelBuilder;
|
||||
import com.arsdigita.bebop.table.DefaultTableCellRenderer;
|
||||
import com.arsdigita.bebop.table.DefaultTableColumnModel;
|
||||
|
|
@ -114,21 +117,15 @@ public class FolderBrowser extends Table {
|
|||
private final static String SORT_KEY_LAST_MODIFIED_DATE = "lastModified";
|
||||
private final static String SORT_KEY_CREATION_DATE = "creationDate";
|
||||
|
||||
private RequestLocal m_sortType = new RequestLocal() {
|
||||
public Object initialValue(PageState state) {
|
||||
return SORT_KEY_NAME;
|
||||
}
|
||||
};
|
||||
|
||||
private final RequestLocal m_sortDirection = new RequestLocal() {
|
||||
public Object initialValue(PageState state) {
|
||||
return SORT_ACTION_UP;
|
||||
}
|
||||
};
|
||||
|
||||
private StringParameter m_sortType = new StringParameter("sortType");
|
||||
private StringParameter m_sortDirection = new StringParameter("sortDirn");
|
||||
|
||||
public FolderBrowser(FolderSelectionModel currentFolder) {
|
||||
//super(new FolderTableModelBuilder(), s_headers);
|
||||
super();
|
||||
m_sortType.setDefaultValue(SORT_KEY_NAME);
|
||||
m_sortDirection.setDefaultValue(SORT_ACTION_UP);
|
||||
|
||||
setModelBuilder(new FolderTableModelBuilder(currentFolder));
|
||||
setColumnModel(new DefaultTableColumnModel(hideIndexColumn() ? s_noIndexHeaders : s_headers));
|
||||
setHeader(new TableHeader(getColumnModel()));
|
||||
|
|
@ -144,7 +141,25 @@ public class FolderBrowser extends Table {
|
|||
((FolderTableModelBuilder)getModelBuilder()).setFolderBrowser(this);
|
||||
|
||||
m_currentFolder = currentFolder;
|
||||
|
||||
/*
|
||||
|
||||
This code should be uncommented if the desired behaviour is for a change
|
||||
of folder to cause reversion to default ordering of contained items
|
||||
(by name ascending). Our feeling is that the user selected ordering
|
||||
should be retained for the duration of the folder browsing session. If
|
||||
anyone wants this alternative behaviour it should be brought in under
|
||||
the control of a config parameter.
|
||||
|
||||
m_currentFolder.addChangeListener(new ChangeListener() {
|
||||
|
||||
public void stateChanged(ChangeEvent e) {
|
||||
PageState state = e.getPageState();
|
||||
state.setValue(m_sortType, m_sortType.getDefaultValue());
|
||||
state.setValue(m_sortDirection, m_sortDirection.getDefaultValue());
|
||||
|
||||
}});
|
||||
*/
|
||||
setClassAttr("dataTable");
|
||||
|
||||
getHeader().setDefaultRenderer(new com.arsdigita.cms.ui.util.DefaultTableCellRenderer());
|
||||
|
|
@ -182,7 +197,8 @@ public class FolderBrowser extends Table {
|
|||
super.register(p);
|
||||
|
||||
p.addComponentStateParam(this, m_currentFolder.getStateParameter());
|
||||
|
||||
p.addComponentStateParam(this, m_sortType);
|
||||
p.addComponentStateParam(this, m_sortDirection);
|
||||
p.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
final PageState state = e.getPageState();
|
||||
|
|
@ -209,11 +225,11 @@ public class FolderBrowser extends Table {
|
|||
String key = state.getControlEventName();
|
||||
String value = state.getControlEventValue();
|
||||
if ( SORT_ACTION_UP.equals(key) ) {
|
||||
m_sortType.set(state, value);
|
||||
m_sortDirection.set(state, SORT_ACTION_UP);
|
||||
state.setValue(m_sortType, value);
|
||||
state.setValue(m_sortDirection, SORT_ACTION_UP);
|
||||
} else if ( SORT_ACTION_DOWN.equals(key) ) {
|
||||
m_sortType.set(state, value);
|
||||
m_sortDirection.set(state, SORT_ACTION_DOWN);
|
||||
state.setValue(m_sortType, value);
|
||||
state.setValue(m_sortDirection, SORT_ACTION_DOWN);
|
||||
} else {
|
||||
super.respond(state);
|
||||
//throw new ServletException("Unknown control event: " + key);
|
||||
|
|
@ -282,9 +298,9 @@ public class FolderBrowser extends Table {
|
|||
itemColl.setRange(new Integer(paginator.getFirst(state)),
|
||||
new Integer(paginator.getLast(state) + 1));
|
||||
|
||||
String sortKey = (String)m_sortType.get(state);
|
||||
String sortKey = (String)state.getValue(m_sortType);
|
||||
String direction = "asc";
|
||||
if (SORT_ACTION_DOWN.equals((String)m_sortDirection.get(state))) {
|
||||
if (SORT_ACTION_DOWN.equals((String)state.getValue(m_sortDirection))) {
|
||||
direction = "desc";
|
||||
}
|
||||
|
||||
|
|
@ -342,9 +358,9 @@ public class FolderBrowser extends Table {
|
|||
boolean isSelected, Object key,
|
||||
int row, int column) {
|
||||
String headerName = (String)((GlobalizedMessage)value).localize();
|
||||
String sortKey = (String)m_sortType.get(state);
|
||||
String sortKey = (String)state.getValue(m_sortType);
|
||||
final boolean isCurrentKey = sortKey.equals(m_key);
|
||||
final String currentSortDirection = (String)m_sortDirection.get(state);
|
||||
final String currentSortDirection = (String)state.getValue(m_sortDirection);
|
||||
String imageURLStub = null;
|
||||
|
||||
if (SORT_ACTION_UP.equals(currentSortDirection)) {
|
||||
|
|
|
|||
|
|
@ -452,25 +452,36 @@ class ItemLifecycleSelectForm extends BaseForm {
|
|||
|
||||
// Apply the new lifecycle.
|
||||
ContentItem pending = item.publish(cycleDef, startDate);
|
||||
final Lifecycle lifecycle = pending.getLifecycle();
|
||||
|
||||
// XXX domlay Whoa. This must be broken for multiphase
|
||||
// lifecycles.
|
||||
|
||||
if (endDate != null) {
|
||||
final Lifecycle lifecycle = pending.getLifecycle();
|
||||
|
||||
|
||||
// update individual phases
|
||||
final PhaseCollection phases = lifecycle.getPhases();
|
||||
|
||||
while (phases.next()) {
|
||||
final Phase phase = phases.getPhase();
|
||||
java.util.Date thisEnd = phase.getEndDate();
|
||||
java.util.Date thisStart = phase.getStartDate();
|
||||
if (thisStart.compareTo(endDate) > 0) {
|
||||
phase.setStartDate(endDate);
|
||||
phase.save();
|
||||
}
|
||||
|
||||
if (thisEnd == null || thisEnd.compareTo(endDate) > 0) {
|
||||
phase.setEndDate(endDate);
|
||||
phase.save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// endOfCycle may be the original date according to lifecycle phase definitions, or endDate if that was before
|
||||
// natural end of lifecycle
|
||||
java.util.Date endOfCycle = lifecycle.getEndDate();
|
||||
if (endOfCycle != null) {
|
||||
|
||||
// if advance notification is requested (!= 0)
|
||||
// add another phase at the start of which the user is notified
|
||||
|
|
@ -487,15 +498,15 @@ class ItemLifecycleSelectForm extends BaseForm {
|
|||
if (notificationHours != null) {
|
||||
notificationPeriod += notificationHours.intValue();
|
||||
}
|
||||
|
||||
|
||||
if (notificationPeriod > 0) {
|
||||
notificationDate =
|
||||
computeNotificationDate(endDate, notificationPeriod);
|
||||
|
||||
computeNotificationDate(endOfCycle, notificationPeriod);
|
||||
s_log.debug("adding custom phase");
|
||||
Phase expirationImminentPhase =
|
||||
lifecycle.addCustomPhase("expirationImminent",
|
||||
new Long(notificationDate.getTime()),
|
||||
new Long(endDate.getTime()));
|
||||
new Long(endOfCycle.getTime()));
|
||||
expirationImminentPhase.
|
||||
setListenerClassName("com.arsdigita.cms.lifecycle.NotifyLifecycleListener");
|
||||
expirationImminentPhase.save();
|
||||
|
|
@ -510,7 +521,7 @@ class ItemLifecycleSelectForm extends BaseForm {
|
|||
item.save();
|
||||
|
||||
final Workflow workflow = m_workflow.getWorkflow(state);
|
||||
try {
|
||||
try {
|
||||
finish(workflow, item, Web.getContext().getUser());
|
||||
} catch (TaskException te) {
|
||||
throw new FormProcessException(te);
|
||||
|
|
@ -524,7 +535,7 @@ class ItemLifecycleSelectForm extends BaseForm {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void finish(Workflow workflow, ContentItem item, User user) throws TaskException {
|
||||
if (workflow != null) {
|
||||
final Engine engine = Engine.getInstance(CMSEngine.CMS_ENGINE_TYPE);
|
||||
|
|
|
|||
|
|
@ -255,13 +255,15 @@ public class CMSTask extends UserTask {
|
|||
Assert.assertNotNull(item, "item associated with this CMSTask");
|
||||
|
||||
String authoringURL = getAuthoringURL(item);
|
||||
String fullURL = URL.there(getTaskType().getURLGenerator(operation).generateURL(item.getID(), getID()), null).getURL();
|
||||
String fullURL = getTaskType().getURLGenerator(operation, item).generateURL(item.getID(), getID());
|
||||
s_log.debug("URL retrieved from generator: " + fullURL);
|
||||
if (!fullURL.startsWith("http")) {
|
||||
// url is not fully qualified
|
||||
fullURL = URL.there(fullURL, null).getURL();
|
||||
|
||||
}
|
||||
// see CMSResources.properties for how these values are used
|
||||
Object[] g11nArgs = new Object[10];
|
||||
// cg - make this configurable. Because our content section managers have access to all
|
||||
// folders, they get all notifications, but they want to know which area it relates to -
|
||||
// first folder in item path tells them. config parameter - full item path or just display name
|
||||
// g11nArgs[0] =((ContentItem)item.getParent()).getPath();
|
||||
Object[] g11nArgs = new Object[11];
|
||||
g11nArgs[0] = item.getDisplayName();
|
||||
g11nArgs[1] = new Double(getTaskType().getID().doubleValue());
|
||||
g11nArgs[2] = fullURL;
|
||||
|
|
@ -283,7 +285,9 @@ public class CMSTask extends UserTask {
|
|||
}
|
||||
g11nArgs[8] = getStartDate();
|
||||
g11nArgs[9] = URL.there(authoringURL, null).getURL();
|
||||
|
||||
//if added to email, allows recipient to identify if the item is in a folder
|
||||
// they are interested in
|
||||
g11nArgs[10] = ((ContentItem)item.getParent()).getPath();
|
||||
String subject = (String) GlobalizationUtil.globalize("cms.ui.workflow.email.subject." + operation,
|
||||
g11nArgs).localize();
|
||||
String body = (String) GlobalizationUtil.globalize("cms.ui.workflow.email.body." + operation,
|
||||
|
|
@ -481,8 +485,10 @@ public class CMSTask extends UserTask {
|
|||
}
|
||||
}
|
||||
}
|
||||
// bugfix - if author is null above then we break out
|
||||
// of loop early. If normal exit and so cursor has already closed then the
|
||||
// next line has no effect
|
||||
hist.close();
|
||||
//hist.close here if not closed
|
||||
if (author == null) {
|
||||
// fallback: creator is always available in audit trail
|
||||
author = item.getCreationUser();
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ package com.arsdigita.cms.workflow;
|
|||
|
||||
import com.arsdigita.cms.ContentItem;
|
||||
import com.arsdigita.cms.ContentSection;
|
||||
import com.arsdigita.cms.ContentType;
|
||||
import com.arsdigita.cms.SecurityManager;
|
||||
import com.arsdigita.cms.ui.ContentItemPage;
|
||||
import com.arsdigita.cms.util.GlobalizationUtil;
|
||||
|
|
@ -168,23 +169,36 @@ public class CMSTaskType extends DomainObject {
|
|||
|
||||
}
|
||||
|
||||
public TaskURLGenerator getURLGenerator(String event) {
|
||||
String key = getID() + " " + event;
|
||||
public TaskURLGenerator getURLGenerator(String event, ContentItem item) {
|
||||
String key = getID() + " " + event + " " + item.getContentType().getID();
|
||||
s_log.debug("looking up url generator for key " + key);
|
||||
TaskURLGenerator generator = (TaskURLGenerator)
|
||||
s_taskURLGeneratorCache.get(key);
|
||||
if (generator == null) {
|
||||
s_log.debug("generator not found in cache");
|
||||
s_log.debug("no generator found in cache");
|
||||
DataAssociationCursor generators = ((DataAssociation)get(URL_GENERATORS)).cursor();
|
||||
generators.addEqualsFilter(TaskEventURLGenerator.EVENT, event);
|
||||
generators.addEqualsFilter(TaskEventURLGenerator.CONTENT_TYPE + "." + ContentType.ID, item.getContentType().getID());
|
||||
try {
|
||||
|
||||
while (generators.next()) {
|
||||
s_log.debug("specific generator found for " + event + " event on task type " + getName());
|
||||
s_log.debug("specific generator found for " + event + " event on task type " + getName() + " for content type " + item.getContentType().getLabel());
|
||||
// generator class available for this specific event and this specific content type
|
||||
generator = ((TaskEventURLGenerator)DomainObjectFactory.newInstance(generators.getDataObject())).getGenerator();
|
||||
generators.close();
|
||||
}
|
||||
if (generator == null) {
|
||||
generators.reset();
|
||||
generators.addEqualsFilter(TaskEventURLGenerator.EVENT, event);
|
||||
generators.addEqualsFilter(TaskEventURLGenerator.CONTENT_TYPE, null);
|
||||
while (generators.next()) {
|
||||
s_log.debug("specific generator found for " + event + " event on task type " + getName() + " for any content type");
|
||||
// generator class available for this specific event
|
||||
generator = ((TaskEventURLGenerator)DomainObjectFactory.newInstance(generators.getDataObject())).getGenerator();
|
||||
generators.close();
|
||||
}
|
||||
}
|
||||
|
||||
if (generator == null) {
|
||||
|
||||
s_log.debug("no specific generator for " + event + " event on task type " + getName()+ ". Revert to default");
|
||||
|
|
|
|||
|
|
@ -18,51 +18,14 @@
|
|||
*/
|
||||
package com.arsdigita.cms.workflow;
|
||||
|
||||
import com.arsdigita.cms.ContentItem;
|
||||
import com.arsdigita.cms.ContentSection;
|
||||
import com.arsdigita.cms.SecurityManager;
|
||||
import com.arsdigita.cms.ui.ContentItemPage;
|
||||
import com.arsdigita.cms.util.GlobalizationUtil;
|
||||
import com.arsdigita.domain.DataObjectNotFoundException;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.arsdigita.domain.DomainObject;
|
||||
import com.arsdigita.domain.DomainObjectFactory;
|
||||
import com.arsdigita.kernel.Group;
|
||||
import com.arsdigita.kernel.KernelHelper;
|
||||
import com.arsdigita.kernel.Party;
|
||||
import com.arsdigita.kernel.User;
|
||||
import com.arsdigita.kernel.UserCollection;
|
||||
import com.arsdigita.kernel.permissions.PermissionService;
|
||||
import com.arsdigita.kernel.permissions.PrivilegeDescriptor;
|
||||
import com.arsdigita.messaging.Message;
|
||||
import com.arsdigita.notification.Notification;
|
||||
import com.arsdigita.persistence.DataAssociation;
|
||||
import com.arsdigita.persistence.DataAssociationCursor;
|
||||
import com.arsdigita.persistence.DataCollection;
|
||||
import com.arsdigita.persistence.DataObject;
|
||||
import com.arsdigita.persistence.DataOperation;
|
||||
import com.arsdigita.persistence.DataQuery;
|
||||
import com.arsdigita.persistence.Filter;
|
||||
import com.arsdigita.persistence.OID;
|
||||
import com.arsdigita.persistence.Session;
|
||||
import com.arsdigita.persistence.SessionManager;
|
||||
import com.arsdigita.persistence.metadata.ObjectType;
|
||||
import com.arsdigita.util.Assert;
|
||||
import com.arsdigita.versioning.TagCollection;
|
||||
import com.arsdigita.versioning.Transaction;
|
||||
import com.arsdigita.versioning.TransactionCollection;
|
||||
import com.arsdigita.versioning.Versions;
|
||||
import com.arsdigita.web.URL;
|
||||
import com.arsdigita.workflow.simple.TaskComment;
|
||||
import com.arsdigita.workflow.simple.TaskException;
|
||||
import com.arsdigita.workflow.simple.UserTask;
|
||||
import org.apache.log4j.Logger;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* This class represents enables fine grained control of the url that is
|
||||
|
|
@ -87,6 +50,7 @@ public class TaskEventURLGenerator extends DomainObject {
|
|||
public static final String EVENT = "event";
|
||||
public static final String URL_GENERATOR_CLASS =
|
||||
"urlGeneratorClass";
|
||||
public static final String CONTENT_TYPE = "contentType";
|
||||
|
||||
private static final Logger s_log = Logger.getLogger(TaskEventURLGenerator.class);
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ import com.arsdigita.bebop.event.FormSectionEvent;
|
|||
import com.arsdigita.bebop.form.FormErrorDisplay;
|
||||
import com.arsdigita.bebop.form.Submit;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
|
|
@ -150,6 +151,7 @@ public class PropertyEditor extends SimpleContainer {
|
|||
private List m_list;
|
||||
private PropertyEditorModelBuilder m_builder;
|
||||
private RequestLocal m_model;
|
||||
private java.util.List m_additionalDisplayComponents = new ArrayList();
|
||||
|
||||
/**
|
||||
* Constructs a new, empty <code>PropertyEditor</code>.
|
||||
|
|
@ -276,6 +278,13 @@ public class PropertyEditor extends SimpleContainer {
|
|||
return (String)m_list.getSelectedKey(state);
|
||||
}
|
||||
|
||||
/**
|
||||
* add an additional component below the list of links
|
||||
* @param c
|
||||
*/
|
||||
public void addDisplayComponent(Component c) {
|
||||
m_additionalDisplayComponents.add(c);
|
||||
}
|
||||
/**
|
||||
* Adds the display component if it has not been added already.
|
||||
*
|
||||
|
|
@ -288,6 +297,10 @@ public class PropertyEditor extends SimpleContainer {
|
|||
|
||||
m_displayPane.add(c);
|
||||
m_displayPane.add(m_list);
|
||||
Iterator it = m_additionalDisplayComponents.iterator();
|
||||
while (it.hasNext()) {
|
||||
m_displayPane.add((Component)it.next());
|
||||
}
|
||||
|
||||
m_display = c;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -552,11 +552,11 @@ public class Table extends BlockStylable implements BebopConstants {
|
|||
* @param p the page that contains this table
|
||||
*/
|
||||
public void register(Page p) {
|
||||
ParameterModel m = getRowSelectionModel().getStateParameter();
|
||||
ParameterModel m = getRowSelectionModel() == null ? null : getRowSelectionModel().getStateParameter();
|
||||
if ( m != null ) {
|
||||
p.addComponentStateParam(this, m);
|
||||
}
|
||||
m = getColumnSelectionModel().getStateParameter();
|
||||
m = getColumnSelectionModel() == null ? null : getColumnSelectionModel().getStateParameter();
|
||||
if ( m != null ) {
|
||||
p.addComponentStateParam(this, m);
|
||||
}
|
||||
|
|
@ -601,7 +601,7 @@ public class Table extends BlockStylable implements BebopConstants {
|
|||
* <code>false</code> otherwise.
|
||||
*/
|
||||
public boolean isSelectedRow(PageState s, Object rowKey) {
|
||||
if ( rowKey == null ) {
|
||||
if ( rowKey == null || getRowSelectionModel() == null) {
|
||||
return false;
|
||||
}
|
||||
return getRowSelectionModel().isSelected(s)
|
||||
|
|
@ -619,7 +619,7 @@ public class Table extends BlockStylable implements BebopConstants {
|
|||
* <code>false</code> otherwise.
|
||||
*/
|
||||
public boolean isSelectedColumn(PageState s, Object column) {
|
||||
if ( column == null ) {
|
||||
if ( column == null || getColumnSelectionModel() == null) {
|
||||
return false;
|
||||
}
|
||||
return getColumnSelectionModel().isSelected(s)
|
||||
|
|
|
|||
|
|
@ -283,6 +283,9 @@ public class TableHeader extends SimpleComponent {
|
|||
* @param column the index of the column to test
|
||||
*/
|
||||
protected boolean isSelected(PageState s, Object key, int column) {
|
||||
if (getTable().getColumnSelectionModel() == null) {
|
||||
return false;
|
||||
}
|
||||
Object sel = getTable()
|
||||
.getColumnSelectionModel().getSelectedKey(s);
|
||||
if(sel == null) {
|
||||
|
|
|
|||
|
|
@ -22,7 +22,9 @@ import com.arsdigita.domain.DataObjectNotFoundException;
|
|||
import com.arsdigita.kernel.ACSObject;
|
||||
import com.arsdigita.kernel.Party;
|
||||
import com.arsdigita.messaging.Message;
|
||||
import com.arsdigita.persistence.DataCollection;
|
||||
import com.arsdigita.persistence.OID;
|
||||
import com.arsdigita.persistence.SessionManager;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
|
|
@ -468,6 +470,17 @@ public class Notification extends ACSObject implements NotificationConstants {
|
|||
if (msg == null) {
|
||||
msgDelete = false;
|
||||
}
|
||||
// find if there are other referring notifications. If so msgdelete = false
|
||||
// so only the last notification tries to delete the message
|
||||
DataCollection notifications = SessionManager.getSession().retrieve(Notification.BASE_DATA_OBJECT_TYPE);
|
||||
notifications.addEqualsFilter(MESSAGE_ID, msg.getID());
|
||||
notifications.addNotEqualsFilter(ID, this.getID());
|
||||
if (notifications.size() > 0) {
|
||||
// other notifications that still refer to the message. Let
|
||||
// the last one out delete the message else foreign key breach
|
||||
// brings down the whole request queue process
|
||||
msgDelete = false;
|
||||
}
|
||||
} else {
|
||||
msg = null;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue