@@ -20,11 +20,13 @@ process.stdin.on('end', async () => {
2020 const changedObjects = [ ] ;
2121
2222 for ( let object of data . objects ) {
23- await updateObject (
23+ const changed = await updateObject (
2424 getObjectData ( object ) ,
25- object . _current ? getObjectData ( object . _current ) : undefined
25+ object ,
26+ object . _current ? getObjectData ( object . _current ) : undefined ,
27+ tagGroups
2628 ) ;
27- if ( await handleNewlyDrawnGeometries ( object , tagGroups ) ) changedObjects . push ( object ) ;
29+ if ( changed ) changedObjects . push ( object ) ;
2830 }
2931
3032 console . log ( JSON . stringify ( { objects : changedObjects } ) ) ;
@@ -52,7 +54,9 @@ function getWFSConfiguration(configuration, objectType) {
5254 return wfsConfiguration ?. find ( configuration => configuration . object_type === objectType ) ;
5355}
5456
55- async function updateObject ( object , currentObject ) {
57+ async function updateObject ( object , rootObject , currentObject , tagGroups ) {
58+ let changed = false ;
59+
5660 const configuration = getPluginConfiguration ( ) ;
5761
5862 if ( currentObject ) addDataFromCurrentObject ( object , currentObject ) ;
@@ -65,14 +69,19 @@ async function updateObject(object, currentObject) {
6569 if ( ! wfsConfiguration ) return ;
6670
6771 for ( let fieldConfiguration of wfsConfiguration . geometry_fields ) {
68- const geometryIds = await getGeometryIds ( object , fieldConfiguration . field_path . split ( '.' ) ) ;
69- if ( geometryIds . length && await hasUsedGeometryIds ( configuration , geometryIds , object . _uuid ) ) {
72+ const geometryFieldValues = await getFieldValues ( object , fieldConfiguration . field_path . split ( '.' ) ) ;
73+ const geometryIds = await getGeometryIds ( geometryFieldValues ) ;
74+ if ( geometryIds . all . length && await hasUsedGeometryIds ( configuration , geometryIds , object . _uuid ) ) {
7075 return throwErrorToFrontend ( 'Eine oder mehrere Geometrien sind bereits mit anderen Objekten verknüpft.' , undefined , 'multipleGeometryLinking' ) ;
7176 }
7277
7378 await editGeometries ( object , fieldConfiguration , geometryIds ) ;
7479 if ( currentObject ) await deleteGeometries ( fieldConfiguration , geometryIds , currentObject ) ;
80+ if ( await handleNewlyDrawnGeometries ( rootObject , tagGroups , geometryIds , fieldConfiguration ) ) changed = true ;
81+ if ( cleanUpGeometryIds ( rootObject , fieldConfiguration ) ) changed = true ;
7582 }
83+
84+ return changed ;
7685}
7786
7887function getLinkedObjectConfiguration ( objectType , configuration ) {
@@ -87,24 +96,54 @@ async function updateLinkedObjects(object, linkedObjectConfiguration) {
8796 }
8897}
8998
90- async function getGeometryIds ( object , pathSegments ) {
91- let geometryIds = [ ] ;
99+ function getGeometryIds ( fieldValues ) {
100+ const result = {
101+ all : [ ] ,
102+ newlyDrawn : [ ] ,
103+ replaced : { }
104+ } ;
92105
93- for ( let fieldValue of await getFieldValues ( object , pathSegments ) ) {
94- if ( ! fieldValue ?. geometry_ids ?. length ) continue ;
95- geometryIds = geometryIds . concat (
96- fieldValue . geometry_ids . filter ( value => value !== undefined )
97- ) ;
106+ for ( let fieldValue of fieldValues ) {
107+ if ( fieldValue ?. geometry_ids ?. length ) {
108+ result . all = result . all . concat ( fieldValue . geometry_ids . filter ( value => value !== undefined ) ) ;
109+ }
110+ if ( fieldValue ?. newly_drawn_geometry_ids ?. length ) {
111+ result . newlyDrawn = result . newlyDrawn . concat ( fieldValue . newly_drawn_geometry_ids . filter ( value => value !== undefined ) ) ;
112+ }
113+ if ( fieldValue ?. replaced_geometry_ids ) {
114+ Object . keys ( fieldValue . replaced_geometry_ids ) . forEach ( geometryId => {
115+ result . replaced [ geometryId ] = fieldValue . replaced_geometry_ids [ geometryId ] ;
116+ } ) ;
117+ }
98118 }
99119
100- return geometryIds ;
120+ return result ;
121+ }
122+
123+ async function cleanUpGeometryIds ( rootObject , fieldConfiguration ) {
124+ let changed = false ;
125+
126+ const fieldValues = await getFieldValues ( rootObject [ rootObject . _objecttype ] , fieldConfiguration . field_path . split ( '.' ) ) ;
127+
128+ for ( let fieldValue of fieldValues ) {
129+ if ( fieldValue ?. newly_drawn_geometry_ids ) {
130+ delete fieldValue . newly_drawn_geometry_ids ;
131+ changed = true ;
132+ }
133+ if ( fieldValue ?. replaced_geometry_ids ) {
134+ delete fieldValue . replaced_geometry_ids ;
135+ changed = true ;
136+ }
137+ }
138+
139+ return changed ;
101140}
102141
103142async function hasUsedGeometryIds ( configuration , geometryIds , uuid ) {
104143 const geometryFieldPaths = getGeometryFieldPaths ( configuration ) ;
105144 const url = info . api_url + '/api/v1/search?access_token=' + info . api_user_access_token ;
106145 const searchRequest = {
107- search : geometryIds . map ( geometryId => {
146+ search : geometryIds . all . map ( geometryId => {
108147 return {
109148 type : 'match' ,
110149 bool : 'should' ,
@@ -147,27 +186,42 @@ async function editGeometries(object, fieldConfiguration, geometryIds) {
147186 if ( isSendingDataToGeoserverActivated ( fieldConfiguration , geometryIds ) ) {
148187 const changeMap = await getChangeMap ( object , fieldConfiguration ) ;
149188 if ( Object . keys ( changeMap ) . length ) {
150- const requestXml = getEditRequestXml ( geometryIds , changeMap , fieldConfiguration . edit_wfs_feature_type ) ;
151- await performEditTransaction ( geometryIds , requestXml , fieldConfiguration ) ;
189+ const requestXml = getEditRequestXml ( geometryIds . all , changeMap , fieldConfiguration . edit_wfs_feature_type ) ;
190+ await performEditTransaction ( geometryIds . all , requestXml , fieldConfiguration ) ;
152191 }
153192 }
154193}
155194
156195async function deleteGeometries ( fieldConfiguration , geometryIds , currentObject ) {
157196 if ( ! currentObject ) return ;
197+ await markGeometriesAsReplaced ( geometryIds , fieldConfiguration ) ;
158198 const deletedGeometryIds = await getDeletedGeometryIds ( geometryIds , currentObject , fieldConfiguration ) ;
159199 if ( deletedGeometryIds . length ) await performDeleteTransaction ( deletedGeometryIds , fieldConfiguration ) ;
160200}
161201
162202async function getDeletedGeometryIds ( geometryIds , currentObject , fieldConfiguration ) {
163- const currentGeometryIds = await getGeometryIds ( currentObject , fieldConfiguration . field_path . split ( '.' ) ) ;
164- return currentGeometryIds . filter ( geometryId => ! geometryIds . includes ( geometryId ) ) ;
203+ const currentGeometryFieldValues = await getFieldValues ( currentObject , fieldConfiguration . field_path . split ( '.' ) ) ;
204+ const currentGeometryIds = await getGeometryIds ( currentGeometryFieldValues ) ;
205+ const replacedGeometryIds = Object . keys ( geometryIds . replaced ) ;
206+ return currentGeometryIds . all . filter ( geometryId => {
207+ return ! geometryIds . all . includes ( geometryId ) && ! replacedGeometryIds . includes ( geometryId ) ;
208+ } ) . concat ( replacedGeometryIds ) ;
209+ }
210+
211+ async function markGeometriesAsReplaced ( geometryIds , fieldConfiguration ) {
212+ const wfsReplacedByFieldName = getPluginConfiguration ( ) . wfs_replaced_by_field_name ;
213+ const featureType = fieldConfiguration . edit_wfs_feature_type ;
214+
215+ for ( let [ replacedGeometryId , newGeometryId ] of Object . entries ( geometryIds . replaced ) ) {
216+ const requestXml = getMarkAsReplacedRequestXml ( replacedGeometryId , newGeometryId , wfsReplacedByFieldName , featureType ) ;
217+ await performEditTransaction ( [ replacedGeometryId ] , requestXml , fieldConfiguration ) ;
218+ }
165219}
166220
167221function isSendingDataToGeoserverActivated ( fieldConfiguration , geometryIds ) {
168222 return fieldConfiguration . send_data_to_geoserver
169223 && fieldConfiguration . edit_wfs_url
170- && geometryIds ? .length ;
224+ && geometryIds . all . length ;
171225}
172226
173227function addDataFromCurrentObject ( object , currentObject ) {
@@ -385,7 +439,7 @@ async function performDeleteTransaction(geometryIds, fieldConfiguration) {
385439}
386440
387441async function performTransaction ( requestXml , wfsUrl ) {
388- const transactionUrl = wfsUrl + '?service=WFS&version=1.1.0&request=Transaction' ; ;
442+ const transactionUrl = wfsUrl + '?service=WFS&version=1.1.0&request=Transaction' ;
389443
390444 try {
391445 const response = await fetch ( transactionUrl , {
@@ -423,6 +477,18 @@ function getMarkAsTemporaryRequestXml(geometryIds, propertyName, featureType) {
423477 ) ;
424478}
425479
480+ function getMarkAsReplacedRequestXml ( replacedGeometryId , newGeometryId , propertyName , featureType ) {
481+ return getTransactionXml (
482+ '<wfs:Update typeName="' + featureType + '">'
483+ + '<wfs:Property>'
484+ + '<wfs:Name>' + propertyName + '</wfs:Name>'
485+ + '<wfs:Value>' + newGeometryId + '</wfs:Value>'
486+ + '</wfs:Property>'
487+ + getFilterXml ( [ replacedGeometryId ] )
488+ + '</wfs:Update>'
489+ ) ;
490+ }
491+
426492function getDeleteRequestXml ( geometryIds , featureType ) {
427493 return getTransactionXml (
428494 '<wfs:Delete typeName="' + featureType + '">'
@@ -471,32 +537,19 @@ function getGeometryFilterXml(geometryId) {
471537 + '</ogc:PropertyIsEqualTo>' ;
472538}
473539
474- async function handleNewlyDrawnGeometries ( object , tagGroups ) {
475- const configuration = getPluginConfiguration ( ) ;
476- const wfsConfiguration = getWFSConfiguration ( configuration , object . _objecttype ) ;
477- if ( ! wfsConfiguration ) return false ;
540+ async function handleNewlyDrawnGeometries ( rootObject , tagGroups , geometryIds , fieldConfiguration ) {
541+ if ( ! geometryIds . newlyDrawn ?. length ) return false ;
478542
543+ const configuration = getPluginConfiguration ( ) ;
479544 const wfsTemporaryGeometryFieldName = configuration . wfs_temporary_geometry_field_name ;
480545 const temporaryGeometryTagId = configuration . temporary_geometry_tag_id ;
481546
482- let changed = false ;
483- for ( let fieldConfiguration of wfsConfiguration . geometry_fields ) {
484- for ( let fieldValue of await getFieldValues ( object [ object . _objecttype ] , fieldConfiguration . field_path . split ( '.' ) ) ) {
485- const newlyDrawnGeometryIds = fieldValue . newly_drawn_geometry_ids ;
486- if ( newlyDrawnGeometryIds ) {
487- delete fieldValue . newly_drawn_geometry_ids ;
488- changed = true ;
489- }
490- if ( ! newlyDrawnGeometryIds ?. length ) continue ;
491-
492- if ( wfsTemporaryGeometryFieldName ) {
493- await markGeometriesAsTemporary ( newlyDrawnGeometryIds , fieldConfiguration , wfsTemporaryGeometryFieldName ) ;
494- }
495- if ( temporaryGeometryTagId ) setTag ( object , temporaryGeometryTagId , tagGroups ) ;
496- }
547+ if ( wfsTemporaryGeometryFieldName ) {
548+ await markGeometriesAsTemporary ( geometryIds . newlyDrawn , fieldConfiguration , wfsTemporaryGeometryFieldName ) ;
497549 }
550+ if ( temporaryGeometryTagId ) setTag ( rootObject , temporaryGeometryTagId , tagGroups ) ;
498551
499- return changed ;
552+ return true ;
500553}
501554
502555async function markGeometriesAsTemporary ( geometryIds , fieldConfiguration , wfsTemporaryGeometryFieldName ) {
@@ -511,12 +564,12 @@ function getAuthorizationString(configuration) {
511564 return btoa ( username + ':' + password ) ;
512565}
513566
514- function setTag ( object , tagId , tagGroups ) {
567+ function setTag ( rootObject , tagId , tagGroups ) {
515568 const tagGroup = tagGroups . find ( group => group . _tags . find ( entry => entry . tag . _id === tagId ) ) ;
516569 const tagsIdsToRemove = tagGroup . taggroup . type === 'choice'
517570 ? tagGroup . _tags . map ( entry => entry . tag . _id )
518571 : [ tagId ] ;
519- object . _tags = object . _tags . filter ( tag => ! tagsIdsToRemove . includes ( tag . _id ) )
572+ rootObject . _tags = rootObject . _tags . filter ( tag => ! tagsIdsToRemove . includes ( tag . _id ) )
520573 . concat ( [ { _id : tagId } ] ) ;
521574}
522575
0 commit comments