Skip to content

Commit

Permalink
Fixed problem with publishing sibling relations (github issue #805).
Browse files Browse the repository at this point in the history
After changing the links in an XML content and publishing it without its
siblings, the siblings would previously show up as unchanged in the
Explorer despite the fact that their relations have been changed to
reflect the changed content. This has been changed so that both
unpublished siblings will have the 'changed' state and need to be
published.
  • Loading branch information
gWestenberger committed Sep 27, 2024
1 parent 5eab9d4 commit 76c7006
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 42 deletions.
89 changes: 61 additions & 28 deletions src/org/opencms/db/CmsDriverManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@

import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
Expand Down Expand Up @@ -2802,7 +2803,9 @@ public void deleteHistoricalVersions(
I_CmsReport.FORMAT_HEADLINE);
} else {
report.println(
Messages.get().container(Messages.RPT_START_DELETE_DEL_VERSIONS_1, Integer.valueOf(versionsDeleted)),
Messages.get().container(
Messages.RPT_START_DELETE_DEL_VERSIONS_1,
Integer.valueOf(versionsDeleted)),
I_CmsReport.FORMAT_HEADLINE);
}
List<I_CmsHistoryResource> resources = getHistoryDriver(dbc).getAllDeletedEntries(dbc);
Expand Down Expand Up @@ -9942,26 +9945,27 @@ public void updateLog(CmsDbContext dbc) throws CmsDataAccessException {
* @param dbc the db context
* @param resource the resource to update the relations for
* @param links the links to consider for updating
* @param updateSiblingState if true, sets the state of siblings whose relations have changed to 'changed' (unless they are new or deleted)
*
* @throws CmsException if something goes wrong
*
* @see CmsSecurityManager#updateRelationsForResource(CmsRequestContext, CmsResource, List)
*/
public void updateRelationsForResource(CmsDbContext dbc, CmsResource resource, List<CmsLink> links)
public void updateRelationsForResource(
CmsDbContext dbc,
CmsResource resource,
List<CmsLink> links,
boolean updateSiblingState)
throws CmsException {

deleteRelationsWithSiblings(dbc, resource);

// build the links again only if needed
if ((links == null) || links.isEmpty()) {
return;
if (links == null) {
links = new ArrayList<>();
}
// the set of written relations
Set<CmsRelation> writtenRelations = new HashSet<CmsRelation>();

// create new relation information
I_CmsVfsDriver vfsDriver = getVfsDriver(dbc);
Iterator<CmsLink> itLinks = links.iterator();
Set<CmsRelation> relationsForOriginalResource = new HashSet<>();
while (itLinks.hasNext()) {
CmsLink link = itLinks.next();
if (link.isInternal()) { // only update internal links
Expand Down Expand Up @@ -9990,26 +9994,54 @@ public void updateRelationsForResource(CmsDbContext dbc, CmsResource resource, L
link.getStructureId(),
destPath,
link.getType());

// do not write twice the same relation
if (writtenRelations.contains(originalRelation)) {
continue;
}
writtenRelations.add(originalRelation);

// TODO: it would be good to have the link locale to make the relation just to the right sibling
// create the relations in content for all siblings
Iterator<CmsResource> itSiblings = readSiblings(dbc, resource, CmsResourceFilter.ALL).iterator();
while (itSiblings.hasNext()) {
CmsResource sibling = itSiblings.next();
CmsRelation relation = new CmsRelation(
sibling.getStructureId(),
sibling.getRootPath(),
originalRelation.getTargetId(),
originalRelation.getTargetPath(),
link.getType());
relationsForOriginalResource.add(originalRelation);
}
}
List<CmsResource> siblings = resource.getSiblingCount() == 1
? Arrays.asList(resource)
: readSiblings(dbc, resource, CmsResourceFilter.ALL);

for (CmsResource sibling : siblings) {
// For each sibling, we determine which 'defined in content' relations it SHOULD have,
// and only update the relations if that set differs from the ones it actually has.
// If the updateSiblingState flag is set, then for siblings, we update the structure
// state to changed (unless the state was 'deleted' or 'new').
// This is so that even if the user later publishes only one sibling, the other sibling will still
// show up as changed in the GUI, so the user can publish it separately (with its updated relations).
Set<CmsRelation> relationsForSibling = relationsForOriginalResource.stream().map(
relation -> new CmsRelation(
sibling.getStructureId(),
sibling.getRootPath(),
relation.getTargetId(),
relation.getTargetPath(),
relation.getType())).collect(Collectors.toSet());
Set<CmsRelation> existingRelations = new HashSet<>(
vfsDriver.readRelations(
dbc,
dbc.currentProject().getUuid(),
sibling,
CmsRelationFilter.TARGETS.filterDefinedInContent()));
if (!existingRelations.equals(relationsForSibling)) {
vfsDriver.deleteRelations(
dbc,
dbc.currentProject().getUuid(),
sibling,
CmsRelationFilter.TARGETS.filterDefinedInContent());
for (CmsRelation relation : relationsForSibling) {
vfsDriver.createRelation(dbc, dbc.currentProject().getUuid(), relation);
}
if (!sibling.getState().isDeleted()
&& !sibling.getState().isNew()
&& (siblings.size() > 1)
&& updateSiblingState) {
sibling.setState(CmsResource.STATE_CHANGED);
vfsDriver.writeResourceState(
dbc,
dbc.currentProject(),
sibling,
CmsDriverManager.UPDATE_STRUCTURE_STATE,
false);
}
}
}
}
Expand Down Expand Up @@ -12155,7 +12187,8 @@ private void transferPrincipalResources(
data.put(I_CmsEventListener.KEY_RESOURCE, resource);
data.put(
I_CmsEventListener.KEY_CHANGE,
Integer.valueOf(((attrModified) ? CHANGED_RESOURCE : 0) | ((aceModified) ? CHANGED_ACCESSCONTROL : 0)));
Integer.valueOf(
((attrModified) ? CHANGED_RESOURCE : 0) | ((aceModified) ? CHANGED_ACCESSCONTROL : 0)));
OpenCms.fireCmsEvent(new CmsEvent(I_CmsEventListener.EVENT_RESOURCE_MODIFIED, data));
}
}
Expand Down
5 changes: 3 additions & 2 deletions src/org/opencms/db/CmsSecurityManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -6738,17 +6738,18 @@ public void updateLog() throws CmsException {
* @param context the current user context
* @param resource the resource to update the relations for
* @param relations the relations to update
* @param updateSiblingState if true, sets the state of siblings with changed relations to 'changed' (unless they are new or deleted)
*
* @throws CmsException if something goes wrong
*
* @see CmsDriverManager#updateRelationsForResource(CmsDbContext, CmsResource, List)
*/
public void updateRelationsForResource(CmsRequestContext context, CmsResource resource, List<CmsLink> relations)
public void updateRelationsForResource(CmsRequestContext context, CmsResource resource, List<CmsLink> relations, boolean updateSiblingState)
throws CmsException {

CmsDbContext dbc = m_dbContextFactory.getDbContext(context);
try {
m_driverManager.updateRelationsForResource(dbc, resource, relations);
m_driverManager.updateRelationsForResource(dbc, resource, relations, updateSiblingState);
} catch (Exception e) {
dbc.report(
null,
Expand Down
23 changes: 12 additions & 11 deletions src/org/opencms/file/types/A_CmsResourceType.java
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ public void chtype(CmsObject cms, CmsSecurityManager securityManager, CmsResourc
// change type
securityManager.chtype(cms.getRequestContext(), resource, type);
// type may have changed from non link parseable to link parseable
createRelations(cms, securityManager, resource.getRootPath());
createRelations(cms, securityManager, resource.getRootPath(), true);
}

/**
Expand All @@ -329,7 +329,7 @@ public void copyResource(
cms.getRequestContext().addSiteRoot(destination),
siblingMode);
// create the relations for the new resource, this could be improved by an sql query for copying relations
createRelations(cms, securityManager, cms.getRequestContext().addSiteRoot(destination));
createRelations(cms, securityManager, cms.getRequestContext().addSiteRoot(destination), false);
}

/**
Expand Down Expand Up @@ -373,7 +373,7 @@ public CmsResource createResource(
processCopyResources(cms, resourcename, resolver);

// create the relations for the new resource
createRelations(cms, securityManager, cms.getRequestContext().addSiteRoot(resourcename));
createRelations(cms, securityManager, cms.getRequestContext().addSiteRoot(resourcename), false);

// return the created resource
return result;
Expand All @@ -396,7 +396,7 @@ public CmsResource createSibling(
cms.getRequestContext().addSiteRoot(destination),
properties);
// create the relations for the new resource, this could be improved by an sql query for copying relations
createRelations(cms, securityManager, sibling.getRootPath());
createRelations(cms, securityManager, sibling.getRootPath(), false);
return sibling;
}

Expand Down Expand Up @@ -833,7 +833,7 @@ public void replaceResource(

securityManager.replaceResource(cms.getRequestContext(), resource, type, content, properties);
// type may have changed from non link parseable to link parseable
createRelations(cms, securityManager, resource.getRootPath());
createRelations(cms, securityManager, resource.getRootPath(), true);
}

/**
Expand All @@ -844,7 +844,7 @@ public void restoreResource(CmsObject cms, CmsSecurityManager securityManager, C

securityManager.restoreResource(cms.getRequestContext(), resource, version);
// type may have changed from non link parseable to link parseable
createRelations(cms, securityManager, resource.getRootPath());
createRelations(cms, securityManager, resource.getRootPath(), false);
}

/**
Expand Down Expand Up @@ -978,7 +978,7 @@ public CmsFile writeFile(CmsObject cms, CmsSecurityManager securityManager, CmsF
links = ((I_CmsLinkParseable)type).parseLinks(cms, file);
}
// this has to be always executed, even if not link parseable to remove old links
securityManager.updateRelationsForResource(cms.getRequestContext(), file, links);
securityManager.updateRelationsForResource(cms.getRequestContext(), file, links, true);
return file;
}
// folders can never be written like a file
Expand Down Expand Up @@ -1018,12 +1018,13 @@ public void writePropertyObjects(
* @param cms the cms context
* @param securityManager the security manager
* @param resourceName the resource name of the resource to update the relations for
* @param updateSiblingState if true, sets the state of siblings with changed relations to 'changed' (unless they are new or deleted)
*
* @return the fresh read resource
*
* @throws CmsException if something goes wrong
*/
protected CmsResource createRelations(CmsObject cms, CmsSecurityManager securityManager, String resourceName)
protected CmsResource createRelations(CmsObject cms, CmsSecurityManager securityManager, String resourceName, boolean updateSiblingState)
throws CmsException {

CmsResource resource = securityManager.readResource(
Expand All @@ -1036,7 +1037,7 @@ protected CmsResource createRelations(CmsObject cms, CmsSecurityManager security
I_CmsLinkParseable linkParseable = (I_CmsLinkParseable)resourceType;
links = linkParseable.parseLinks(cms, cms.readFile(resource));
}
securityManager.updateRelationsForResource(cms.getRequestContext(), resource, links);
securityManager.updateRelationsForResource(cms.getRequestContext(), resource, links, updateSiblingState);
return resource;
}

Expand Down Expand Up @@ -1274,7 +1275,7 @@ protected void updateRelationForUndo(CmsObject cms, CmsSecurityManager securityM
CmsResource undoneResource1 = null;
try {
// first try to locate the resource by path
undoneResource1 = createRelations(cms, securityManager, resource.getRootPath());
undoneResource1 = createRelations(cms, securityManager, resource.getRootPath(), false);
} catch (CmsVfsResourceNotFoundException e) {
// ignore, undone move operation
}
Expand Down Expand Up @@ -1302,7 +1303,7 @@ protected void updateRelationForUndo(CmsObject cms, CmsSecurityManager securityM
}
}
}
securityManager.updateRelationsForResource(cms.getRequestContext(), undoneResource2, links);
securityManager.updateRelationsForResource(cms.getRequestContext(), undoneResource2, links, false);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,7 @@ public CmsFile writeFile(CmsObject cms, CmsSecurityManager securityManager, CmsF
links = ((I_CmsLinkParseable)type).parseLinks(cms, file);
}
// this has to be always executed, even if not link parseable to remove old links
securityManager.updateRelationsForResource(cms.getRequestContext(), file, links);
securityManager.updateRelationsForResource(cms.getRequestContext(), file, links, true);
return file;
}
}

0 comments on commit 76c7006

Please sign in to comment.