1
+ using System ;
2
+ using System . Collections . Generic ;
3
+ using Newtonsoft . Json ;
4
+ using Newtonsoft . Json . Linq ;
5
+ using Umbraco . Core ;
6
+ using Umbraco . Core . Deploy ;
7
+ using Umbraco . Core . Models ;
8
+ using Umbraco . Core . Services ;
9
+ using Umbraco . Deploy . ValueConnectors ;
10
+
11
+ namespace Umbraco . Deploy . Contrib . Connectors . ValueConnectors
12
+ {
13
+ public class PropertyListValueConnector : IValueConnector
14
+ {
15
+ private readonly IDataTypeService _dataTypeService ;
16
+
17
+ private readonly Lazy < ValueConnectorCollection > _valueConnectorsLazy ;
18
+
19
+ public PropertyListValueConnector ( IDataTypeService dataTypeService , Lazy < ValueConnectorCollection > valueConnectors )
20
+ {
21
+ Mandate . ParameterNotNull ( dataTypeService , nameof ( dataTypeService ) ) ;
22
+ Mandate . ParameterNotNull ( valueConnectors , nameof ( valueConnectors ) ) ;
23
+
24
+ _dataTypeService = dataTypeService ;
25
+ _valueConnectorsLazy = valueConnectors ;
26
+ }
27
+
28
+ public IEnumerable < string > PropertyEditorAliases => new [ ] { "Our.Umbraco.PropertyList" } ;
29
+
30
+ private ValueConnectorCollection ValueConnectors => _valueConnectorsLazy . Value ;
31
+
32
+ public string GetValue ( Property property , ICollection < ArtifactDependency > dependencies )
33
+ {
34
+ // get the property value
35
+ var value = property . Value ? . ToString ( ) ;
36
+ if ( string . IsNullOrWhiteSpace ( value ) )
37
+ return null ;
38
+
39
+ // deserialize it
40
+ var model = JsonConvert . DeserializeObject < PropertyListValue > ( value ) ;
41
+ if ( model == null )
42
+ return null ;
43
+
44
+ // get the selected data-type (and ensure it exists)
45
+ var dataType = _dataTypeService . GetDataTypeDefinitionById ( model . DataTypeGuid ) ;
46
+
47
+ if ( dataType == null )
48
+ throw new InvalidOperationException ( $ "Could not resolve the data-type used by the Property List value for: { property . Alias } ") ;
49
+
50
+ // add the selected data-type as a dependency
51
+ dependencies . Add ( new ArtifactDependency ( dataType . GetUdi ( ) , false , ArtifactDependencyMode . Match ) ) ;
52
+
53
+ // make a property-type to use in a mocked Property
54
+ // and get the value-connector needed to parse values (outside the loop, as it's the same for all iterations)
55
+ var propertyType = new PropertyType ( dataType ) ;
56
+ var valueConnector = ValueConnectors . Get ( propertyType ) ;
57
+
58
+ // loop through each value
59
+ for ( int i = 0 ; i < model . Values . Count ; i ++ )
60
+ {
61
+ // pass it to its own value-connector
62
+ // set the parsed value back onto the original object, (it may be a string representing more json. which is fine)
63
+ model . Values [ i ] = valueConnector . GetValue ( new Property ( propertyType , model . Values [ i ] ) , dependencies ) ;
64
+ }
65
+
66
+ return JsonConvert . SerializeObject ( model ) ;
67
+ }
68
+
69
+ public void SetValue ( IContentBase content , string alias , string value )
70
+ {
71
+ // take the value
72
+ if ( string . IsNullOrWhiteSpace ( value ) )
73
+ return ;
74
+
75
+ // deserialize it
76
+ var model = JsonConvert . DeserializeObject < PropertyListValue > ( value ) ;
77
+ if ( model == null )
78
+ return ;
79
+
80
+ // get the selected data-type (and ensure it exists)
81
+ var dataType = _dataTypeService . GetDataTypeDefinitionById ( model . DataTypeGuid ) ;
82
+
83
+ if ( dataType == null )
84
+ throw new InvalidOperationException ( $ "Could not resolve the data-type used by the Property List value for: { alias } ") ;
85
+
86
+ // make a property-type to use in a mocked Property
87
+ // and get the value-connector needed to parse values (outside the loop, as it's the same for all iterations)
88
+ var propertyType = new PropertyType ( dataType , "mockPropertyListAlias" ) ;
89
+ var valueConnector = ValueConnectors . Get ( propertyType ) ;
90
+
91
+ // loop through each value
92
+ for ( int i = 0 ; i < model . Values . Count ; i ++ )
93
+ {
94
+ var item = model . Values [ i ] ;
95
+
96
+ var mockProperty = new Property ( propertyType ) ;
97
+ var mockContent = new Content ( "mockContent" , - 1 , new ContentType ( - 1 ) , new PropertyCollection ( new List < Property > { mockProperty } ) ) ;
98
+
99
+ // pass it to its own value-connector
100
+ // NOTE: due to how ValueConnector.SetValue() works, we have to pass the mock item
101
+ // through to the connector to have it do its work on parsing the value on the item itself.
102
+ valueConnector . SetValue ( mockContent , mockProperty . Alias , item ? . ToString ( ) ) ;
103
+
104
+ // get the value back and assign
105
+ model . Values [ i ] = mockContent . GetValue ( mockProperty . Alias ) ;
106
+ }
107
+
108
+ // serialize the JSON values
109
+ content . SetValue ( alias , JObject . FromObject ( model ) . ToString ( ) ) ;
110
+ }
111
+
112
+ public class PropertyListValue
113
+ {
114
+ [ JsonProperty ( "dtd" ) ]
115
+ public Guid DataTypeGuid { get ; set ; }
116
+
117
+ [ JsonProperty ( "values" ) ]
118
+ public List < object > Values { get ; set ; }
119
+ }
120
+ }
121
+ }
0 commit comments