Skip to content
This repository was archived by the owner on Feb 10, 2024. It is now read-only.

Commit e0bf20e

Browse files
committed
first
1 parent 3782b18 commit e0bf20e

29 files changed

+2003
-0
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.vs
2+
Our.Umbraco.DocTypeGridEditor9.Testsite
3+
bin
4+
obj
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 16
4+
VisualStudioVersion = 16.0.30711.63
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Our.Umbraco.DocTypeGridEditor9", "Our.Umbraco.DocTypeGridEditor9\Our.Umbraco.DocTypeGridEditor9.csproj", "{D4318AFD-033C-46FC-9DD2-9FC57934CD2F}"
7+
EndProject
8+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Our.Umbraco.DocTypeGridEditor9.Testsite", "Our.Umbraco.DocTypeGridEditor9.Testsite\Our.Umbraco.DocTypeGridEditor9.Testsite.csproj", "{D510AF65-1DCB-4A60-99DE-DA1D3B6E1AC7}"
9+
EndProject
10+
Global
11+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
12+
Debug|Any CPU = Debug|Any CPU
13+
Release|Any CPU = Release|Any CPU
14+
EndGlobalSection
15+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
16+
{D4318AFD-033C-46FC-9DD2-9FC57934CD2F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17+
{D4318AFD-033C-46FC-9DD2-9FC57934CD2F}.Debug|Any CPU.Build.0 = Debug|Any CPU
18+
{D4318AFD-033C-46FC-9DD2-9FC57934CD2F}.Release|Any CPU.ActiveCfg = Release|Any CPU
19+
{D4318AFD-033C-46FC-9DD2-9FC57934CD2F}.Release|Any CPU.Build.0 = Release|Any CPU
20+
{D510AF65-1DCB-4A60-99DE-DA1D3B6E1AC7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21+
{D510AF65-1DCB-4A60-99DE-DA1D3B6E1AC7}.Debug|Any CPU.Build.0 = Debug|Any CPU
22+
{D510AF65-1DCB-4A60-99DE-DA1D3B6E1AC7}.Release|Any CPU.ActiveCfg = Release|Any CPU
23+
{D510AF65-1DCB-4A60-99DE-DA1D3B6E1AC7}.Release|Any CPU.Build.0 = Release|Any CPU
24+
EndGlobalSection
25+
GlobalSection(SolutionProperties) = preSolution
26+
HideSolutionNode = FALSE
27+
EndGlobalSection
28+
GlobalSection(ExtensibilityGlobals) = postSolution
29+
SolutionGuid = {66EC167C-845A-4DCC-87B7-C7DB5CC1E38B}
30+
EndGlobalSection
31+
EndGlobal
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using Our.Umbraco.DocTypeGridEditor9.Helpers;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Text;
6+
using System.Threading.Tasks;
7+
using Umbraco.Cms.Core.Composing;
8+
using Umbraco.Cms.Core.DependencyInjection;
9+
using Umbraco.Extensions;
10+
11+
namespace Our.Umbraco.DocTypeGridEditor9
12+
{
13+
public class DocTypeGridEditorComposer : IUserComposer
14+
{
15+
public void Compose(IUmbracoBuilder builder)
16+
{
17+
builder.Services.AddUnique<DocTypeGridEditorHelper>();
18+
}
19+
}
20+
}
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
using Newtonsoft.Json;
2+
using Newtonsoft.Json.Linq;
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
using System.Text;
7+
using System.Threading.Tasks;
8+
using Umbraco.Cms.Core.Cache;
9+
using Umbraco.Cms.Core.Models;
10+
using Umbraco.Cms.Core.Models.Editors;
11+
using Umbraco.Cms.Core.Models.PublishedContent;
12+
using Umbraco.Cms.Core.PropertyEditors;
13+
using Umbraco.Cms.Core.Web;
14+
using Microsoft.Extensions.Logging;
15+
using Umbraco.Extensions;
16+
using Our.Umbraco.DocTypeGridEditor9.Models;
17+
using Umbraco.Cms.Core.Routing;
18+
using Umbraco.Cms.Core.Services;
19+
20+
namespace Our.Umbraco.DocTypeGridEditor9.Helpers
21+
{
22+
public class DocTypeGridEditorHelper
23+
{
24+
private readonly AppCaches _appCaches;
25+
private readonly IUmbracoContextAccessor _umbracoContext;
26+
private readonly PropertyEditorCollection _dataEditors;
27+
private readonly ILogger<DocTypeGridEditorHelper> _logger;
28+
private readonly IDataTypeService _dataTypeService;
29+
private readonly IPublishedModelFactory _publishedModelFactory;
30+
private readonly IContentTypeService _contentTypeService;
31+
private readonly IPublishedContentTypeFactory _publishedContentTypeFactory;
32+
33+
public DocTypeGridEditorHelper(AppCaches appCaches, IUmbracoContextAccessor umbracoContextAccessor, PropertyEditorCollection dataEditors, ILoggerFactory loggerFactory, IDataTypeService dataTypeService, IPublishedModelFactory publishedModelFactory, IContentTypeService contentTypeService, IPublishedContentTypeFactory publishedContentTypeFactory)
34+
{
35+
_appCaches = appCaches;
36+
_umbracoContext = umbracoContextAccessor;
37+
_dataEditors = dataEditors;
38+
_logger = loggerFactory.CreateLogger<DocTypeGridEditorHelper>();
39+
_dataTypeService = dataTypeService;
40+
_publishedModelFactory = publishedModelFactory;
41+
_contentTypeService = contentTypeService;
42+
_publishedContentTypeFactory = publishedContentTypeFactory;
43+
44+
}
45+
public IPublishedElement ConvertValueToContent(string id, string contentTypeAlias, string dataJson)
46+
{
47+
if (string.IsNullOrWhiteSpace(contentTypeAlias))
48+
return null;
49+
50+
if (dataJson == null)
51+
return null;
52+
53+
if (_umbracoContext.UmbracoContext == null)
54+
return ConvertValue(id, contentTypeAlias, dataJson);
55+
56+
return (IPublishedElement)_appCaches.RequestCache.Get(
57+
$"Our.Umbraco.DocTypeGridEditor.Helpers.DocTypeGridEditorHelper.ConvertValueToContent_{id}_{contentTypeAlias}",
58+
() =>
59+
{
60+
return ConvertValue(id, contentTypeAlias, dataJson);
61+
});
62+
}
63+
64+
private IPublishedElement ConvertValue(string id, string contentTypeAlias, string dataJson)
65+
{
66+
var contentTypes = GetContentTypesByAlias(contentTypeAlias);
67+
var properties = new List<IPublishedProperty>();
68+
69+
// Convert all the properties
70+
var data = JsonConvert.DeserializeObject(dataJson);
71+
var propValues = ((JObject)data).ToObject<Dictionary<string, object>>();
72+
foreach (var jProp in propValues)
73+
{
74+
var propType = contentTypes.PublishedContentType.GetPropertyType(jProp.Key);
75+
if (propType == null)
76+
continue;
77+
78+
79+
/* Because we never store the value in the database, we never run the property editors
80+
* "ConvertEditorToDb" method however the property editors will expect their value to
81+
* be in a "DB" state so to get round this, we run the "ConvertEditorToDb" here before
82+
* we go on to convert the value for the view.
83+
*/
84+
_dataEditors.TryGet(propType.EditorAlias, out var propEditor);
85+
var propPreValues = GetPreValuesCollectionByDataTypeId(propType.DataType.Id);
86+
87+
var contentPropData = new ContentPropertyData(jProp.Value, propPreValues);
88+
89+
var newValue = propEditor.GetValueEditor().FromEditor(contentPropData, jProp.Value);
90+
91+
// Performing "ValueProcessing" if any ValueProcessor is configured for this Property Editor-alias.
92+
// TODO: Process values
93+
//var processorsCollection = Current.Factory.GetInstance<DocTypeGridEditorValueProcessorsCollection>();
94+
//var processor = processorsCollection.FirstOrDefault(x => x.IsProcessorFor(propEditor.Alias));
95+
//if (processor != null)
96+
//{
97+
// newValue = processor.ProcessValue(newValue);
98+
//}
99+
100+
/* Now that we have the DB stored value, we actually need to then convert it into its
101+
* XML serialized state as expected by the published property by calling ConvertDbToString
102+
*/
103+
var propType2 = contentTypes.ContentType.CompositionPropertyTypes.First(x => x.PropertyEditorAlias.InvariantEquals(propType.DataType.EditorAlias));
104+
105+
Property prop2 = null;
106+
try
107+
{
108+
/* HACK: [LK:2016-04-01] When using the "Umbraco.Tags" property-editor, the converted DB value does
109+
* not match the datatypes underlying db-column type. So it throws a "Type validation failed" exception.
110+
* We feel that the Umbraco core isn't handling the Tags value correctly, as it should be the responsiblity
111+
* of the "Umbraco.Tags" property-editor to handle the value conversion into the correct type.
112+
* See: http://issues.umbraco.org/issue/U4-8279
113+
*/
114+
prop2 = new Property(propType2);
115+
prop2.SetValue(newValue);
116+
}
117+
catch (Exception ex)
118+
{
119+
_logger.LogError(new EventId(0), ex, "[DocTypeGridEditor] Error creating Property object.");
120+
}
121+
122+
if (prop2 != null)
123+
{
124+
var newValue2 = propEditor.GetValueEditor().ConvertDbToString(propType2, newValue, _dataTypeService);
125+
126+
properties.Add(new DetachedPublishedProperty(propType, newValue2));
127+
}
128+
}
129+
130+
// Manually parse out the special properties
131+
propValues.TryGetValue("name", out object nameObj);
132+
Guid.TryParse(id, out Guid key);
133+
134+
// Get the current request node we are embedded in
135+
136+
var pcr = _umbracoContext.UmbracoContext.PublishedRequest;
137+
var containerNode = pcr != null && pcr.HasPublishedContent() ? pcr.PublishedContent : null;
138+
139+
// Create the model based on our implementation of IPublishedElement
140+
IPublishedElement content = new DetachedPublishedElement(
141+
key,
142+
contentTypes.PublishedContentType,
143+
properties.ToArray());
144+
145+
if (_publishedModelFactory != null)
146+
{
147+
// Let the current model factory create a typed model to wrap our model
148+
content = _publishedModelFactory.CreateModel(content);
149+
}
150+
151+
return content;
152+
153+
}
154+
155+
private object GetPreValuesCollectionByDataTypeId(int dataTypeId)
156+
{
157+
return (object)_appCaches.RuntimeCache.GetCacheItem(
158+
string.Concat(
159+
"Our.Umbraco.DocTypeGridEditor.Helpers.DocTypeGridEditorHelper.GetPreValuesCollectionByDataTypeId_",
160+
dataTypeId),
161+
() => _dataTypeService.GetDataType(dataTypeId).Configuration);
162+
}
163+
164+
private ContentTypeContainer GetContentTypesByAlias(string contentTypeAlias)
165+
{
166+
if (Guid.TryParse(contentTypeAlias, out Guid contentTypeGuid))
167+
contentTypeAlias = GetContentTypeAliasByGuid(contentTypeGuid);
168+
169+
return (ContentTypeContainer)_appCaches.RuntimeCache.GetCacheItem(
170+
string.Concat("Our.Umbraco.DocTypeGridEditor.Helpers.DocTypeGridEditorHelper.GetContentTypesByAlias_", contentTypeAlias),
171+
() => new ContentTypeContainer
172+
{
173+
PublishedContentType = new PublishedContentType(_contentTypeService.Get(contentTypeAlias), _publishedContentTypeFactory),
174+
ContentType = _contentTypeService.Get(contentTypeAlias)
175+
});
176+
}
177+
178+
private string GetContentTypeAliasByGuid(Guid contentTypeGuid)
179+
{
180+
return (string)_appCaches.RuntimeCache.GetCacheItem(
181+
string.Concat("Our.Umbraco.DocTypeGridEditor.Helpers.DocTypeGridEditorHelper.GetContentTypeAliasByGuid_", contentTypeGuid),
182+
() => _contentTypeService.GetAllContentTypeAliases(contentTypeGuid).FirstOrDefault());
183+
}
184+
}
185+
186+
public class ContentTypeContainer
187+
{
188+
public PublishedContentType PublishedContentType { get; set; }
189+
190+
public IContentType ContentType { get; set; }
191+
}
192+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
using Umbraco.Cms.Core.Models.PublishedContent;
7+
using Umbraco.Extensions;
8+
9+
namespace Our.Umbraco.DocTypeGridEditor9.Models
10+
{
11+
internal class DetachedPublishedElement : IPublishedElement
12+
{
13+
private readonly IPublishedContentType _contentType;
14+
private readonly IEnumerable<IPublishedProperty> _properties;
15+
private readonly bool _isPreviewing;
16+
private readonly Guid _key;
17+
18+
19+
public DetachedPublishedElement(
20+
Guid key,
21+
IPublishedContentType contentType,
22+
IEnumerable<IPublishedProperty> properties,
23+
bool isPreviewing = false)
24+
{
25+
_key = key;
26+
_contentType = contentType;
27+
_properties = properties;
28+
_isPreviewing = isPreviewing;
29+
}
30+
public IPublishedContentType ContentType => _contentType;
31+
32+
public IPublishedProperty GetProperty(string alias) => _properties.FirstOrDefault(x => x.PropertyType.Alias.InvariantEquals(alias));
33+
34+
public Guid Key => _key;
35+
36+
public IEnumerable<IPublishedProperty> Properties => _properties;
37+
38+
public bool IsDraft => _isPreviewing;
39+
}
40+
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
using Umbraco.Cms.Core.Models.PublishedContent;
7+
using Umbraco.Cms.Core.PropertyEditors;
8+
9+
namespace Our.Umbraco.DocTypeGridEditor9.Models
10+
{
11+
internal class DetachedPublishedProperty : IPublishedProperty
12+
{
13+
private readonly IPublishedPropertyType _propertyType;
14+
private readonly object _rawValue;
15+
private readonly Lazy<object> _sourceValue;
16+
private readonly Lazy<object> _objectValue;
17+
private readonly Lazy<object> _xpathValue;
18+
private readonly bool _isPreview;
19+
20+
public DetachedPublishedProperty(IPublishedPropertyType propertyType, object value)
21+
: this(propertyType, value, false)
22+
{ }
23+
24+
public DetachedPublishedProperty(IPublishedPropertyType propertyType, object value, bool isPreview)
25+
{
26+
_propertyType = propertyType;
27+
_isPreview = isPreview;
28+
29+
_rawValue = value;
30+
31+
_sourceValue = new Lazy<object>(() => _propertyType.ConvertSourceToInter(null, _rawValue, _isPreview));
32+
_objectValue = new Lazy<object>(() => _propertyType.ConvertInterToObject(null, PropertyCacheLevel.None, _sourceValue.Value, _isPreview));
33+
_xpathValue = new Lazy<object>(() => _propertyType.ConvertInterToXPath(null, PropertyCacheLevel.None, _sourceValue.Value, _isPreview));
34+
}
35+
36+
public string PropertyTypeAlias
37+
{
38+
get
39+
{
40+
return _propertyType.DataType.EditorAlias;
41+
}
42+
}
43+
44+
public bool HasValue
45+
{
46+
get { return DataValue != null && DataValue.ToString().Trim().Length > 0; }
47+
}
48+
49+
public object DataValue
50+
{
51+
get { return _rawValue; }
52+
}
53+
54+
public object Value
55+
{
56+
get { return _objectValue.Value; }
57+
}
58+
59+
public object XPathValue
60+
{
61+
get { return _xpathValue.Value; }
62+
}
63+
64+
bool IPublishedProperty.HasValue(string culture, string segment)
65+
{
66+
return HasValue;
67+
}
68+
69+
public object GetSourceValue(string culture = null, string segment = null)
70+
{
71+
return DataValue;
72+
}
73+
74+
public object GetValue(string culture = null, string segment = null)
75+
{
76+
return Value;
77+
}
78+
79+
public object GetXPathValue(string culture = null, string segment = null)
80+
{
81+
return XPathValue;
82+
}
83+
84+
public IPublishedPropertyType PropertyType
85+
{
86+
get
87+
{
88+
return _propertyType;
89+
}
90+
}
91+
public string Alias
92+
{
93+
get
94+
{
95+
return _propertyType.Alias;
96+
}
97+
}
98+
}
99+
}

0 commit comments

Comments
 (0)