Skip to content

Instantly share code, notes, and snippets.

@Migaroez
Last active October 31, 2023 11:45
Show Gist options
  • Save Migaroez/162faab59d4d04515d665e27f50e2735 to your computer and use it in GitHub Desktop.
Save Migaroez/162faab59d4d04515d665e27f50e2735 to your computer and use it in GitHub Desktop.
Umbraco entity generation
//todo: refactor code for future expansion
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Strings;
using Umbraco.Cms.Infrastructure.Persistence;
using Umbraco.Cms.Infrastructure.Persistence.Querying;
using Umbraco.Cms.Web.Common.Controllers;
namespace Umbraco.Cms.Web.UI.Code;
public class ContentGenerateController : UmbracoApiController
{
private readonly IContentTypeService _contentTypeService;
private readonly IContentService _contentService;
private readonly IShortStringHelper _shortStringHelper;
private readonly IDataTypeService _dataTypeService;
private readonly ILocalizationService _localizationService;
private readonly ISqlContext _sqlContext;
public ContentGenerateController(IContentTypeService contentTypeService, IContentService contentService,
IShortStringHelper shortStringHelper, IDataTypeService dataTypeService,
ILocalizationService localizationService, ISqlContext sqlContext)
{
_contentTypeService = contentTypeService;
_contentService = contentService;
_shortStringHelper = shortStringHelper;
_dataTypeService = dataTypeService;
_localizationService = localizationService;
_sqlContext = sqlContext;
}
[Route("api/generate/test")]
public bool Test()
{
return true;
}
public class ContentGenerateRequestModel
{
public int amount { get; set; } = 100;
public string[]? doctypeAliases { get; set; } = null;
public string? containingDoctypeAlias { get; set; } = null;
public bool firstContainingDocumentOnly { get; set; } = true;
public int newDocTypePropertyMinAmount { get; set; } = 1;
public int newDocTypePropertyMaxAmount { get; set; } = 1;
public string[]? languageIsoCodes { get; set; }
public string[]? segments { get; set; }
public bool containtingDoctypeUsesListview { get; set; }
}
[Route("api/generate/content")]
[HttpPost]
public List<string> Index([FromBody] ContentGenerateRequestModel model)
{
var messages = new List<string>();
var languages = GetOrCreateLanguages(model.languageIsoCodes);
var newDocTypesNeedToSupportCultures = languages.Count() > 1;
var newDocTypesNeedToSupportSegments = model.segments?.Length > 1;
var doctypes = GetOrCreateDocTypes(messages, model.doctypeAliases, model.newDocTypePropertyMinAmount,
model.newDocTypePropertyMaxAmount, newDocTypesNeedToSupportCultures, newDocTypesNeedToSupportSegments);
if (doctypes == null)
{
return messages;
}
var containingDocuments = GetOrCreateContainingDocuments(model.containingDoctypeAlias, doctypes,
model.containtingDoctypeUsesListview);
if (containingDocuments == null || model.firstContainingDocumentOnly)
{
CreateDocument(model.amount, doctypes, languages, model.segments, model.firstContainingDocumentOnly ? containingDocuments?.First() : null, messages);
}
else
{
foreach (IContent containingDocument in containingDocuments)
{
CreateDocument(model.amount, doctypes, languages, model.segments, containingDocument, messages);
}
}
return messages;
}
private void CreateDocument(int amount, List<IContentType> doctypes, ICollection<ILanguage> languages, string[]? segments, IContent? containingDocument, List<string> messages)
{
for (int documentCreateIndex = 0; documentCreateIndex < amount; documentCreateIndex++)
{
var doctype = doctypes[(documentCreateIndex + 1) % doctypes.Count];
var properties = new PropertyCollection();
foreach (IPropertyType propertyType in doctype.PropertyTypes.Where(pt =>
pt.PropertyEditorAlias.Equals("Umbraco.TextBox", StringComparison.InvariantCultureIgnoreCase)))
{
var property = new Property(propertyType);
if (doctype.Variations is ContentVariation.CultureAndSegment &&
propertyType.Variations is ContentVariation.CultureAndSegment)
{
foreach (var cultureIsoCode in languages.Select(l => l.IsoCode))
{
foreach (var segment in segments ?? Enumerable.Empty<string>())
{
property.SetValue(Guid.NewGuid() + "_" + cultureIsoCode + "_" + segment, cultureIsoCode,
segment);
}
}
}
else if (doctype.Variations is ContentVariation.CultureAndSegment or ContentVariation.Culture &&
propertyType.Variations is ContentVariation.Culture)
{
foreach (var cultureIsoCode in languages.Select(l => l.IsoCode))
{
property.SetValue(Guid.NewGuid() + "_" + cultureIsoCode, cultureIsoCode);
}
}
else if (doctype.Variations is ContentVariation.CultureAndSegment or ContentVariation.Segment &&
propertyType.Variations is ContentVariation.Segment)
{
foreach (var segment in segments ?? Enumerable.Empty<string>())
{
property.SetValue(Guid.NewGuid() + "_" + segment, null, segment);
}
}
else
{
property.SetValue(Guid.NewGuid().ToString());
}
properties.Add(property);
}
var content = containingDocument != null
? new Content(DateTime.Now.Ticks.ToString(), containingDocument!, doctype,
properties)
: new Content(DateTime.Now.Ticks.ToString(), -1, doctype,
properties);
if (doctype.Variations is ContentVariation.Culture or ContentVariation.CultureAndSegment)
{
foreach (var cultureIsoCode in languages.Select(l => l.IsoCode))
{
content.SetCultureName(content.Name + "_" + cultureIsoCode, cultureIsoCode);
}
}
_contentService.SaveAndPublish(content);
messages.Add("Published content: " + content.Name);
}
}
private ICollection<ILanguage> GetOrCreateLanguages(string[]? modelLanguageIsoCodes)
{
if (modelLanguageIsoCodes?.Any() != true)
{
return new[]
{
_localizationService.GetLanguageByIsoCode(_localizationService.GetDefaultLanguageIsoCode())!
};
}
var languages = _localizationService.GetAllLanguages().Where(l =>
modelLanguageIsoCodes.Any(lic => lic.Equals(l.IsoCode, StringComparison.InvariantCultureIgnoreCase)))
.ToList();
var languagesToCreate = modelLanguageIsoCodes.Where(lic =>
languages.Any(l => l.IsoCode.Equals(lic, StringComparison.InvariantCultureIgnoreCase)) == false).ToArray();
foreach (var languageIsoCode in languagesToCreate)
{
var language = new Language(languageIsoCode, languageIsoCode);
_localizationService.Save(language);
languages.Add(language);
}
return languages;
}
private List<IContentType>? GetOrCreateDocTypes(List<string> messages, string[]? doctypeAliases = null,
int newDocTypePropertyMinAmount = 1, int newDocTypePropertyMaxAmount = 1, bool makeNewPropertiesCultureVariant = false,
bool makeNewPropertiesSegmentVariant = false)
{
if (doctypeAliases?.Any() != true)
{
messages.Add("need at least one existing or new doctypeAlias");
return null;
}
List<IContentType> doctypes = new List<IContentType>();
if (doctypeAliases?.Any() == true)
{
doctypes.AddRange(_contentTypeService.GetAll().Where(ct =>
doctypeAliases.Contains(ct.Alias, StringComparer.InvariantCultureIgnoreCase)));
}
var newDocTypesAliases = doctypeAliases!.Where(dta =>
doctypes.Any(dt => dt.Alias.Equals(dta, StringComparison.InvariantCultureIgnoreCase)) == false).ToList();
var random = new Random();
var textBoxDataType = _dataTypeService.GetByEditorAlias("Umbraco.TextBox").First();
foreach (var newDoctypeAlias in newDocTypesAliases)
{
var doctype = new ContentType(_shortStringHelper, -1);
doctype.Alias = newDoctypeAlias;
doctype.Icon = "icon-add";
doctype.Name = newDoctypeAlias.ToFirstUpper();
doctype.AllowedAsRoot = true;
doctype.Variations = ContentVariation.Nothing;
if (makeNewPropertiesCultureVariant)
{
doctype.Variations = doctype.Variations.SetFlag(ContentVariation.Culture);
}
if (makeNewPropertiesSegmentVariant)
{
doctype.Variations = doctype.Variations.SetFlag(ContentVariation.Segment);
}
var properties = new List<PropertyType>();
var maxPropertyCount = random.Next(newDocTypePropertyMinAmount, newDocTypePropertyMaxAmount + 1);
for (var i = 0; i < maxPropertyCount; i++)
{
properties.Add(
new PropertyType(_shortStringHelper, textBoxDataType, "generatedProperty" + i)
{
Name = "generatedProperty" + i,
Variations = doctype.Variations,
});
}
var propertyTypeCollection = new PropertyTypeCollection(true, properties);
doctype.PropertyGroups = new PropertyGroupCollection()
{
new PropertyGroup(false)
{
Alias = "generated", PropertyTypes = propertyTypeCollection, Name = "generated"
},
};
_contentTypeService.Save(doctype);
messages.Add("Created doctype: " + newDoctypeAlias);
doctypes.Add(doctype);
}
return doctypes;
}
private IEnumerable<IContent>? GetOrCreateContainingDocuments(string? containingDoctypeAlias,
IEnumerable<IContentType> contentTypesThatShouldBeAllowed, bool isContainer)
{
if (containingDoctypeAlias.IsNullOrWhiteSpace())
{
return null;
}
var doctype = _contentTypeService
.GetAll()
.FirstOrDefault(ct => ct.Alias.Equals(containingDoctypeAlias, StringComparison.InvariantCultureIgnoreCase));
if (doctype == null)
{
doctype = new ContentType(_shortStringHelper, -1);
doctype.Alias = containingDoctypeAlias;
doctype.Icon = "icon-folder";
doctype.Name = containingDoctypeAlias.ToFirstUpper();
doctype.IsContainer = isContainer;
}
var allowedContentTypes = new List<ContentTypeSort>();
if (doctype.AllowedContentTypes != null)
{
allowedContentTypes.AddRange(doctype.AllowedContentTypes);
}
// make sure the doctypes are allowed
allowedContentTypes.AddRange(contentTypesThatShouldBeAllowed
.Where(ct => allowedContentTypes.Any(act => act.Alias == ct.Alias) == false)
.Select(ct => new ContentTypeSort(ct.Id, 0)));
doctype.AllowedContentTypes = allowedContentTypes;
// make sure it can be created at root so we don't need to go look for it
doctype.AllowedAsRoot = true;
_contentTypeService.Save(doctype);
var containingDocuments = _contentService.GetPagedOfType(doctype.Id,0,1000, out var _,new Query<IContent>(_sqlContext))
.Where(doc => doc.ContentType.Alias == containingDoctypeAlias).ToList();
if (containingDocuments.Any())
{
return containingDocuments;
}
var newContainingDocument = new Content("Generate Container " + DateTime.Now.Ticks, -1, doctype);
_contentService.SaveAndPublish(newContainingDocument);
containingDocuments.Add(newContainingDocument);
return containingDocuments;
}
}
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Web.Common.Controllers;
namespace Umbraco.Cms.Web.UI.Generate;
public class GenerateMembersController : UmbracoApiController
{
private readonly IMemberService _memberService;
private readonly IMemberManager _memberManager;
private readonly IPasswordHasher _passwordHasher;
public GenerateMembersController(IMemberService memberService, IMemberManager memberManager, IPasswordHasher passwordHasher)
{
_memberService = memberService;
_memberManager = memberManager;
_passwordHasher = passwordHasher;
}
[Route("api/generate/members")]
public List<string> Index(int amount = 100, string emailPattern = "test[]@test.test", string namePattern = "test[]", string passwordPattern = "test[]@test.test", string memberTypeAlias = "Member")
{
var messages = new List<string>();
for (int i = 0; i < amount; i++)
{
var email = emailPattern.Replace("[]", i.ToString());
var password = passwordPattern.Replace("[]", i.ToString());
var name = namePattern.Replace("[]", i.ToString());
var member = _memberService.CreateMember(email, email, name, memberTypeAlias);
member.RawPasswordValue = _passwordHasher.HashPassword(password);
_memberService.Save(member);
messages.Add($"Created user {email} with password {password}");
}
return messages;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment