Skip to content

Commit 2e6a1a2

Browse files
authored
Merge pull request #671 from intersystems/ptd-unescape-cdata
Fix parsing of nested CDATA in PTD items
2 parents 76221f9 + 13b474d commit 2e6a1a2

File tree

3 files changed

+36
-25
lines changed

3 files changed

+36
-25
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
### Added
1111
- Menu option to export production to support migrating to production decomposition (#665)
1212

13+
### Fixed
14+
- Fixed errors on production page when item settings need to be XML escaped (#667)
15+
1316
## [2.8.0] - 2024-12-06
1417

1518
### Added

cls/SourceControl/Git/Production.cls

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ ClassMethod DeleteProductionDefinitionShards(productionClass As %String, deleteM
6262
while rs.%Next(.sc) {
6363
quit:$$$ISERR(sc)
6464
set ptdFilename = rs.Data("Name")
65-
set sc = ##class(%Studio.SourceControl.Production).ParseExternalName(ptdFilename, .ptdInternalName)
65+
set sc = ..ParseExternalName(ptdFilename, .ptdInternalName)
6666
quit:$$$ISERR(sc)
6767
// TODO: Consider reverting delete if any ptd is not editable by current user
6868
set sc = $method(%SourceControl, deleteMethod, ptdInternalName)
@@ -371,26 +371,32 @@ ClassMethod IsProductionClass(className As %String, nameMethod As %String) As %B
371371
ClassMethod ParseExternalName(externalName, Output internalName = "", Output productionName = "") As %Status
372372
{
373373
set sc = $$$OK
374-
set extNameNormalized = $replace(externalName, "\", "/")
375-
set file = $piece(extNameNormalized, "/", *)
376-
if $extract(file,1,9) = "ProdStgs-" {
377-
set productionName = $replace($extract(file,10,*-4), "_", ".")
378-
set internalName = ..CreateInternalName(productionName,,,1)
379-
} else {
380-
if ##class(%File).Exists(externalName) {
381-
// Special case for Config Item Settings PTD, requires checking PTD CDATA for Item and Class name
382-
set deployDoc = ##class(EnsLib.EDI.XML.Document).%New(externalName)
383-
set exportNotesPTDText = $ZCVT(deployDoc.GetValueAt("/Export/Document[1]/1"),"I","XML")
384-
set exportNotesPTD = ##class(EnsLib.EDI.XML.Document).%New(exportNotesPTDText)
385-
set productionName = exportNotesPTD.GetValueAt("/Deployment/Creation/SourceProduction")
386-
set settingsPTDText = $zconvert(deployDoc.GetValueAt("/Export/Document[2]/1"),"I","XML")
387-
set settingsPTD = ##class(EnsLib.EDI.XML.Document).%New(settingsPTDText)
388-
set itemClass = settingsPTD.GetValueAt("/Item/@ClassName")
389-
set itemName = settingsPTD.GetValueAt("/Item/@Name")
390-
set internalName = ..CreateInternalName(productionName, itemName, itemClass, 0)
391-
} else {
392-
set sc = $$$ERROR($$$GeneralError, "Item settings PTD file " _ externalName _ " does not exist. Cannot parse external name.")
393-
}
374+
try {
375+
set extNameNormalized = $replace(externalName, "\", "/")
376+
set file = $piece(extNameNormalized, "/", *)
377+
if $extract(file,1,9) = "ProdStgs-" {
378+
set productionName = $replace($extract(file,10,*-4), "_", ".")
379+
set internalName = ..CreateInternalName(productionName,,,1)
380+
} else {
381+
if ##class(%File).Exists(externalName) {
382+
// Special case for Config Item Settings PTD, requires checking PTD CDATA for Item and Class name
383+
set deployDoc = ##class(EnsLib.EDI.XML.Document).%New(externalName)
384+
set exportNotesPTDText = $ZCVT(deployDoc.GetValueAt("/Export/Document[1]/1"),"I","XML")
385+
set exportNotesPTD = ##class(EnsLib.EDI.XML.Document).%New(exportNotesPTDText)
386+
set productionName = exportNotesPTD.GetValueAt("/Deployment/Creation/SourceProduction")
387+
set settingsPTDText = $zconvert(deployDoc.GetValueAt("/Export/Document[2]/1"),"I","XML")
388+
// unquote embedded CDATA close markers - see Ens.Util.ProjectTextDocument StreamToGbl method
389+
set settingsPTDText = $replace(settingsPTDText,"]*]>", "]]>")
390+
set settingsPTD = ##class(EnsLib.EDI.XML.Document).%New(settingsPTDText)
391+
set itemClass = settingsPTD.GetValueAt("/Item/@ClassName")
392+
set itemName = settingsPTD.GetValueAt("/Item/@Name")
393+
set internalName = ..CreateInternalName(productionName, itemName, itemClass, 0)
394+
} else {
395+
set sc = $$$ERROR($$$GeneralError, "Item settings PTD file " _ externalName _ " does not exist. Cannot parse external name.")
396+
}
397+
}
398+
} catch err {
399+
set sc = err.AsStatus()
394400
}
395401
return sc
396402
}

test/UnitTest/SourceControl/Git/ProductionDecomposition.cls

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,10 @@ Method TestEditProduction()
8282
$$$ThrowOnError(%SourceControl.OnBeforeSave(..#ProductionName_".cls"))
8383
do ..ReplaceProductionDefinition("ProductionDefinition3")
8484
$$$ThrowOnError(%SourceControl.OnAfterSave(..#ProductionName_".cls"))
85-
do $$$AssertTrue(##class(SourceControl.Git.Utils).IsInSourceControl("UnitTest.SampleProduction||Settings-b|Ens.Activity.Operation.Local.PTD"))
85+
do $$$AssertTrue(##class(SourceControl.Git.Utils).IsInSourceControl("UnitTest.SampleProduction||Settings-b|EnsLib.SOAP.GenericOperation.PTD"))
8686
do ##class(SourceControl.Git.Utils).RunGitCommand("add",,,".")
8787
do ##class(SourceControl.Git.Utils).Commit("UnitTest.SampleProduction||Settings-a|Ens.Activity.Operation.Local.PTD")
88-
do ##class(SourceControl.Git.Utils).Commit("UnitTest.SampleProduction||Settings-b|Ens.Activity.Operation.Local.PTD")
88+
do ##class(SourceControl.Git.Utils).Commit("UnitTest.SampleProduction||Settings-b|EnsLib.SOAP.GenericOperation.PTD")
8989
$$$ThrowOnError(production.%Reload())
9090
do $$$AssertEquals(production.Items.Count(), 2)
9191
do $$$AssertEquals(production.Items.GetAt(1).Settings.GetAt(1).Name, "RecordStatsInterval")
@@ -135,7 +135,8 @@ XData ProductionDefinition2
135135
<Item Name="a" Category="" ClassName="Ens.Activity.Operation.Local" PoolSize="1" Enabled="true" Foreground="false" Comment="" LogTraceEvents="false" Schedule="">
136136
<Setting Target="Host" Name="RecordStatsInterval">61</Setting>
137137
</Item>
138-
<Item Name="b" Category="" ClassName="Ens.Activity.Operation.Local" PoolSize="1" Enabled="true" Foreground="false" Comment="" LogTraceEvents="false" Schedule="">
138+
<Item Name="b" Category="" ClassName="EnsLib.SOAP.GenericOperation" PoolSize="1" Enabled="false" Foreground="false" Comment="" LogTraceEvents="false" Schedule="">
139+
<Setting Target="Adapter" Name="HTTPServer"><![CDATA[<something that must be escaped>]]></Setting>
139140
</Item>
140141
</Production>
141142
}
@@ -147,7 +148,8 @@ XData ProductionDefinition3
147148
<Item Name="a" Category="" ClassName="Ens.Activity.Operation.Local" PoolSize="1" Enabled="true" Foreground="false" Comment="" LogTraceEvents="false" Schedule="">
148149
<Setting Target="Host" Name="RecordStatsInterval">71</Setting>
149150
</Item>
150-
<Item Name="b" Category="" ClassName="Ens.Activity.Operation.Local" PoolSize="1" Enabled="true" Foreground="false" Comment="" LogTraceEvents="false" Schedule="">
151+
<Item Name="b" Category="" ClassName="EnsLib.SOAP.GenericOperation" PoolSize="1" Enabled="false" Foreground="false" Comment="" LogTraceEvents="false" Schedule="">
152+
<Setting Target="Adapter" Name="HTTPServer"><![CDATA[<something that must be escaped>]]></Setting>
151153
</Item>
152154
</Production>
153155
}

0 commit comments

Comments
 (0)