tdf#154469 DOCX export: fix hyperlink in group shape

Hyperlink inserted to shape lost after export,
if the shape was inside a group shape.

Follow-up to commit 7f4f88b883f81fbce975f72aea0f66a54e269ead
"tdf#145147 DOCX import: fix hyperlink in group shape".

Change-Id: I48b582c04b6f779cb5393179f65a32d7a7eca5ce
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/149716
Tested-by: László Németh <nemeth@numbertext.org>
Reviewed-by: László Németh <nemeth@numbertext.org>
diff --git a/include/oox/core/xmlfilterbase.hxx b/include/oox/core/xmlfilterbase.hxx
index 89a7994..317c2a2 100644
--- a/include/oox/core/xmlfilterbase.hxx
+++ b/include/oox/core/xmlfilterbase.hxx
@@ -221,6 +221,10 @@ public:
     */
    sal_Int32 GetUniqueId() { return mnMaxDocId++; }

    sal_Int32 GetMaxDocId() { return mnMaxDocId; }

    void SetMaxDocId(sal_Int32 maxDocId) { mnMaxDocId = maxDocId; }

    /** Write the document properties into into the current OPC package.

        @param xProperties  The document properties to export.
diff --git a/oox/source/export/shapes.cxx b/oox/source/export/shapes.cxx
index eab82a8..83d308c 100644
--- a/oox/source/export/shapes.cxx
+++ b/oox/source/export/shapes.cxx
@@ -902,6 +902,29 @@ ShapeExport& ShapeExport::WriteCustomShape( const Reference< XShape >& xShape )
    else
    {
        pFS->startElementNS(mnXmlNamespace, XML_wsp);
        if (m_xParent.is())
        {
            pFS->startElementNS(mnXmlNamespace, XML_cNvPr, XML_id,
                                OString::number(GetShapeID(xShape) == -1 ? GetNewShapeID(xShape)
                                                                         : GetShapeID(xShape)),
                                XML_name, GetShapeName(xShape));

            if (GetProperty(rXPropSet, "Hyperlink"))
            {
                OUString sURL;
                mAny >>= sURL;
                if (!sURL.isEmpty())
                {
                    OUString sRelId = mpFB->addRelation(
                        mpFS->getOutputStream(), oox::getRelationship(Relationship::HYPERLINK),
                        mpURLTransformer->getTransformedString(sURL),
                        mpURLTransformer->isExternalURL(sURL));

                    mpFS->singleElementNS(XML_a, XML_hlinkClick, FSNS(XML_r, XML_id), sRelId);
                }
            }
            pFS->endElementNS(mnXmlNamespace, XML_cNvPr);
        }
        pFS->singleElementNS(mnXmlNamespace, XML_cNvSpPr);
    }

diff --git a/sw/qa/extras/ooxmlimport/data/grouped_link.docx b/sw/qa/extras/ooxmlexport/data/grouped_link.docx
similarity index 100%
rename from sw/qa/extras/ooxmlimport/data/grouped_link.docx
rename to sw/qa/extras/ooxmlexport/data/grouped_link.docx
Binary files differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx
index 04ce5b8..908d8db 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx
@@ -878,6 +878,17 @@ DECLARE_OOXMLEXPORT_TEST(testTdf149996, "lorem_hyperlink.fodt")
    // because the exported file was corrupted.
}

DECLARE_OOXMLEXPORT_TEST(testGroupedShapeLink, "grouped_link.docx")
{
    // tdf#145147 Hyperlink in grouped shape not imported
    // tdf#154469 Hyperlink in grouped shape not exported
    uno::Reference<drawing::XShapes> xGroupShape(getShape(1), uno::UNO_QUERY);
    CPPUNIT_ASSERT_EQUAL(OUString("https://www.libreoffice.org"),
                         getProperty<OUString>(xGroupShape->getByIndex(0), "Hyperlink"));
    CPPUNIT_ASSERT_EQUAL(OUString("https://www.documentfoundation.org"),
                         getProperty<OUString>(xGroupShape->getByIndex(1), "Hyperlink"));
}

CPPUNIT_PLUGIN_IMPLEMENT();

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx b/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx
index bcd75b7..caaa4b6 100644
--- a/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx
+++ b/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx
@@ -1144,16 +1144,6 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf154695)
    }
}

CPPUNIT_TEST_FIXTURE(Test, testTdf145147)
{
    createSwDoc("grouped_link.docx");
    uno::Reference<drawing::XShapes> xGroupShape(getShape(1), uno::UNO_QUERY);
    CPPUNIT_ASSERT_EQUAL(OUString("https://www.libreoffice.org"),
                         getProperty<OUString>(xGroupShape->getByIndex(0), "Hyperlink"));
    CPPUNIT_ASSERT_EQUAL(OUString("https://www.documentfoundation.org"),
                         getProperty<OUString>(xGroupShape->getByIndex(1), "Hyperlink"));
}

// tests should only be added to ooxmlIMPORT *if* they fail round-tripping in ooxmlEXPORT

CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx
index 70e5156..8f7a5b9 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -5872,10 +5872,12 @@ void DocxAttributeOutput::WritePostponedCustomShape()

    for( const auto & rPostponedDrawing : *m_oPostponedCustomShape)
    {
        m_rExport.GetFilter().SetMaxDocId(m_anchorId + 1);
        if ( IsAlternateContentChoiceOpen() )
            m_rExport.SdrExporter().writeDMLDrawing(rPostponedDrawing.object, rPostponedDrawing.frame, m_anchorId++);
        else
            m_rExport.SdrExporter().writeDMLAndVMLDrawing(rPostponedDrawing.object, *rPostponedDrawing.frame, m_anchorId++);
        m_anchorId = m_rExport.GetFilter().GetMaxDocId();
    }
    m_oPostponedCustomShape.reset();
}
@@ -5894,10 +5896,12 @@ void DocxAttributeOutput::WritePostponedDMLDrawing()
    for( const auto & rPostponedDrawing : *pPostponedDMLDrawings )
    {
        // Avoid w:drawing within another w:drawing.
        m_rExport.GetFilter().SetMaxDocId(m_anchorId + 1);
        if ( IsAlternateContentChoiceOpen() && !( m_rExport.SdrExporter().IsDrawingOpen()) )
           m_rExport.SdrExporter().writeDMLDrawing(rPostponedDrawing.object, rPostponedDrawing.frame, m_anchorId++);
        else
            m_rExport.SdrExporter().writeDMLAndVMLDrawing(rPostponedDrawing.object, *rPostponedDrawing.frame, m_anchorId++);
        m_anchorId = m_rExport.GetFilter().GetMaxDocId();
    }

    m_oPostponedOLEs = std::move(pPostponedOLEs);
@@ -5953,6 +5957,7 @@ void DocxAttributeOutput::WriteFlyFrame(const ww8::Frame& rFrame)
                    {
                        if (!m_oPostponedDMLDrawings)
                        {
                            m_rExport.GetFilter().SetMaxDocId(m_anchorId + 1);
                            if ( IsAlternateContentChoiceOpen() )
                            {
                                // Do not write w:drawing inside w:drawing. Instead Postpone the Inner Drawing.
@@ -5963,6 +5968,7 @@ void DocxAttributeOutput::WriteFlyFrame(const ww8::Frame& rFrame)
                            }
                            else
                                m_rExport.SdrExporter().writeDMLAndVMLDrawing( pSdrObj, rFrame.GetFrameFormat(), m_anchorId++);
                            m_anchorId = m_rExport.GetFilter().GetMaxDocId();

                            m_bPostponedProcessingFly = false ;
                        }