From baebf8c6aba8541709c2d61802227d1229a9d614 Mon Sep 17 00:00:00 2001
From: Thomas Mortagne <thomas.mortagne@gmail.com>
Date: Thu, 6 Oct 2016 12:03:28 +0200
Subject: [PATCH] XWIKI-13490: Document displayer put the wrong XwikiDocument
 instance in the context

---
 .../xwiki/bridge/DocumentAccessBridge.java    | 14 +++
 .../internal/DocumentContentDisplayer.java    |  2 +-
 .../internal/macro/DisplayMacroTest.java      | 86 ++++++++-----------
 .../doc/DefaultDocumentAccessBridge.java      |  8 +-
 4 files changed, 56 insertions(+), 54 deletions(-)

diff --git a/xwiki-platform-core/xwiki-platform-bridge/src/main/java/org/xwiki/bridge/DocumentAccessBridge.java b/xwiki-platform-core/xwiki-platform-bridge/src/main/java/org/xwiki/bridge/DocumentAccessBridge.java
index f51fbf643a2..afbb5e3d18b 100644
--- a/xwiki-platform-core/xwiki-platform-bridge/src/main/java/org/xwiki/bridge/DocumentAccessBridge.java
+++ b/xwiki-platform-core/xwiki-platform-bridge/src/main/java/org/xwiki/bridge/DocumentAccessBridge.java
@@ -650,6 +650,20 @@ String getDocumentURL(DocumentReference documentReference,
      */
     void pushDocumentInContext(Map<String, Object> backupObjects, DocumentReference documentReference) throws Exception;
 
+    /**
+     * Sets the passed document as the current document in the XWiki Context and saves current values related to the
+     * current document into a backup object.
+     * 
+     * @param backupObjects the object in which to some context properties will be saved
+     * @param document the document to set as the current document
+     * @throws Exception in case of an error like a problem loading the document from the database
+     * @since 8.4M1
+     */
+    default void pushDocumentInContext(Map<String, Object> backupObjects, DocumentModelBridge document) throws Exception
+    {
+        pushDocumentInContext(backupObjects, document.getDocumentReference());
+    }
+
     /**
      * Restore values saved in a backup object in the XWiki Context and restore the current document with the same value
      * before {@link #pushDocumentInContext(Map, String)} was called.
diff --git a/xwiki-platform-core/xwiki-platform-display/xwiki-platform-display-api/src/main/java/org/xwiki/display/internal/DocumentContentDisplayer.java b/xwiki-platform-core/xwiki-platform-display/xwiki-platform-display-api/src/main/java/org/xwiki/display/internal/DocumentContentDisplayer.java
index fbeb1a023ed..d338f4f5c87 100644
--- a/xwiki-platform-core/xwiki-platform-display/xwiki-platform-display-api/src/main/java/org/xwiki/display/internal/DocumentContentDisplayer.java
+++ b/xwiki-platform-core/xwiki-platform-display/xwiki-platform-display-api/src/main/java/org/xwiki/display/internal/DocumentContentDisplayer.java
@@ -221,7 +221,7 @@ private XDOM displayInIsolatedExecutionContext(DocumentModelBridge document, Str
         EntityReference currentWikiReference = this.modelContext.getCurrentEntityReference();
         try {
             // The following method call also clones the execution context.
-            documentAccessBridge.pushDocumentInContext(backupObjects, document.getDocumentReference());
+            documentAccessBridge.pushDocumentInContext(backupObjects, document);
             // Make sure to synchronize the context wiki with the context document's wiki.
             modelContext.setCurrentEntityReference(document.getDocumentReference().getWikiReference());
             return display(document, nameSpace, parameters);
diff --git a/xwiki-platform-core/xwiki-platform-display/xwiki-platform-display-macro/src/test/java/org/xwiki/rendering/internal/macro/DisplayMacroTest.java b/xwiki-platform-core/xwiki-platform-display/xwiki-platform-display-macro/src/test/java/org/xwiki/rendering/internal/macro/DisplayMacroTest.java
index 3975b0b3be7..d194a64b115 100644
--- a/xwiki-platform-core/xwiki-platform-display/xwiki-platform-display-macro/src/test/java/org/xwiki/rendering/internal/macro/DisplayMacroTest.java
+++ b/xwiki-platform-core/xwiki-platform-display/xwiki-platform-display-macro/src/test/java/org/xwiki/rendering/internal/macro/DisplayMacroTest.java
@@ -81,6 +81,8 @@ public class DisplayMacroTest extends AbstractComponentTestCase
 
     private AuthorizationManager mockAuthorization;
 
+    private DocumentModelBridge mockDocument;
+
     @Override
     public void setUp() throws Exception
     {
@@ -109,22 +111,17 @@ protected void registerComponents() throws Exception
     @Test
     public void testDisplayMacroShowsVelocityMacrosAreIsolated() throws Exception
     {
-        String expected = "beginDocument\n"
-            + "beginMetaData [[base]=[wiki:Space.DisplayedPage][source]=[wiki:Space.DisplayedPage]"
-                + "[syntax]=[XWiki 2.0]]\n"
-            + "beginMacroMarkerStandalone [velocity] [] [#testmacro]\n"
-            + "beginParagraph\n"
-            + "onSpecialSymbol [#]\n"
-            + "onWord [testmacro]\n"
-            + "endParagraph\n"
-            + "endMacroMarkerStandalone [velocity] [] [#testmacro]\n"
-            + "endMetaData [[base]=[wiki:Space.DisplayedPage][source]=[wiki:Space.DisplayedPage]"
-                + "[syntax]=[XWiki 2.0]]\n"
-            + "endDocument";
+        String expected =
+            "beginDocument\n" + "beginMetaData [[base]=[wiki:Space.DisplayedPage][source]=[wiki:Space.DisplayedPage]"
+                + "[syntax]=[XWiki 2.0]]\n" + "beginMacroMarkerStandalone [velocity] [] [#testmacro]\n"
+                + "beginParagraph\n" + "onSpecialSymbol [#]\n" + "onWord [testmacro]\n" + "endParagraph\n"
+                + "endMacroMarkerStandalone [velocity] [] [#testmacro]\n"
+                + "endMetaData [[base]=[wiki:Space.DisplayedPage][source]=[wiki:Space.DisplayedPage]"
+                + "[syntax]=[XWiki 2.0]]\n" + "endDocument";
 
         // We verify that a Velocity macro set in the including page is not seen in the displayed page.
-        List<Block> blocks = runDisplayMacroWithPreVelocity("#macro(testmacro)#end",
-            "{{velocity}}#testmacro{{/velocity}}");
+        List<Block> blocks =
+            runDisplayMacroWithPreVelocity("#macro(testmacro)#end", "{{velocity}}#testmacro{{/velocity}}");
 
         assertBlocks(expected, blocks, this.rendererFactory);
     }
@@ -149,21 +146,15 @@ public void testDisplayMacroWithNoDocumentSpecified() throws Exception
     @Test
     public void testDisplayMacroWhenDisplayingDocumentWithRelativeReferences() throws Exception
     {
-        String expected = "beginDocument\n"
-            + "beginMetaData [[base]=[displayedWiki:displayedSpace.displayedPage]"
-                + "[source]=[displayedWiki:displayedSpace.displayedPage][syntax]=[XWiki 2.0]]\n"
-            + "beginParagraph\n"
+        String expected = "beginDocument\n" + "beginMetaData [[base]=[displayedWiki:displayedSpace.displayedPage]"
+            + "[source]=[displayedWiki:displayedSpace.displayedPage][syntax]=[XWiki 2.0]]\n" + "beginParagraph\n"
             + "beginLink [Typed = [false] Type = [doc] Reference = [page]] [false]\n"
-            + "endLink [Typed = [false] Type = [doc] Reference = [page]] [false]\n"
-            + "onSpace\n"
+            + "endLink [Typed = [false] Type = [doc] Reference = [page]] [false]\n" + "onSpace\n"
             + "beginLink [Typed = [true] Type = [attach] Reference = [test.png]] [false]\n"
-            + "endLink [Typed = [true] Type = [attach] Reference = [test.png]] [false]\n"
-            + "onSpace\n"
-            + "onImage [Typed = [false] Type = [attach] Reference = [test.png]] [true]\n"
-            + "endParagraph\n"
+            + "endLink [Typed = [true] Type = [attach] Reference = [test.png]] [false]\n" + "onSpace\n"
+            + "onImage [Typed = [false] Type = [attach] Reference = [test.png]] [true]\n" + "endParagraph\n"
             + "endMetaData [[base]=[displayedWiki:displayedSpace.displayedPage]"
-                + "[source]=[displayedWiki:displayedSpace.displayedPage][syntax]=[XWiki 2.0]]\n"
-            + "endDocument";
+            + "[source]=[displayedWiki:displayedSpace.displayedPage][syntax]=[XWiki 2.0]]\n" + "endDocument";
 
         final DocumentReference displayedDocumentReference =
             new DocumentReference("displayedWiki", "displayedSpace", "displayedPage");
@@ -174,7 +165,8 @@ public void testDisplayMacroWhenDisplayingDocumentWithRelativeReferences() throw
             {
                 oneOf(mockSetup.bridge).isDocumentViewable(with(any(DocumentReference.class)));
                 will(returnValue(true));
-                oneOf(mockSetup.bridge).pushDocumentInContext(with(any(Map.class)), with(any(DocumentReference.class)));
+                oneOf(mockSetup.bridge).pushDocumentInContext(with(any(Map.class)),
+                    with(any(DocumentModelBridge.class)));
                 oneOf(mockSetup.bridge).getCurrentDocumentReference();
                 will(returnValue(displayedDocumentReference));
                 oneOf(mockSetup.bridge).popDocumentFromContext(with(any(Map.class)));
@@ -249,14 +241,11 @@ public Object invoke(Invocation invocation) throws Throwable
     }
 
     @Test
-    public void testDisplayMacroInsideBaseMetaDataBlockAndWithRelativeDocumentReferencePassed()
-        throws Exception
+    public void testDisplayMacroInsideBaseMetaDataBlockAndWithRelativeDocumentReferencePassed() throws Exception
     {
         String expected = "beginDocument\n"
             + "beginMetaData [[base]=[wiki:space.relativePage][source]=[wiki:space.relativePage][syntax]=[XWiki 2.0]]\n"
-            + "beginParagraph\n"
-            + "onWord [content]\n"
-            + "endParagraph\n"
+            + "beginParagraph\n" + "onWord [content]\n" + "endParagraph\n"
             + "endMetaData [[base]=[wiki:space.relativePage][source]=[wiki:space.relativePage][syntax]=[XWiki 2.0]]\n"
             + "endDocument";
 
@@ -265,11 +254,13 @@ public void testDisplayMacroInsideBaseMetaDataBlockAndWithRelativeDocumentRefere
 
         MacroTransformationContext macroContext = createMacroTransformationContext("whatever", false);
         // Add a Source MetaData Block as a parent of the display Macro block.
-        new MetaDataBlock(Collections.<Block> singletonList(macroContext.getCurrentMacroBlock()), new MetaData(
-            Collections.<String, Object> singletonMap(MetaData.BASE, "wiki:space.page")));
+        new MetaDataBlock(Collections.<Block>singletonList(macroContext.getCurrentMacroBlock()),
+            new MetaData(Collections.<String, Object>singletonMap(MetaData.BASE, "wiki:space.page")));
 
         final DocumentReference sourceReference = new DocumentReference("wiki", "space", "page");
         final DocumentReference resolvedReference = new DocumentReference("wiki", "space", "relativePage");
+        setUpDocumentMock("relativePage", resolvedReference, "content");
+
         getMockery().checking(new Expectations()
         {
             {
@@ -281,15 +272,13 @@ public void testDisplayMacroInsideBaseMetaDataBlockAndWithRelativeDocumentRefere
                 will(returnValue(resolvedReference));
                 oneOf(mockSetup.bridge).isDocumentViewable(resolvedReference);
                 will(returnValue(true));
-                oneOf(mockSetup.bridge).pushDocumentInContext(with(any(Map.class)), with(same(resolvedReference)));
+                oneOf(mockSetup.bridge).pushDocumentInContext(with(any(Map.class)), with(same(mockDocument)));
                 oneOf(mockSetup.bridge).getCurrentDocumentReference();
                 will(returnValue(resolvedReference));
                 oneOf(mockSetup.bridge).popDocumentFromContext(with(any(Map.class)));
             }
         });
 
-        setUpDocumentMock("relativePage", resolvedReference, "content");
-
         List<Block> blocks = this.displayMacro.execute(parameters, null, macroContext);
 
         assertBlocks(expected, blocks, this.rendererFactory);
@@ -298,18 +287,12 @@ public void testDisplayMacroInsideBaseMetaDataBlockAndWithRelativeDocumentRefere
     @Test
     public void testDisplayMacroWhenSectionSpecified() throws Exception
     {
-        String expected = "beginDocument\n"
-            + "beginMetaData [[base]=[wiki:Space.DisplayedPage][source]=[wiki:Space.DisplayedPage]"
-                + "[syntax]=[XWiki 2.0]]\n"
-            + "beginHeader [1, Hsection]\n"
-            + "onWord [section]\n"
-            + "endHeader [1, Hsection]\n"
-            + "beginParagraph\n"
-            + "onWord [content2]\n"
-            + "endParagraph\n"
-            + "endMetaData [[base]=[wiki:Space.DisplayedPage][source]=[wiki:Space.DisplayedPage]"
-                + "[syntax]=[XWiki 2.0]]\n"
-            + "endDocument";
+        String expected =
+            "beginDocument\n" + "beginMetaData [[base]=[wiki:Space.DisplayedPage][source]=[wiki:Space.DisplayedPage]"
+                + "[syntax]=[XWiki 2.0]]\n" + "beginHeader [1, Hsection]\n" + "onWord [section]\n"
+                + "endHeader [1, Hsection]\n" + "beginParagraph\n" + "onWord [content2]\n" + "endParagraph\n"
+                + "endMetaData [[base]=[wiki:Space.DisplayedPage][source]=[wiki:Space.DisplayedPage]"
+                + "[syntax]=[XWiki 2.0]]\n" + "endDocument";
 
         DisplayMacroParameters parameters = new DisplayMacroParameters();
         parameters.setSection("Hsection");
@@ -346,7 +329,7 @@ private MacroTransformationContext createMacroTransformationContext(String docum
     private void setUpDocumentMock(final String resolve, final DocumentReference reference, final String content)
         throws Exception
     {
-        final DocumentModelBridge mockDocument = getMockery().mock(DocumentModelBridge.class, resolve);
+        mockDocument = getMockery().mock(DocumentModelBridge.class, resolve);
         getMockery().checking(new Expectations()
         {
             {
@@ -396,8 +379,7 @@ private List<Block> runDisplayMacro(DisplayMacroParameters parameters, String di
             {
                 allowing(mockSetup.bridge).isDocumentViewable(with(same(displayedDocumentReference)));
                 will(returnValue(true));
-                oneOf(mockSetup.bridge).pushDocumentInContext(with(any(Map.class)),
-                    with(same(displayedDocumentReference)));
+                oneOf(mockSetup.bridge).pushDocumentInContext(with(any(Map.class)), with(same(mockDocument)));
                 atMost(1).of(mockSetup.bridge).getCurrentDocumentReference();
                 will(returnValue(displayedDocumentReference));
                 oneOf(mockSetup.bridge).popDocumentFromContext(with(any(Map.class)));
diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/doc/DefaultDocumentAccessBridge.java b/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/doc/DefaultDocumentAccessBridge.java
index f8dbb435fa5..3570d78c3d5 100644
--- a/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/doc/DefaultDocumentAccessBridge.java
+++ b/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/doc/DefaultDocumentAccessBridge.java
@@ -812,6 +812,12 @@ public void pushDocumentInContext(Map<String, Object> backupObjects, String docu
     @Override
     public void pushDocumentInContext(Map<String, Object> backupObjects, DocumentReference documentReference)
         throws Exception
+    {
+        pushDocumentInContext(backupObjects, getDocument(documentReference));
+    }
+
+    @Override
+    public void pushDocumentInContext(Map<String, Object> backupObjects, DocumentModelBridge document) throws Exception
     {
         XWikiContext xcontext = getContext();
 
@@ -822,7 +828,7 @@ public void pushDocumentInContext(Map<String, Object> backupObjects, DocumentRef
         xcontext = getContext();
 
         // Change context document
-        xcontext.getWiki().getDocument(documentReference, xcontext).setAsContextDoc(xcontext);
+        ((XWikiDocument) document).setAsContextDoc(xcontext);
     }
 
     @Override
-- 
GitLab