11using System . Collections . Generic ;
22using System . Collections . Specialized ;
33using System . Linq ;
4+ using System . Xml ;
45using FieldFallback . Data ;
56using Sitecore . Data ;
67using Sitecore . Data . Fields ;
@@ -13,14 +14,11 @@ internal class FallbackItem : CustomItemBase
1314 {
1415 public static readonly ID FallbackFields = new ID ( "{8A826BE2-C878-49DA-A0F7-32DB6718E2FB}" ) ;
1516
16- private NameValueCollection _fallbackConfiguration ;
17- private Dictionary < ID , List < Field > > _fallbackDefinition ;
18-
1917 private FallbackItem ( Item innerItem ) : base ( innerItem )
2018 {
21-
19+ Initialize ( ) ;
2220 }
23-
21+
2422 public static implicit operator FallbackItem ( Item item )
2523 {
2624 if ( item == null )
@@ -30,7 +28,7 @@ public static implicit operator FallbackItem(Item item)
3028
3129 return new FallbackItem ( item ) ;
3230 }
33-
31+
3432 /// <summary>
3533 /// Gets a value indicating whether this item has lateral fallback configured.
3634 /// </summary>
@@ -41,58 +39,32 @@ public bool HasLateralFallback
4139 {
4240 get
4341 {
44- return FallbackConfiguration . HasKeys ( ) ;
45- }
46- }
47-
48- /// <summary>
49- /// Gets the fallback configuration from the "FallbackFields" field.
50- /// </summary>
51- /// <value>The fallback configuration.</value>
52- protected NameValueCollection FallbackConfiguration
53- {
54- get
55- {
56- if ( _fallbackConfiguration == null )
57- {
58- // don't use fallback on this configuration field
59- using ( new FallbackDisabler ( ) )
60- {
61- _fallbackConfiguration = WebUtil . ParseUrlParameters ( InnerItem [ FallbackFields ] ) ;
62- }
63- }
64- return _fallbackConfiguration ?? new NameValueCollection ( 0 ) ;
42+ return FallbackDefinition . Keys . Count > 0 ;
6543 }
6644 }
6745
6846 /// <summary>
6947 /// Gets the fallback definition.
7048 /// </summary>
7149 /// <value>The fallback definition.</value>
72- protected Dictionary < ID , List < Field > > FallbackDefinition
50+ protected Dictionary < ID , Setting > FallbackDefinition
7351 {
74- get
75- {
76- if ( _fallbackDefinition == null )
77- {
78- _fallbackDefinition = InitializeLateralFallbackConfiguration ( ) ;
79- }
80- return _fallbackDefinition ;
81- }
52+ get ;
53+ private set ;
8254 }
8355
8456 /// <summary>
8557 /// Gets the fallback fields for the given field.
8658 /// </summary>
8759 /// <param name="field">The field.</param>
8860 /// <returns></returns>
89- public List < Field > GetFallbackFields ( Field field )
61+ public Setting GetFallbackFields ( Field field )
9062 {
9163 if ( DoesFieldHaveLateralFallback ( field ) )
9264 {
9365 return FallbackDefinition [ field . ID ] ;
9466 }
95- return new List < Field > ( 0 ) ;
67+ return null ;
9668 }
9769
9870 /// <summary>
@@ -114,51 +86,134 @@ public IEnumerable<ID> GetFieldsThatFallbackTo(Field field)
11486 {
11587 foreach ( ID key in FallbackDefinition . Keys )
11688 {
117- if ( FallbackDefinition [ key ] . Any ( f => f . ID == field . ID ) )
89+ if ( FallbackDefinition [ key ] . SourceFields . Any ( f => f . ID == field . ID ) )
11890 {
11991 yield return key ;
12092 }
12193 }
12294 }
12395
124- /// <summary>
125- /// Converts the NameValueCollection into Dictionary<ID, List<Field>>
126- /// where the key is the ID of the field to recieve the fallback value
127- /// and the values are the list of fields to check for a fallback value
128- /// </summary>
129- /// <returns></returns>
130- private Dictionary < ID , List < Field > > InitializeLateralFallbackConfiguration ( )
96+ private void Initialize ( )
13197 {
132- Dictionary < ID , List < Field > > dic ;
133- if ( ! HasLateralFallback )
98+ var _fallbackDefinition = new Dictionary < ID , Setting > ( ) ;
99+
100+ // don't use fallback on this configuration field
101+ using ( new FallbackDisabler ( ) )
134102 {
135- dic = new Dictionary < ID , List < Field > > ( 0 ) ;
103+ // try to get this fields as an XML field
104+ // Original version of this field was key/value pair
105+ // It was converted to XML to support advanced options
106+ XmlField test = InnerItem . Fields [ FallbackFields ] ;
107+ if ( test . Xml == null )
108+ {
109+ ParseNameValueConfiguration ( InnerItem [ FallbackFields ] , _fallbackDefinition ) ;
110+ }
111+ else
112+ {
113+ ParseXmlConfiguration ( test , _fallbackDefinition ) ;
114+ }
136115 }
137- else
116+ FallbackDefinition = _fallbackDefinition ;
117+ }
118+
119+ private void ParseNameValueConfiguration ( string oldConfigurationValue , Dictionary < ID , Setting > settings )
120+ {
121+ NameValueCollection fallbackConfiguration = WebUtil . ParseUrlParameters ( oldConfigurationValue ) ;
122+ foreach ( string fieldName in fallbackConfiguration . AllKeys )
138123 {
139- dic = new Dictionary < ID , List < Field > > ( ) ;
140- foreach ( string fieldName in FallbackConfiguration . AllKeys )
141- {
142- Field mainField = InnerItem . Fields [ fieldName ] ;
124+ Field mainField = InnerItem . Fields [ fieldName ] ;
143125
144- if ( mainField != null )
126+ if ( mainField != null )
127+ {
128+ List < Field > fallbackFields = new List < Field > ( ) ;
129+ List < string > fallbackFieldNames = fallbackConfiguration . GetValues ( fieldName ) . FirstOrDefault ( ) . Split ( new char [ ] { '|' , ',' , ';' } , System . StringSplitOptions . RemoveEmptyEntries ) . ToList ( ) ;
130+ foreach ( string fallbackFieldName in fallbackFieldNames )
145131 {
146- List < Field > fallbackFields = new List < Field > ( ) ;
147- List < string > fallbackFieldNames = FallbackConfiguration . GetValues ( fieldName ) . FirstOrDefault ( ) . Split ( new char [ ] { '|' , ',' , ';' } , System . StringSplitOptions . RemoveEmptyEntries ) . ToList ( ) ;
148- foreach ( string fallbackFieldName in fallbackFieldNames )
132+ Field f = InnerItem . Fields [ fallbackFieldName ] ;
133+ if ( f != null )
149134 {
150- Field f = InnerItem . Fields [ fallbackFieldName ] ;
151- if ( f != null )
152- {
153- fallbackFields . Add ( f ) ;
154- }
135+ fallbackFields . Add ( f ) ;
155136 }
137+ }
138+
139+ Setting setting = new Setting ( ) ;
140+ setting . SourceFields = fallbackFields ;
156141
157- dic . Add ( mainField . ID , fallbackFields ) ;
142+ settings . Add ( mainField . ID , setting ) ;
143+ }
144+ }
145+ }
146+
147+ private void ParseXmlConfiguration ( XmlField fallbackField , Dictionary < ID , Setting > settings )
148+ {
149+ // complex structure...
150+ // TODO: Create a nice Sitecore field editing interface for this
151+
152+ /// <fallback>
153+ /// <setting target="{id}" source="{id}|{id}|{id}..." enableEllipsis="true|false" clipAt="{number chars}" />
154+ /// <setting target="{id}" source="{id}|{id}|{id}..." enableEllipsis="true|false" clipAt="{number chars}" />
155+ /// ...
156+ /// </fallback>
157+
158+ foreach ( XmlNode child in fallbackField . Xml . FirstChild . ChildNodes )
159+ {
160+ XmlAttribute target = child . Attributes [ "target" ] ;
161+ XmlAttribute source = child . Attributes [ "source" ] ;
162+ XmlAttribute enableEllipsis = child . Attributes [ "enableEllipsis" ] ;
163+ XmlAttribute clipAt = child . Attributes [ "clipAt" ] ;
164+
165+ /// TODO: Guard against improper input.. move to factory
166+ Setting setting = new Setting ( ) ;
167+
168+ if ( enableEllipsis != null )
169+ {
170+ setting . UseEllipsis = bool . Parse ( enableEllipsis . Value ) ;
171+ }
172+
173+ if ( clipAt != null )
174+ {
175+ int i ;
176+ if ( int . TryParse ( clipAt . Value , out i ) && i > 0 )
177+ {
178+ setting . ClipAt = i ;
179+ }
180+ }
181+
182+ List < Field > fallbackFields = new List < Field > ( ) ;
183+ List < string > fallbackFieldNames = source . Value . Split ( new char [ ] { '|' , ',' , ';' } , System . StringSplitOptions . RemoveEmptyEntries ) . ToList ( ) ;
184+ foreach ( string fallbackFieldName in fallbackFieldNames )
185+ {
186+ Field f = InnerItem . Fields [ fallbackFieldName ] ;
187+ if ( f != null )
188+ {
189+ fallbackFields . Add ( f ) ;
158190 }
159191 }
192+
193+ setting . SourceFields = fallbackFields ;
194+
195+ ID targetID = new Sitecore . Data . ID ( target . Value ) ;
196+
197+ settings . Add ( targetID , setting ) ;
198+
160199 }
161- return dic ;
200+ }
201+
202+ internal class Setting
203+ {
204+ public List < Sitecore . Data . Fields . Field > SourceFields { get ; set ; }
205+
206+ public bool TruncateText
207+ {
208+ get
209+ {
210+ return ClipAt . HasValue ;
211+ }
212+ }
213+
214+ public bool UseEllipsis { get ; set ; }
215+
216+ public int ? ClipAt { get ; set ; }
162217 }
163218 }
164219}
0 commit comments