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

Added ValueProcessors and solved #173 #174

Merged
merged 4 commits into from
Feb 5, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions docs/developers-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,47 @@ By inheriting from the `DocTypeGridEditorSurfaceController` base class, you'll a

---

### Value Processors
Since Doc Type Grid Editor stores the data for each property as a JSON-blob, we're not processing the values in the same way as Umbraco-core before storing it. This also means that the values that comes back and are passed into a Property Value Converter might be in of a type/format that that Property Value Convert can't handle.

We've added something that we call "ValueProcessors" and these can be used to modify the raw property value before we send it to the property value converter. One example of where this is needed is the Tags-editor.

If you need to perform some processing of a value before it's sent to the property value converter you can add your own ValueProcessor.

```csharp
public class UmbracoColorPickerValueProcessor : IDocTypeGridEditorValueProcessor
{
public bool IsProcessorFor(string propertyEditorAlias)
=> propertyEditorAlias.Equals(Constants.PropertyEditors.Aliases.ColorPicker);

public object ProcessValue(object value)
{
// Do something with the value
return value;
}
}
```

Then register this during composition withing IUserComposer,
```csharp
public class MyCustomDocTypeGridEditorComposer : IUserComposer
{
public void Compose(Composition composition)
{
composition.DocTypeGridEditorValueProcessors()
.Append<UmbracoColorPickerValueProcessor>();
}
}
```

Dot Type Grid editor ships with a ValueProcessor for the Umbraco-Tags property.

**Note:** When using a Tag-editor inside a DTGE this would not create any relationship between the current node and that tag, if you need to tag a node you should use the Tags-editor as a property directly on the document type.





### Useful Links

