Skip to content

Commit 2e5ed0e

Browse files
authored
Merge pull request #12 from UmbrellaInc/feature/nupickers-connector
nuPickers ValueConnector
2 parents 645f7c2 + df398ac commit 2e5ed0e

File tree

3 files changed

+207
-0
lines changed

3 files changed

+207
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ This project offers Umbraco Deploy connectors for the following community packag
1717
- [LeBlender](https://our.umbraco.org/projects/backoffice-extensions/leblender)
1818
- [Nested Content](https://our.umbraco.org/projects/backoffice-extensions/nested-content/)
1919
- [Stacked Content](https://github.com/umco/umbraco-stacked-content)
20+
- [nuPickers](https://our.umbraco.org/projects/backoffice-extensions/nupickers/)
2021

2122
---
2223

src/Umbraco.Deploy.Contrib.Connectors/Umbraco.Deploy.Contrib.Connectors.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@
239239
<Compile Include="Properties\VersionInfo.cs" />
240240
<Compile Include="ValueConnectors\ArchetypeValueConnector.cs" />
241241
<Compile Include="ValueConnectors\MultiUrlPickerValueConnector.cs" />
242+
<Compile Include="ValueConnectors\NuPickersValueConnector.cs" />
242243
<Compile Include="ValueConnectors\RelatedLinksValueConnector.cs" />
243244
<Compile Include="ValueConnectors\RelatedLinks2ValueConnector.cs" />
244245
<Compile Include="ValueConnectors\VortoValueConnector.cs" />
Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Xml.Linq;
5+
using Newtonsoft.Json;
6+
using Newtonsoft.Json.Linq;
7+
using Umbraco.Core;
8+
using Umbraco.Core.Deploy;
9+
using Umbraco.Core.Models;
10+
using Umbraco.Core.Services;
11+
12+
namespace Umbraco.Deploy.Contrib.Connectors.ValueConnectors
13+
{
14+
/// <summary>
15+
/// A Deploy connector for the nuPickers property editor, when used with Umbraco content & media.
16+
/// </summary>
17+
public class NuPickersValueConnector : IValueConnector
18+
{
19+
private readonly IEntityService _entityService;
20+
21+
private enum SaveFormat
22+
{
23+
CSV,
24+
JSON,
25+
XML
26+
}
27+
28+
/// <summary>
29+
/// Initializes a new instance of the <see cref="NuPickersValueConnector"/> class.
30+
/// </summary>
31+
/// <param name="entityService">An <see cref="IEntityService"/> implementation.</param>
32+
public NuPickersValueConnector(IEntityService entityService)
33+
{
34+
_entityService = entityService ?? throw new ArgumentNullException(nameof(entityService));
35+
}
36+
37+
public IEnumerable<string> PropertyEditorAliases => Enumerable.Empty<string>();
38+
39+
/// <summary>
40+
/// Gets the deploy property corresponding to a content property.
41+
/// </summary>
42+
/// <param name="property">The content property.</param>
43+
/// <param name="dependencies">The content dependencies.</param>
44+
/// <returns>The deploy property value.</returns>
45+
public string GetValue(Property property, ICollection<ArtifactDependency> dependencies)
46+
{
47+
// get the property value
48+
var value = property.Value as string;
49+
50+
if (string.IsNullOrWhiteSpace(value))
51+
return null;
52+
53+
// parse the value - checking the format - CSV, XML or JSON
54+
SaveFormat format;
55+
var items = ParseValue(value, out format);
56+
57+
var result = new List<KeyValuePair<string, string>>();
58+
59+
// loop over the values
60+
foreach (var item in items)
61+
{
62+
int nodeId;
63+
if (int.TryParse(item.Key, out nodeId))
64+
{
65+
// if an INT, attempt to get the UDI
66+
var guidUdi = GetGuidUdi(nodeId);
67+
if (guidUdi != null)
68+
{
69+
dependencies.Add(new ArtifactDependency(guidUdi, false, ArtifactDependencyMode.Exist));
70+
result.Add(new KeyValuePair<string, string>(guidUdi.ToString(), item.Value));
71+
}
72+
else
73+
{
74+
// the value isn't a UDI, assume it's "just a string"
75+
result.Add(item);
76+
}
77+
}
78+
else
79+
{
80+
// the value isn't a node ID, assume it's "just a string"
81+
result.Add(item);
82+
}
83+
}
84+
85+
// return the value in the correct format - CSV, XML, JSON, (whatevs)
86+
return SerializeValue(result, format);
87+
}
88+
89+
/// <summary>
90+
/// Sets a content property value using a deploy property.
91+
/// </summary>
92+
/// <param name="content">The content item.</param>
93+
/// <param name="alias">The property alias.</param>
94+
/// <param name="value">The deploy property value.</param>
95+
public void SetValue(IContentBase content, string alias, string value)
96+
{
97+
// parse the value - checking the format - CSV, XML or JSON
98+
SaveFormat format;
99+
var items = ParseValue(value, out format);
100+
101+
var result = new List<KeyValuePair<string, string>>();
102+
103+
// loop over the values
104+
foreach (var item in items)
105+
{
106+
GuidUdi guidUdi;
107+
if (GuidUdi.TryParse(item.Key, out guidUdi) && guidUdi.Guid != Guid.Empty)
108+
{
109+
// if an UDI, attempt to get the INT
110+
var nodeId = GetIntId(guidUdi.Guid);
111+
if (nodeId > 0)
112+
{
113+
result.Add(new KeyValuePair<string, string>(nodeId.ToString(), item.Value));
114+
}
115+
else
116+
{
117+
// the value isn't a node ID, assume it's "just a string"
118+
result.Add(item);
119+
}
120+
}
121+
else
122+
{
123+
// the value isn't a UDI, assume it's "just a string"
124+
result.Add(item);
125+
}
126+
}
127+
128+
// re-assemble the values into the correct format - CSV, XML, JSON, (whatevs)
129+
content.SetValue(alias, SerializeValue(result, format));
130+
}
131+
132+
private IEnumerable<KeyValuePair<string, string>> ParseValue(string value, out SaveFormat format)
133+
{
134+
// code taken from nuPickers
135+
// ref: https://github.com/uComponents/nuPickers/blob/master/source/nuPickers/Shared/SaveFormat/SaveFormat.cs#L43
136+
if (!string.IsNullOrWhiteSpace(value))
137+
{
138+
switch (value[0])
139+
{
140+
case '[':
141+
format = SaveFormat.JSON;
142+
return JsonConvert.DeserializeObject<JArray>(value).Select(x => new KeyValuePair<string, string>(x["key"].ToString(), x["label"].ToString()));
143+
144+
case '<':
145+
format = SaveFormat.XML;
146+
return XDocument.Parse(value).Descendants("Picked").Select(x => new KeyValuePair<string, string>(x.Attribute("Key").Value, x.Value));
147+
148+
default:
149+
format = SaveFormat.CSV;
150+
return value.Split(',').Select(x => new KeyValuePair<string, string>(x, null)); // NOTE: label is null
151+
}
152+
}
153+
154+
format = SaveFormat.CSV;
155+
return Enumerable.Empty<KeyValuePair<string, string>>();
156+
}
157+
158+
private string SerializeValue(IEnumerable<KeyValuePair<string, string>> value, SaveFormat format)
159+
{
160+
// ref: https://github.com/uComponents/nuPickers/wiki/Save-Formats
161+
// ref: https://github.com/uComponents/nuPickers/blob/master/source/nuPickers/Shared/SaveFormat/SaveFormatResource.js#L16
162+
163+
switch (format)
164+
{
165+
case SaveFormat.JSON:
166+
var json = value.Select(x => $"{{ 'key': '{x.Key}', 'label': '{x.Value}' }}");
167+
return string.Concat("[", string.Join(",", json, "]"));
168+
169+
case SaveFormat.XML:
170+
var xml = value.Select(x => $"<Picked Key=\"{x.Key}\"><![CDATA[{x.Value}]]></Picked>");
171+
return string.Concat("<Picker>", string.Join(",", xml, "</Picker>"));
172+
173+
case SaveFormat.CSV:
174+
default:
175+
return string.Join(",", value.Select(x => x.Key));
176+
}
177+
}
178+
179+
private GuidUdi GetGuidUdi(int id)
180+
{
181+
var keyForId = _entityService.GetKeyForId(id, UmbracoObjectTypes.Document);
182+
if (keyForId.Success)
183+
return new GuidUdi(Constants.UdiEntityType.Document, keyForId.Result);
184+
185+
keyForId = _entityService.GetKeyForId(id, UmbracoObjectTypes.Media);
186+
if (keyForId.Success)
187+
return new GuidUdi(Constants.UdiEntityType.Media, keyForId.Result);
188+
189+
return null;
190+
}
191+
192+
private int GetIntId(Guid id)
193+
{
194+
var idForKey = _entityService.GetIdForKey(id, UmbracoObjectTypes.Document);
195+
if (idForKey.Success)
196+
return idForKey.Result;
197+
198+
idForKey = _entityService.GetIdForKey(id, UmbracoObjectTypes.Media);
199+
if (idForKey.Success)
200+
return idForKey.Result;
201+
202+
return -1;
203+
}
204+
}
205+
}

0 commit comments

Comments
 (0)