// 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();
 }
Example #2
0
        /// <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();
        }
Example #3
0
        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);
                }
            }
        }
Example #4
0
        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);
            }
        }