// internal so it can be used by PublishedNoCache which does _not_ want to cache anything and so will never // use the static cache getter PublishedContentType.GetPublishedContentType(alias) below - anything else // should use it. internal PublishedContentType(IContentTypeComposition contentType) { Id = contentType.Id; Alias = contentType.Alias; _compositionAliases = new HashSet <string>(contentType.CompositionAliases(), StringComparer.InvariantCultureIgnoreCase); _propertyTypes = contentType.CompositionPropertyTypes .Select(x => new PublishedPropertyType(this, x)) .ToArray(); InitializeIndexes(); }
/// <summary> /// Initializes a new instance of the <see cref="PublishedContentType"/> class with a content type. /// </summary> public PublishedContentType(IContentTypeComposition contentType, IPublishedContentTypeFactory factory) : this(contentType.Id, contentType.Alias, contentType.GetItemType(), contentType.CompositionAliases(), contentType.Variations, contentType.IsElement) { var propertyTypes = contentType.CompositionPropertyTypes .Select(x => factory.CreatePropertyType(this, x)) .ToList(); if (ItemType == PublishedItemType.Member) { EnsureMemberProperties(propertyTypes, factory); } _propertyTypes = propertyTypes.ToArray(); InitializeIndexes(); }
private static void MapComposition(ContentTypeSave source, IContentTypeComposition target, Func <string, IContentTypeComposition> getContentType) { var current = target.CompositionAliases().ToArray(); var proposed = source.CompositeContentTypes; var remove = current.Where(x => !proposed.Contains(x)); var add = proposed.Where(x => !current.Contains(x)); foreach (var alias in remove) { target.RemoveContentType(alias); } foreach (var alias in add) { // TODO: Remove N+1 lookup var contentType = getContentType(alias); if (contentType != null) { target.AddContentType(contentType); } } }
private void ValidateLocked(IContentTypeComposition compositionContentType) { // performs business-level validation of the composition // should ensure that it is absolutely safe to save the composition // eg maybe a property has been added, with an alias that's OK (no conflict with ancestors) // but that cannot be used (conflict with descendants) var contentType = compositionContentType as IContentType; var mediaType = compositionContentType as IMediaType; IContentTypeComposition[] allContentTypes; if (contentType != null) { allContentTypes = GetAllContentTypes().Cast <IContentTypeComposition>().ToArray(); } else if (mediaType != null) { allContentTypes = GetAllMediaTypes().Cast <IContentTypeComposition>().ToArray(); } else { throw new Exception("Composition is neither IContentType nor IMediaType?"); } var compositionAliases = compositionContentType.CompositionAliases(); var compositions = allContentTypes.Where(x => compositionAliases.Any(y => x.Alias.Equals(y))); var propertyTypeAliases = compositionContentType.PropertyTypes.Select(x => x.Alias.ToLowerInvariant()).ToArray(); var indirectReferences = allContentTypes.Where(x => x.ContentTypeComposition.Any(y => y.Id == compositionContentType.Id)); var comparer = new DelegateEqualityComparer <IContentTypeComposition>((x, y) => x.Id == y.Id, x => x.Id); var dependencies = new HashSet <IContentTypeComposition>(compositions, comparer); var stack = new Stack <IContentTypeComposition>(); indirectReferences.ForEach(stack.Push);//Push indirect references to a stack, so we can add recursively while (stack.Count > 0) { var indirectReference = stack.Pop(); dependencies.Add(indirectReference); //Get all compositions for the current indirect reference var directReferences = indirectReference.ContentTypeComposition; foreach (var directReference in directReferences) { if (directReference.Id == compositionContentType.Id || directReference.Alias.Equals(compositionContentType.Alias)) { continue; } dependencies.Add(directReference); //A direct reference has compositions of its own - these also need to be taken into account var directReferenceGraph = directReference.CompositionAliases(); allContentTypes.Where(x => directReferenceGraph.Any(y => x.Alias.Equals(y, StringComparison.InvariantCultureIgnoreCase))).ForEach(c => dependencies.Add(c)); } //Recursive lookup of indirect references allContentTypes.Where(x => x.ContentTypeComposition.Any(y => y.Id == indirectReference.Id)).ForEach(stack.Push); } foreach (var dependency in dependencies) { if (dependency.Id == compositionContentType.Id) { continue; } var contentTypeDependency = allContentTypes.FirstOrDefault(x => x.Alias.Equals(dependency.Alias, StringComparison.InvariantCultureIgnoreCase)); if (contentTypeDependency == null) { continue; } var intersect = contentTypeDependency.PropertyTypes.Select(x => x.Alias.ToLowerInvariant()).Intersect(propertyTypeAliases).ToArray(); if (intersect.Length == 0) { continue; } var message = string.Format("The following PropertyType aliases from the current ContentType conflict with existing PropertyType aliases: {0}.", string.Join(", ", intersect)); throw new Exception(message); } }