-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Bake diagram XML in the PNG image meta data (#83)
* Bake diagram XML in the PNG image meta data * Change drawio default template content There was a problem with usage of "<bs:drawio {{{diagramName}}} />". In that case "bs:drawio" tag was parsed before "{{{diagramName}}}" parameter was passed. So it looked like diagram is named "{{{diagramName}}}". Now when using "{{#tag:drawio ... }}} diagram name is passed before parsing tag, so now it works correctly. --------- Co-authored-by: akulbii <[email protected]>
- Loading branch information
Showing
6 changed files
with
242 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,4 @@ | ||
<bs:drawio filename="{{{diagramName}}}" /> | ||
{{#tag:drawio | ||
| | ||
|filename={{{diagramName}}} | ||
}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
<?php | ||
|
||
namespace HalloWelt\MigrateConfluence\Utility; | ||
|
||
class DrawIOFileHandler { | ||
|
||
/** | ||
* Checks by file extension if that's associated with DrawIO temporary file. | ||
* That could be either ".drawio" file or ".drawio.tmp" file | ||
* | ||
* @param string $fileName | ||
* @return bool | ||
*/ | ||
public function isDrawIODataFile( string $fileName ): bool { | ||
return ( | ||
preg_match( '#\.drawio.tmp$#', $fileName ) || | ||
preg_match( '#\.drawio$#', $fileName ) | ||
); | ||
} | ||
|
||
/** | ||
* Checks by file extension if that's associated with DrawIO PNG image | ||
* | ||
* @param string $fileName | ||
* @return bool | ||
*/ | ||
public function isDrawIOImage( string $fileName ): bool { | ||
return preg_match( '#\.drawio.png$#', $fileName ); | ||
} | ||
|
||
/** | ||
* Encodes and bakes DrawIO diagram XML into PNG image "tEXt" data chunk | ||
* | ||
* @param string $imageContent | ||
* @param string $diagramXml | ||
* @return string | ||
*/ | ||
public function bakeDiagramDataIntoImage( string $imageContent, string $diagramXml ): string { | ||
// "urlencode" does not suit us here because it encodes spaces with "+" symbol | ||
// That breaks diagram data processing by DrawIO editor | ||
// We need to encode spaces as "%20", so "rawurlencode" is used | ||
// See https://www.php.net/manual/en/function.urlencode.php | ||
$diagramXmlEncoded = rawurlencode( $diagramXml ); | ||
|
||
$keyword = 'mxfile'; | ||
|
||
$chunkData = $keyword . "\0" . $diagramXmlEncoded; | ||
|
||
$crc = pack( 'N', crc32( 'tEXt' . $chunkData ) ); | ||
|
||
// Create the tEXt chunk | ||
$tEXtChunk = pack( 'N', strlen( $chunkData ) ) . 'tEXt' . $chunkData . $crc; | ||
|
||
$IDATChunkPos = strpos( $imageContent, 'IDAT', 8 ); | ||
|
||
// Add the tEXt chunk to the image content | ||
$imageContent = substr_replace( $imageContent, $tEXtChunk, $IDATChunkPos - 4, 0 ); | ||
|
||
return $imageContent; | ||
} | ||
} |
73 changes: 73 additions & 0 deletions
73
tests/phpunit/Utility/DrawIOFileHandler/DrawIOFileHandlerTest.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
<?php | ||
|
||
namespace HalloWelt\MigrateConfluence\Tests\Utility\DrawIOFileHandler; | ||
|
||
use HalloWelt\MigrateConfluence\Utility\DrawIOFileHandler; | ||
use PHPUnit\Framework\TestCase; | ||
|
||
/** | ||
* @covers \HalloWelt\MigrateConfluence\Utility\DrawIOFileHandler | ||
*/ | ||
class DrawIOFileHandlerTest extends TestCase { | ||
|
||
/** | ||
* @covers \HalloWelt\MigrateConfluence\Utility\DrawIOFileHandler::isDrawIODataFile | ||
*/ | ||
public function testIsDrawIODataFile() { | ||
$drawIoFileHandler = new DrawIOFileHandler(); | ||
|
||
$this->assertTrue( $drawIoFileHandler->isDrawIODataFile( 'diagram.drawio' ) ); | ||
$this->assertTrue( $drawIoFileHandler->isDrawIODataFile( 'diagram.drawio.tmp' ) ); | ||
|
||
$this->assertFalse( $drawIoFileHandler->isDrawIODataFile( 'diagram.drawio.png' ) ); | ||
} | ||
|
||
/** | ||
* @covers \HalloWelt\MigrateConfluence\Utility\DrawIOFileHandler::isDrawIOImage | ||
*/ | ||
public function testIsDrawIOImage() { | ||
$drawIoFileHandler = new DrawIOFileHandler(); | ||
|
||
$this->assertFalse( $drawIoFileHandler->isDrawIOImage( 'diagram.drawio' ) ); | ||
$this->assertFalse( $drawIoFileHandler->isDrawIOImage( 'diagram.drawio.tmp' ) ); | ||
|
||
$this->assertTrue( $drawIoFileHandler->isDrawIOImage( 'diagram.drawio.png' ) ); | ||
} | ||
|
||
/** | ||
* @covers \HalloWelt\MigrateConfluence\Utility\DrawIOFileHandler::bakeDiagramDataIntoImage | ||
*/ | ||
public function testBakeDiagramDataIntoImage() { | ||
$drawIoFileHandler = new DrawIOFileHandler(); | ||
|
||
$diagramXml = file_get_contents( __DIR__ . '/data/diagram.drawio' ); | ||
$imageContent = file_get_contents( __DIR__ . '/data/diagram.drawio.png' ); | ||
|
||
// Get expected diagram XML | ||
$matches = []; | ||
preg_match( '#<mxfile.*?>(.*?)</mxfile>#s', $diagramXml, $matches ); | ||
|
||
$expectedDiagramXML = trim( $matches[0] ); | ||
|
||
// Bake diagram XML into PNG image meta data | ||
$imageContent = $drawIoFileHandler->bakeDiagramDataIntoImage( $imageContent, $diagramXml ); | ||
|
||
// Extract and check diagram XML from the PNG | ||
// Extraction is done with the same algorithm how it is done in the wiki | ||
$encodedXML = preg_replace( | ||
'#^.*?tEXt(.*?)IDAT.*?$#s', | ||
'$1', | ||
$imageContent | ||
); | ||
$encodedXML = preg_replace( '/[[:^print:]]/', '', $encodedXML ); | ||
$partiallyDecodedXML = urldecode( $encodedXML ); | ||
|
||
// Get actual diagram XML after extraction from PNG | ||
$matches = []; | ||
preg_match( '#<mxfile.*?>(.*?)</mxfile>#s', $partiallyDecodedXML, $matches ); | ||
|
||
$actualDiagramXML = trim( $matches[0] ); | ||
|
||
$this->assertEquals( $expectedDiagramXML, $actualDiagramXML ); | ||
} | ||
} |
77 changes: 77 additions & 0 deletions
77
tests/phpunit/Utility/DrawIOFileHandler/data/diagram.drawio
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
<mxfile host="ac.draw.io" modified="2023-08-09T08:35:34.679Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36" etag="JMqJX_jkzzPyvO56GqTc" version="21.6.9" type="embed"> | ||
<diagram id="prtHgNgQTEPvFCAcTncT" name="Page-1"> | ||
<mxGraphModel dx="1434" dy="784" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0"> | ||
<root> | ||
<mxCell id="0" /> | ||
<mxCell id="1" parent="0" /> | ||
<mxCell id="dNxyNK7c78bLwvsdeMH5-19" value="test" style="swimlane;html=1;childLayout=stackLayout;resizeParent=1;resizeParentMax=0;horizontal=0;startSize=20;horizontalStack=0;" parent="1" vertex="1"> | ||
<mxGeometry x="120" y="120" width="450" height="360" as="geometry" /> | ||
</mxCell> | ||
<mxCell id="dNxyNK7c78bLwvsdeMH5-27" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;dashed=1;endArrow=none;endFill=0;" parent="dNxyNK7c78bLwvsdeMH5-19" source="dNxyNK7c78bLwvsdeMH5-24" target="dNxyNK7c78bLwvsdeMH5-26" edge="1"> | ||
<mxGeometry relative="1" as="geometry" /> | ||
</mxCell> | ||
<mxCell id="dNxyNK7c78bLwvsdeMH5-31" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;endArrow=classic;endFill=1;" parent="dNxyNK7c78bLwvsdeMH5-19" source="dNxyNK7c78bLwvsdeMH5-28" target="dNxyNK7c78bLwvsdeMH5-30" edge="1"> | ||
<mxGeometry relative="1" as="geometry" /> | ||
</mxCell> | ||
<mxCell id="dNxyNK7c78bLwvsdeMH5-35" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;endArrow=classic;endFill=1;" parent="dNxyNK7c78bLwvsdeMH5-19" source="dNxyNK7c78bLwvsdeMH5-28" target="dNxyNK7c78bLwvsdeMH5-34" edge="1"> | ||
<mxGeometry relative="1" as="geometry" /> | ||
</mxCell> | ||
<mxCell id="dNxyNK7c78bLwvsdeMH5-38" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;endArrow=classic;endFill=1;" parent="dNxyNK7c78bLwvsdeMH5-19" source="dNxyNK7c78bLwvsdeMH5-26" target="dNxyNK7c78bLwvsdeMH5-36" edge="1"> | ||
<mxGeometry relative="1" as="geometry"> | ||
<Array as="points"> | ||
<mxPoint x="180" y="340" /> | ||
<mxPoint x="400" y="340" /> | ||
</Array> | ||
</mxGeometry> | ||
</mxCell> | ||
<mxCell id="dNxyNK7c78bLwvsdeMH5-20" value="Lane 1" style="swimlane;html=1;startSize=20;horizontal=0;" parent="dNxyNK7c78bLwvsdeMH5-19" vertex="1"> | ||
<mxGeometry x="20" width="430" height="120" as="geometry" /> | ||
</mxCell> | ||
<mxCell id="dNxyNK7c78bLwvsdeMH5-25" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="dNxyNK7c78bLwvsdeMH5-20" source="dNxyNK7c78bLwvsdeMH5-23" target="dNxyNK7c78bLwvsdeMH5-24" edge="1"> | ||
<mxGeometry relative="1" as="geometry" /> | ||
</mxCell> | ||
<mxCell id="dNxyNK7c78bLwvsdeMH5-23" value="" style="ellipse;whiteSpace=wrap;html=1;" parent="dNxyNK7c78bLwvsdeMH5-20" vertex="1"> | ||
<mxGeometry x="40" y="40" width="40" height="40" as="geometry" /> | ||
</mxCell> | ||
<UserObject label="test" link="https://geht.atlassian.net/wiki/spaces/GENERAL/pages/256147457/Pallet+truck+2" id="dNxyNK7c78bLwvsdeMH5-24"> | ||
<mxCell style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Helvetica;fontSize=12;fontColor=#000000;align=center;" parent="dNxyNK7c78bLwvsdeMH5-20" vertex="1"> | ||
<mxGeometry x="120" y="30" width="80" height="60" as="geometry" /> | ||
</mxCell> | ||
</UserObject> | ||
<mxCell id="dNxyNK7c78bLwvsdeMH5-33" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;endArrow=classic;endFill=1;" parent="dNxyNK7c78bLwvsdeMH5-20" source="dNxyNK7c78bLwvsdeMH5-30" target="dNxyNK7c78bLwvsdeMH5-32" edge="1"> | ||
<mxGeometry relative="1" as="geometry" /> | ||
</mxCell> | ||
<mxCell id="dNxyNK7c78bLwvsdeMH5-30" value="test" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Helvetica;fontSize=12;fontColor=#000000;align=center;" parent="dNxyNK7c78bLwvsdeMH5-20" vertex="1"> | ||
<mxGeometry x="240" y="30" width="80" height="60" as="geometry" /> | ||
</mxCell> | ||
<mxCell id="dNxyNK7c78bLwvsdeMH5-32" value="" style="ellipse;whiteSpace=wrap;html=1;" parent="dNxyNK7c78bLwvsdeMH5-20" vertex="1"> | ||
<mxGeometry x="360" y="40" width="40" height="40" as="geometry" /> | ||
</mxCell> | ||
<mxCell id="dNxyNK7c78bLwvsdeMH5-21" value="Lane 2" style="swimlane;html=1;startSize=20;horizontal=0;" parent="dNxyNK7c78bLwvsdeMH5-19" vertex="1"> | ||
<mxGeometry x="20" y="120" width="430" height="120" as="geometry" /> | ||
</mxCell> | ||
<mxCell id="dNxyNK7c78bLwvsdeMH5-29" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;endArrow=classic;endFill=1;" parent="dNxyNK7c78bLwvsdeMH5-21" source="dNxyNK7c78bLwvsdeMH5-26" target="dNxyNK7c78bLwvsdeMH5-28" edge="1"> | ||
<mxGeometry relative="1" as="geometry" /> | ||
</mxCell> | ||
<mxCell id="dNxyNK7c78bLwvsdeMH5-26" value="test" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Helvetica;fontSize=12;fontColor=#000000;align=center;" parent="dNxyNK7c78bLwvsdeMH5-21" vertex="1"> | ||
<mxGeometry x="120" y="30" width="80" height="60" as="geometry" /> | ||
</mxCell> | ||
<mxCell id="dNxyNK7c78bLwvsdeMH5-28" value="" style="rhombus;whiteSpace=wrap;html=1;fontFamily=Helvetica;fontSize=12;fontColor=#000000;align=center;" parent="dNxyNK7c78bLwvsdeMH5-21" vertex="1"> | ||
<mxGeometry x="260" y="40" width="40" height="40" as="geometry" /> | ||
</mxCell> | ||
<mxCell id="dNxyNK7c78bLwvsdeMH5-22" value="Lane 3" style="swimlane;html=1;startSize=20;horizontal=0;" parent="dNxyNK7c78bLwvsdeMH5-19" vertex="1"> | ||
<mxGeometry x="20" y="240" width="430" height="120" as="geometry" /> | ||
</mxCell> | ||
<mxCell id="dNxyNK7c78bLwvsdeMH5-37" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;endArrow=classic;endFill=1;" parent="dNxyNK7c78bLwvsdeMH5-22" source="dNxyNK7c78bLwvsdeMH5-34" target="dNxyNK7c78bLwvsdeMH5-36" edge="1"> | ||
<mxGeometry relative="1" as="geometry" /> | ||
</mxCell> | ||
<mxCell id="dNxyNK7c78bLwvsdeMH5-34" value="test" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Helvetica;fontSize=12;fontColor=#000000;align=center;" parent="dNxyNK7c78bLwvsdeMH5-22" vertex="1"> | ||
<mxGeometry x="240" y="20" width="80" height="60" as="geometry" /> | ||
</mxCell> | ||
<mxCell id="dNxyNK7c78bLwvsdeMH5-36" value="" style="rhombus;whiteSpace=wrap;html=1;fontFamily=Helvetica;fontSize=12;fontColor=#000000;align=center;" parent="dNxyNK7c78bLwvsdeMH5-22" vertex="1"> | ||
<mxGeometry x="360" y="30" width="40" height="40" as="geometry" /> | ||
</mxCell> | ||
</root> | ||
</mxGraphModel> | ||
</diagram> | ||
</mxfile> |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.