-
-
Notifications
You must be signed in to change notification settings - Fork 552
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
XWIKI-12987: Relative links are made absolute or even broken after moving a page #3553
base: master
Are you sure you want to change the base?
Conversation
bd6d6fe
to
12a6e52
Compare
setup.createPage(sourcePageReference2, "Some content to be linked in macro. number 2"); | ||
ViewPage nestedMacroLinkPage = | ||
setup.createPage(sourcePageReference3, "Some content to be linked in nested macro. number 3"); | ||
setup.createPage(sourcePageReference1, "Some content to be linked. number 1"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better use the rest API if you don't need a ViewPage, it's much faster and reliable.
|
||
// Wait for an empty queue here to ensure that the deleted page has been removed from the index and links | ||
// won't be updated just because the page is still in the index. | ||
new SolrTestUtils(testUtils, testConfiguration.getServletEngine()).waitEmptyQueue(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should not be needed anymore with XWIKI-22323.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually call it to avoid getting a question when performing the rename operation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The question is supposed to automatically vanish (it's not a blocker question) as soon as the job is done AFAIU.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
well what's sure is that I'm getting a timeout when I remove this and the screenshot shows the question...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We might need to update the PO to support non-blocking questions (maybe it does not find what it expects to see to check if the job is still running when a question is displayed).
* @param oldTarget the previous reference of the renamed entity (attachment or document) | ||
* @param newTarget the new reference of the renamed entity (attachment or document) | ||
* @param relative {@code true} if the link should be serialized relatively to the current document | ||
* @param updatedDocuments the list of documents that have been renamed in the same job: this list contains the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure about the "have been
", isn't this called during the rename, for each page ? Also, I think it's related to copy too and not just rename, right ?
@Unstable | ||
default boolean renameReferences(Block block, DocumentReference currentDocumentReference, | ||
DocumentReference oldTarget, | ||
DocumentReference newTarget, boolean relative, Set<DocumentReference> updatedDocuments) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updatedDocuments
does not seem enough to me. I don't see how you can properly cover all use cases without knowing where those pages are moved.
if (((CancelableEvent) beginEvent).isCanceled()) { | ||
return; | ||
} | ||
this.progressManager.endStep(this); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't need to call endStep if you have a startStep with the same source.
this.progressManager.startStep(this); | ||
EndFoldEvent endEvent = getEndEvent(); | ||
this.observationManager.notify(endEvent, this, this.getRequest()); | ||
this.progressManager.endStep(this); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't need this endStep, it will be closed by popLevelProgress.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't need it but it's not a mistake to have it right? Note that here it's some old code that I just moved, and personally I feel more comfortable to keep the symmetry start/end Step
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not going to cause problems, it's just useless.
I feel more comfortable to keep the symmetry start/end Step
On my side, I usually prefer to limit plumbing to not pollute too much the "real" code.
@@ -90,4 +66,16 @@ protected boolean atomicOperation(DocumentReference source, DocumentReference ta | |||
{ | |||
return this.modelBridge.copy(source, target); | |||
} | |||
|
|||
@Override | |||
protected <T extends BeginFoldEvent & CancelableEvent> T getBeginEvent() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Feels more like a createBeginEvent
.
} | ||
|
||
@Override | ||
protected EndFoldEvent getEndEvent() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment as above.
@@ -90,4 +66,16 @@ protected boolean atomicOperation(DocumentReference source, DocumentReference ta | |||
{ | |||
return this.modelBridge.copy(source, target); | |||
} | |||
|
|||
@Override | |||
protected <T extends BeginFoldEvent & CancelableEvent> T getBeginEvent() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the type of begin event and end event depend on the class implementing and not on the code calling the method, you should declare those two type in the class definition.
Alternatively, you could just declare that getBeginEvent returns a BeginFoldEvent and check in the abstract if it happens to also be a CancelableEvent. Would be more consistent with getEndEvent.
…ving a page WIP The idea of this work is to: 1. Provide a way to access all documents that are moved as part of a move job 2. Use that information when performing a call to ReferenceRenamer to define if a relative untyped link should be handled or not On top of it, the idea is also to check if the doc exists in case of refactoring of a link to avoid refactoring unexisting relative links. One problem is remaining about relative link pointing to sibling pages (e.g. the link to Alice in Bob page in the ticket): we rely apparently to an old mechanism for backward compatibility reason for this to work in the UI, we might need same thing in the check, or to decide to ignore that UC. I started to add an integration tests but for some reason it's not passing, though it seemed to be working locally for the scenario described in the ticket (except for the link in Bob page).
…ving a page * Fix integration test setup * Fix some signatures * Work on the conditions for performing link update: WIP
…ving a page * Fix conditions to make all RenamePageIT passing * WIP: need to double check that some conditions are not redundant and double check side effects
…ving a page * Simplify a bit the conditions in ResourceReferenceRenamer and ensure all unit tests are passing in refactoring module
…ving a page * Fix checkstyle * WIP: try to find proper oracle for renaming absolute references, without success so far.
…ving a page * Find proper conditions to perform or not link renames * Fix unit tests to add missing conditions * WIP: need to fix coverage and check on subwikis / with more conditions (e.g. with holes in hierarchy)
…ving a page * Fix a regression and provide a test to cover it
…ving a page * Provide subwiki integration tests * Minor improvment in RenamePageIT
…ving a page * Improve SubWikiIT to add more checks
Jira URL
https://jira.xwiki.org/browse/XWIKI-12987
TODO
Changes
Description
The idea of this work is to:
The PR provides mainly:
Clarifications
The refactoring of references is currently called at two places:
The problem of XWIKI-12987 is that XWiki#updateLinksForRename is called first and does perform an absolute rename of the relative links.
Now ResourceReferenceRenamer APIs names might be misleading:
updateResourceReferenceRelative
andupdateResourceReferenceAbsolute
are not about the references being absolute or relative: it's about the renamed references being absolute or relative respectively to the current document. It took me a while to integrate this, and I'm still struggling a bit with it.So the problem was to find a proper condition to decide when to not refactor links, for this I'm performing a check for assessing if a link is absolute or not, by trying to resolve the ResourceReference without any parameter: if the result equals the reference with parameter then it was absolute.
Then for the
updateResourceReferenceAbsolute
the idea is to only perform update of the links, if the provided link is absolute, or if it's relative but the current document hasn't been moved as part of same job: in such case we do need to update the relative link, because there won't be a call toXWiki#updateLinksForRename
on that document to update the link, we only get the call fromBackLinkUpdaterListener
.For the
updateResourceReferenceRelative
the check is a bit more complex.We only update links that are relative here, we don't want to update absolute references (is that correct? Can't find a counter example right now).
Then since we only perform refactoring of links relative to current document, we also check that the link about to be refactored is not related to pages that are part of the moved document in the same job: if those are also moved in the same job, then they're moved using same "direction", they're part of same hierarchy and we don't want to change the relative links wrt to them. This check is the main part of avoiding to update the relative links.
And finally we perform the update of the link only if the doc actually exists: we would create absolute links for those not existing doc, which doesn't make sense, we should keep the relative link we don't really know what the user wanted to do with those. Note that we could do the same check in
updateResourceReferenceAbsolute
but we don't really have the need since this is only called from the BackLinkUpdaterListener and if I'm correct we'll never have registered backlinks for a not existing doc.Note that initially we discussed about using untyped link as a condition to perform or not the refactoring: I dropped the idea because we currently always create image resource references as untyped references from the WYSIWYG editor.
Screenshots & Video
Executed Tests
Run of tests on following modules / integration test:
Expected merging strategy
*