* [Source Code](https://github.com/skttl/umbraco-doc-type-grid-editor)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using Our.Umbraco.DocTypeGridEditor.Extensions;
using Our.Umbraco.DocTypeGridEditor.ValueProcessing;
using Umbraco.Core.Composing;

namespace Our.Umbraco.DocTypeGridEditor.Composing
{
/// <summary>
/// Composes defaults for Doc Type Grid Editor
/// </summary>
public class DocTypeGridEditorComposer : IUserComposer
{
public void Compose(Composition composition)
{
composition.DocTypeGridEditorValueProcessors().Append<UmbracoTagsValueProcessor>();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using Our.Umbraco.DocTypeGridEditor.ValueProcessing.Collections;
using Umbraco.Core.Composing;

namespace Our.Umbraco.DocTypeGridEditor.Extensions
{
public static class CompositionExtensions
{
/// <summary>
/// Used to modify the collection of Value Processors for Doc Type Grid Editor
/// </summary>
/// <param name="composition"></param>
/// <returns></returns>
public static DocTypeGridEditorValueProcessorsCollectionBuilder DocTypeGridEditorValueProcessors(this Composition composition)
=> composition.WithCollectionBuilder<DocTypeGridEditorValueProcessorsCollectionBuilder>();
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Our.Umbraco.DocTypeGridEditor.Extensions;
using Our.Umbraco.DocTypeGridEditor.Models;
using Our.Umbraco.DocTypeGridEditor.ValueProcessing;
using Our.Umbraco.DocTypeGridEditor.ValueProcessing.Collections;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Web.Composing;
Expand Down Expand Up @@ -64,6 +67,14 @@ private static IPublishedElement ConvertValue(string id, string contentTypeAlias

var newValue = propEditor.GetValueEditor().FromEditor(contentPropData, jProp.Value);

// Performing "ValueProcessing" if any ValueProcessor is configured for this Property Editor-alias.
var processorsCollection = Current.Factory.GetInstance<DocTypeGridEditorValueProcessorsCollection>();
var processor = processorsCollection.FirstOrDefault(x => x.IsProcessorFor(propEditor.Alias));
if (processor != null)
{
newValue = processor.ProcessValue(newValue);
}

/* Now that we have the DB stored value, we actually need to then convert it into its
* XML serialized state as expected by the published property by calling ConvertDbToString
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,12 @@
<Compile Include="Models\UnpublishedProperty.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Properties\VersionInfo.cs" />
<Compile Include="Composing\DocTypeGridEditorComposer.cs" />
<Compile Include="Extensions\CompositionExtensions.cs" />
<Compile Include="ValueProcessing\Collections\DocTypeGridEditorValueProcessorsCollection.cs" />
<Compile Include="ValueProcessing\Collections\DocTypeGridEditorValueProcessorsCollectionBuilder.cs" />
<Compile Include="ValueProcessing\IDocTypeGridEditorValueProcessor.cs" />
<Compile Include="ValueProcessing\UmbracoTagsValueProcessor.cs" />
<Compile Include="Web\Controllers\DocTypeGridEditorApiController.cs" />
<Compile Include="Extensions\ContentTypeServiceExtensions.cs" />
<Compile Include="Web\Controllers\DocTypeGridEditorSurfaceController.cs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System.Collections.Generic;
using Umbraco.Core.Composing;

namespace Our.Umbraco.DocTypeGridEditor.ValueProcessing.Collections
{
/// <summary>
/// Collection to hold references to Value Processors to be used with Doc Type Grid Editor. <see cref="IDocTypeGridEditorValueProcessor"/>
/// </summary>
public class DocTypeGridEditorValueProcessorsCollection : BuilderCollectionBase<IDocTypeGridEditorValueProcessor>
{
public DocTypeGridEditorValueProcessorsCollection(IEnumerable<IDocTypeGridEditorValueProcessor> items) : base(items)
{ }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using Umbraco.Core.Composing;

namespace Our.Umbraco.DocTypeGridEditor.ValueProcessing.Collections
{
/// <summary>
/// Collection builder for Value Processors <see cref="IDocTypeGridEditorValueProcessor"/>
/// </summary>
public class DocTypeGridEditorValueProcessorsCollectionBuilder : OrderedCollectionBuilderBase<DocTypeGridEditorValueProcessorsCollectionBuilder, DocTypeGridEditorValueProcessorsCollection, IDocTypeGridEditorValueProcessor>
{
protected override DocTypeGridEditorValueProcessorsCollectionBuilder This => this;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
namespace Our.Umbraco.DocTypeGridEditor.ValueProcessing
{
/// <summary>
/// Abstracts a ValueProcessor that is used to modify a property value before it's sent to a Property Value Converter
/// These are useful when the data format stored for DTGE is different from what the PVC expects ie. like Umbraco.Tags
/// </summary>
public interface IDocTypeGridEditorValueProcessor
{
/// <summary>
/// Returns if this processor can handle a certain property editor based on the property editors alias.
/// </summary>
/// <param name="propertyEditorAlias">Contains the alias of the property editor ie. "Umbraco.Tags" or "Umbraco.Picker".</param>
/// <returns></returns>
bool IsProcessorFor(string propertyEditorAlias);

/// <summary>
/// Processes the value to de desired format/type. Most of the time this is to make sure that the object passed to the property value converters is
/// of the correct type and in the correct format for the property value converter to handle.
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
object ProcessValue(object value);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using Newtonsoft.Json;
using Umbraco.Core;

namespace Our.Umbraco.DocTypeGridEditor.ValueProcessing
{
/// <summary>
/// Processes the value stored in DTGE to match the string-json-format that the Property Value Converter expects.
/// </summary>
/// <remarks>
/// When we're setting a value on a Umbraco.Core.Models.Property it will be converted into the type that this Property expects.
/// In the case with Tags, there will be a .ToString() that converts the object passed into a string, something like System.Linq.Enumerable+WhereSelectEnumerableIterator`2[Newtonsoft.Json.Linq.JToken,System.String]
/// This value would be passed to the Property Value Converter which would blow up. The processing below will safely convert the value to a valid json-string before it's passed
/// to the Property Value Converter.
/// </remarks>
public class UmbracoTagsValueProcessor : IDocTypeGridEditorValueProcessor
{
public bool IsProcessorFor(string propertyEditorAlias) => propertyEditorAlias.Equals(Constants.PropertyEditors.Aliases.Tags);

public object ProcessValue(object value)
{
if (value == null)
{
// When the value is null, we need to fake an empty array since this is
// how Umbraco would store an empty "Umbraco.Tags"-property.
return "[]";
}

// Returns a string-version of the JArray that DTGE would pass.
return JsonConvert.SerializeObject(value);
}
}
}