Beispiel #1
0
        /// <summary>
        /// This constructor is for tests and is not intended to be used directly from application code.
        /// </summary>
        /// <remarks>
        /// <para>Values are assumed to be consistent and are not checked.</para>
        /// </remarks>
        public PublishedContentType(int id, string alias, PublishedItemType itemType, IEnumerable <string> compositionAliases, Func <IPublishedContentType, IEnumerable <IPublishedPropertyType> > propertyTypes, ContentVariation variations, bool isElement = false)
            : this(id, alias, itemType, compositionAliases, variations, isElement)
        {
            _propertyTypes = propertyTypes(this).ToArray();

            InitializeIndexes();
        }
Beispiel #2
0
        public static IEnumerable <IGraphType> CreateGraphTypes(
            IEnumerable <IContentTypeComposition> contentTypes,
            PublishedItemType publishedItemType)
        {
            var interfaceGraphTypes = new Dictionary <string, IInterfaceGraphType>();

            //TODO: Whitelist/blacklist content types

            var contentTypeList = contentTypes.ToList();
            var compositions    = contentTypeList.SelectMany(x => x.ContentTypeComposition).Distinct().ToList();

            foreach (var contentType in compositions)
            {
                var graphType = new PublishedContentCompositionGraphType(contentType, publishedItemType);
                yield return(graphType);

                interfaceGraphTypes.Add(contentType.Alias, graphType);
            }

            foreach (var contentType in contentTypeList.Except(compositions))
            {
                var graphType = new PublishedContentGraphType(contentType, publishedItemType, interfaceGraphTypes);
                yield return(graphType);
            }
        }
        public PublishedContentGraphType(IContentTypeComposition contentType, PublishedItemType itemType, IDictionary <string, IInterfaceGraphType> interfaceGraphTypes)
        {
            Name        = contentType.Alias.ToPascalCase();
            Description = contentType.Description;
            IsTypeOf    = content => ((IPublishedContent)content).ContentType.Alias == contentType.Alias;
            Metadata    = new Dictionary <string, object>
            {
                [Constants.Metadata.ContentTypeAlias] = contentType.Alias,
                [Constants.Metadata.AllowedAtRoot]    = contentType.AllowedAsRoot,
                [Constants.Metadata.AllowedChildren]  = contentType.AllowedContentTypes.Select(x => x.Alias).ToArray(),
            };

            Interface <PublishedContentInterfaceGraphType>();

            foreach (IContentTypeComposition composition in contentType.ContentTypeComposition)
            {
                if (interfaceGraphTypes.TryGetValue(composition.Alias, out IInterfaceGraphType interfaceType))
                {
                    AddResolvedInterface(interfaceType);
                }
            }

            this.AddUmbracoBuiltInProperties();
            this.AddUmbracoContentPropeties(contentType, itemType);
        }
Beispiel #4
0
 internal static string GetNodeTypeIcon(PublishedItemType nodeType)
 {
     return(nodeType == PublishedItemType.Content ? "icon-umb-content"
     : nodeType == PublishedItemType.Media ? "icon-umb-media"
     : nodeType == PublishedItemType.Member ? "icon-umb-members"
     : null);
 }
Beispiel #5
0
        /// <summary>
        /// Gets a published content type.
        /// </summary>
        /// <param name="itemType">An item type.</param>
        /// <param name="id">An identifier.</param>
        /// <returns>The published content type corresponding to the item type and identifier.</returns>
        public PublishedContentType Get(PublishedItemType itemType, int id)
        {
            try
            {
                _lock.EnterUpgradeableReadLock();

                if (_typesById.TryGetValue(id, out var type))
                {
                    return(type);
                }

                type = CreatePublishedContentType(itemType, id);

                try
                {
                    _lock.EnterWriteLock();

                    return(_typesByAlias[GetAliasKey(type)] = _typesById[type.Id] = type);
                }
                finally
                {
                    if (_lock.IsWriteLockHeld)
                    {
                        _lock.ExitWriteLock();
                    }
                }
            }
            finally
            {
                if (_lock.IsUpgradeableReadLockHeld)
                {
                    _lock.ExitUpgradeableReadLock();
                }
            }
        }
Beispiel #6
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="searcherName"></param>
        /// <param name="nodeType"></param>
        /// <param name="sort"></param>
        /// <param name="skip"></param>
        /// <param name="take"></param>
        /// <returns></returns>
        internal static MatchesResult GetDetachedMatches(string searcherName, PublishedItemType nodeType, string filter, string sort, int skip, int take)
        {
            var matchesResult = new MatchesResult();

            var lookQuery = new LookQuery(searcherName)
            {
                NodeQuery = new NodeQuery()
                {
                    Type          = nodeType,
                    Alias         = !string.IsNullOrWhiteSpace(filter) ? filter : null,
                    DetachedQuery = DetachedQuery.OnlyDetached
                }
            };

            QueryService.SetSort(lookQuery, sort);

            var lookResult = lookQuery.Search();

            matchesResult.TotalItemCount = lookResult.TotalItemCount;
            matchesResult.Matches        = lookResult
                                           .Matches
                                           .Skip(skip)
                                           .Take(take)
                                           .Select(x => (MatchesResult.Match)x)
                                           .ToArray();

            return(matchesResult);
        }
Beispiel #7
0
        private PublishedContentType CreatePublishedContentType(PublishedItemType itemType, int id)
        {
            if (GetPublishedContentTypeById != null)
            {
                return(GetPublishedContentTypeById(id));
            }

            IContentTypeComposition contentType;

            switch (itemType)
            {
            case PublishedItemType.Content:
                contentType = _contentTypeService.Get(id);
                break;

            case PublishedItemType.Media:
                contentType = _mediaTypeService.Get(id);
                break;

            case PublishedItemType.Member:
                contentType = _memberTypeService.Get(id);
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(itemType));
            }

            if (contentType == null)
            {
                throw new Exception($"ContentTypeService failed to find a {itemType.ToString().ToLower()} type with id {id}.");
            }

            return(_publishedContentTypeFactory.CreateContentType(contentType));
        }
Beispiel #8
0
        private IReadOnlyCollection <IPublishedContentType> CreateContentTypes(PublishedItemType itemType, int[] ids)
        {
            // XxxTypeService.GetAll(empty) returns everything!
            if (ids.Length == 0)
            {
                return(Array.Empty <IPublishedContentType>());
            }

            IEnumerable <IContentTypeComposition> contentTypes;

            switch (itemType)
            {
            case PublishedItemType.Content:
                contentTypes = _serviceContext.ContentTypeService.GetAll(ids);
                break;

            case PublishedItemType.Media:
                contentTypes = _serviceContext.MediaTypeService.GetAll(ids);
                break;

            case PublishedItemType.Member:
                contentTypes = _serviceContext.MemberTypeService.GetAll(ids);
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(itemType));
            }

            // some may be missing - not checking here
            return(contentTypes.Select(x => _publishedContentTypeFactory.CreateContentType(x)).ToList());
        }
Beispiel #9
0
        /// <summary>
        /// Gets a published content type.
        /// </summary>
        /// <param name="itemType">An item type.</param>
        /// <param name="key">An key.</param>
        /// <returns>The published content type corresponding to the item key.</returns>
        public IPublishedContentType Get(PublishedItemType itemType, Guid key)
        {
            try
            {
                _lock.EnterUpgradeableReadLock();

                if (_keyToIdMap.TryGetValue(key, out var id))
                {
                    return(Get(itemType, id));
                }

                var type = CreatePublishedContentType(itemType, key);

                try
                {
                    _lock.EnterWriteLock();
                    _keyToIdMap[key] = type.Id;
                    return(_typesByAlias[GetAliasKey(type)] = _typesById[type.Id] = type);
                }
                finally
                {
                    if (_lock.IsWriteLockHeld)
                    {
                        _lock.ExitWriteLock();
                    }
                }
            }
            finally
            {
                if (_lock.IsUpgradeableReadLockHeld)
                {
                    _lock.ExitUpgradeableReadLock();
                }
            }
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="searcherName"></param>
        /// <param name="sort"></param>
        /// <param name="skip"></param>
        /// <param name="take"></param>
        /// <returns></returns>
        internal static MatchesResult GetNodeTypeMatches(string searcherName, PublishedItemType nodeType, string sort, int skip, int take)
        {
            var matchesResult = new MatchesResult();

            var lookQuery = new LookQuery(searcherName);

            lookQuery.NodeQuery = new NodeQuery()
            {
                Type = nodeType
            };

            QueryService.SetSort(lookQuery, sort);

            var lookResult = lookQuery.Search();

            matchesResult.TotalItemCount = lookResult.TotalItemCount;
            matchesResult.Matches        = lookResult
                                           .Matches
                                           .Skip(skip)
                                           .Take(take)
                                           .Select(x => (MatchesResult.Match)x)
                                           .ToArray();

            return(matchesResult);
        }
        private static PublishedContentType CreatePublishedContentType(PublishedItemType itemType, string alias)
        {
            if (GetPublishedContentTypeCallback != null)
            {
                return(GetPublishedContentTypeCallback(alias));
            }

            IContentTypeComposition contentType;

            switch (itemType)
            {
            case PublishedItemType.Content:
                contentType = ApplicationContext.Current.Services.ContentTypeService.GetContentType(alias);
                break;

            case PublishedItemType.Media:
                contentType = ApplicationContext.Current.Services.ContentTypeService.GetMediaType(alias);
                break;

            case PublishedItemType.Member:
                contentType = ApplicationContext.Current.Services.MemberTypeService.Get(alias);
                break;

            default:
                throw new ArgumentOutOfRangeException("itemType");
            }

            if (contentType == null)
            {
                throw new InvalidOperationException(string.Format("ContentTypeService failed to find a {0} type with alias \"{1}\".",
                                                                  itemType.ToString().ToLower(), alias));
            }

            return(new PublishedContentType(contentType));
        }
        public PublishedContentGraphType(IContentTypeComposition contentType, PublishedItemType itemType, IDictionary <string, IInterfaceGraphType> interfaceGraphTypes)
        {
            Name        = contentType.Alias.ToPascalCase();
            Description = contentType.Description;
            IsTypeOf    = content => ((IPublishedContent)content).ContentType.Alias == contentType.Alias;
            Metadata    = new Dictionary <string, object>
            {
                [Constants.Metadata.ContentTypeAlias] = contentType.Alias,
                [Constants.Metadata.AllowedAtRoot]    = contentType.AllowedAsRoot,
                [Constants.Metadata.AllowedChildren]  = contentType.AllowedContentTypes.Select(x => x.Alias).ToArray(),
            };

            Interface <PublishedContentInterfaceGraphType>();

            foreach (IContentTypeComposition composition in contentType.ContentTypeComposition)
            {
                if (interfaceGraphTypes.TryGetValue(composition.Alias, out IInterfaceGraphType interfaceType))
                {
                    AddResolvedInterface(interfaceType);
                }
            }

            // TODO: set this field name as a reserved property alias
            Field <NonNullGraphType <PublishedContentDataGraphType> >()
            .Name("_contentData")
            .Description("Built in published content data.")
            .Resolve(context => context.Source)
            .SetDoctypeMetadata(GetMetadata <string>(Constants.Metadata.ContentTypeAlias));

            this.AddUmbracoContentPropeties(contentType, itemType);
        }
Beispiel #13
0
        public IHttpActionResult GetDetachedFilters(
            [FromUri] string searcherName,
            [FromUri] PublishedItemType nodeType)
        {
            var searcher = (BaseSearchProvider)this.RequestContext.RouteData.Values["searcher"];

            return(this.Ok(QueryService.GetDetachedFilters(searcherName, nodeType)));
        }
 private PublishedContentType(int id, string alias, PublishedItemType itemType, IEnumerable <string> compositionAliases, ContentVariation variations)
 {
     Id                 = id;
     Alias              = alias;
     ItemType           = itemType;
     CompositionAliases = new HashSet <string>(compositionAliases, StringComparer.InvariantCultureIgnoreCase);
     Variations         = variations;
 }
Beispiel #15
0
 public IHttpActionResult GetNodeTypeMatches(
     [FromUri] string searcherName,
     [FromUri] PublishedItemType nodeType,
     [FromUri] string sort,
     [FromUri] int skip,
     [FromUri] int take)
 {
     return(this.Ok(QueryService.GetNodeTypeMatches(searcherName, nodeType, sort, skip, take)));
 }
 private PublishedContentType(Guid key, int id, string alias, PublishedItemType itemType, IEnumerable <string> compositionAliases, ContentVariation variations, bool isElement)
 {
     Key                = key;
     Id                 = id;
     Alias              = alias;
     ItemType           = itemType;
     CompositionAliases = new HashSet <string>(compositionAliases, StringComparer.InvariantCultureIgnoreCase);
     Variations         = variations;
     IsElement          = isElement;
 }
        public static PublishedContentType Get(PublishedItemType itemType, string alias)
        {
            var key = string.Format("PublishedContentType_{0}_{1}",
                                    itemType.ToString().ToLowerInvariant(), alias.ToLowerInvariant());

            var type = ApplicationContext.Current.ApplicationCache.StaticCache.GetCacheItem <PublishedContentType>(key,
                                                                                                                   () => CreatePublishedContentType(itemType, alias));

            return(type);
        }
        internal NodeTypeTreeNode(FormDataCollection queryStrings) : base("nodeType-" + queryStrings["searcherName"] + "|" + queryStrings["nodeType"], queryStrings)
        {
            this.SearcherName = queryStrings["searcherName"];
            this.NodeType     = (PublishedItemType)Enum.Parse(typeof(PublishedItemType), queryStrings["nodeType"], true);

            this.Icon = IconService.GetNodeTypeIcon(this.NodeType);

            this.Name = this.NodeType == PublishedItemType.Content ? "Content"
                        : this.NodeType == PublishedItemType.Media ? "Media"
                        : this.NodeType == PublishedItemType.Member ? "Members"
                        : null;
        }
Beispiel #19
0
        /// <summary>
        /// This constructor is for tests and is not intended to be used directly from application code.
        /// </summary>
        /// <remarks>
        /// <para>Values are assumed to be consistent and are not checked.</para>
        /// </remarks>
        public PublishedContentType(int id, string alias, PublishedItemType itemType, IEnumerable <string> compositionAliases, IEnumerable <PublishedPropertyType> propertyTypes, ContentVariation variations, bool isElement = false)
            : this(id, alias, itemType, compositionAliases, variations, isElement)
        {
            var propertyTypesA = propertyTypes.ToArray();

            foreach (var propertyType in propertyTypesA)
            {
                propertyType.ContentType = this;
            }
            _propertyTypes = propertyTypesA;

            InitializeIndexes();
        }
Beispiel #20
0
        private IPublishedContentType CreatePublishedContentType(PublishedItemType itemType, Guid key)
        {
            IContentTypeComposition contentType = itemType switch
            {
                PublishedItemType.Content => _contentTypeService.Get(key),
                PublishedItemType.Media => _mediaTypeService.Get(key),
                PublishedItemType.Member => _memberTypeService.Get(key),
                _ => throw new ArgumentOutOfRangeException(nameof(itemType)),
            };

            if (contentType == null)
            {
                throw new Exception($"ContentTypeService failed to find a {itemType.ToString().ToLower()} type with key \"{key}\".");
            }

            return(_publishedContentTypeFactory.CreateContentType(contentType));
        }
Beispiel #21
0
        public static ComplexGraphType <IPublishedContent> AddUmbracoContentPropeties(
            this ComplexGraphType <IPublishedContent> graphType,
            IContentTypeComposition contentType,
            PublishedItemType publishedItemType)
        {
            var publishedContentType = PublishedContentType.Get(publishedItemType, contentType.Alias);

            foreach (var property in contentType.CompositionPropertyTypes)
            {
                //TODO: black/whitelist properties
                if (property.PropertyEditorAlias == Constants.PropertyEditors.ListViewAlias ||
                    property.PropertyEditorAlias == Constants.PropertyEditors.FolderBrowserAlias ||
                    property.Alias.StartsWith("umbracoMember"))
                {
                    continue;
                }

                var publishedPropertyType = publishedContentType.GetPropertyType(property.Alias);

                var resolver = GraphQLValueResolversResolver.Current.FindResolver(publishedPropertyType)
                               ?? new DefaultValueResolver();

                var propertyGraphType = resolver.GetGraphQLType(publishedPropertyType);

                if (property.Mandatory)
                {
                    propertyGraphType = typeof(NonNullGraphType <>).MakeGenericType(propertyGraphType);
                }

                graphType.Field(
                    propertyGraphType,
                    property.Alias.ToCamelCase(),
                    property.Description,
                    resolve: context =>
                {
                    var publishedProperty = context.Source.GetProperty(property.Alias);
                    return(publishedProperty == null
                            ? null
                            : resolver.Resolve(publishedPropertyType, publishedProperty.Value));
                }
                    ).SetPermissions(graphType);
            }

            return(graphType);
        }
        // looks safer but probably useless... ppl should not call these methods directly
        // and if they do... they have to take care about not doing stupid things

        //public static PublishedPropertyType GetModelPropertyType2<T>(Expression<Func<T, object>> selector)
        //    where T : PublishedContentModel
        //{
        //    var type = typeof (T);
        //    var s1 = type.GetField("ModelTypeAlias", BindingFlags.Public | BindingFlags.Static);
        //    var alias = (s1.IsLiteral && s1.IsInitOnly && s1.FieldType == typeof(string)) ? (string)s1.GetValue(null) : null;
        //    var s2 = type.GetField("ModelItemType", BindingFlags.Public | BindingFlags.Static);
        //    var itemType = (s2.IsLiteral && s2.IsInitOnly && s2.FieldType == typeof(PublishedItemType)) ? (PublishedItemType)s2.GetValue(null) : 0;

        //    var contentType = PublishedContentType.Get(itemType, alias);
        //    // etc...
        //}

        public static PublishedContentType GetModelContentType(PublishedItemType itemType, string alias)
        {
            var facade = Current.UmbracoContext.PublishedSnapshot; // fixme inject!

            switch (itemType)
            {
            case PublishedItemType.Content:
                return(facade.Content.GetContentType(alias));

            case PublishedItemType.Media:
                return(facade.Media.GetContentType(alias));

            case PublishedItemType.Member:
                return(facade.Members.GetContentType(alias));

            default:
                throw new ArgumentOutOfRangeException(nameof(itemType));
            }
        }
        private static PublishedContentType CreatePublishedContentType(PublishedItemType itemType, string alias)
        {
            if (GetPublishedContentTypeCallback != null)
            {
                return(GetPublishedContentTypeCallback(alias));
            }

            var contentType = itemType == PublishedItemType.Content
                ? (IContentTypeComposition)ApplicationContext.Current.Services.ContentTypeService.GetContentType(alias)
                : (IContentTypeComposition)ApplicationContext.Current.Services.ContentTypeService.GetMediaType(alias);

            if (contentType == null)
            {
                throw new Exception(string.Format("ContentTypeService failed to find a {0} type with alias \"{1}\".",
                                                  itemType.ToString().ToLower(), alias));
            }

            return(new PublishedContentType(contentType));
        }
Beispiel #24
0
        internal static FiltersResult GetDetachedFilters(string searcherName, PublishedItemType nodeType)
        {
            var filtersResult = new FiltersResult();

            filtersResult.Aliases = new LookQuery(searcherName)
            {
                NodeQuery = new NodeQuery()
                {
                    Type = nodeType, DetachedQuery = DetachedQuery.OnlyDetached
                }
            }
            .Search()
            .Matches
            .Select(x => x.Alias)
            .Distinct()
            .OrderBy(x => x)
            .ToArray();

            return(filtersResult);
        }
Beispiel #25
0
        /// <summary>
        /// gets the icon associated with the docType, mediaType or memberType (by alias)
        /// </summary>
        /// <param name="nodeType">whether it's a node, media or member</param>
        /// <param name="isDetached">flag indicating the item is detached (so will always be a document type_</param>
        /// <param name="alias">alias of the node, media or member type</param>
        /// <returns></returns>
        internal static string GetAliasIcon(PublishedItemType nodeType, bool isDetached, string alias)
        {
            string icon = null;

            try
            {
                if (nodeType == PublishedItemType.Content || isDetached)
                {
                    var contentType = ApplicationContext.Current.Services.ContentTypeService.GetContentType(alias);

                    icon = contentType.Icon;
                }
                else
                {
                    switch (nodeType)
                    {
                    case PublishedItemType.Media:

                        var mediaType = ApplicationContext.Current.Services.ContentTypeService.GetMediaType(alias);

                        icon = mediaType.Icon;

                        break;

                    case PublishedItemType.Member:

                        var memberType = ApplicationContext.Current.Services.MemberTypeService.Get(alias);

                        icon = memberType.Icon;

                        break;
                    }
                }
            }
            catch
            {
                icon = "icon-alert-alt";
            }

            return(icon);
        }
Beispiel #26
0
        private IPublishedContentType CreatePublishedContentType(PublishedItemType itemType, int id)
        {
            if (GetPublishedContentTypeById != null)
            {
                return(GetPublishedContentTypeById(id));
            }
            IContentTypeComposition contentType = itemType switch
            {
                PublishedItemType.Content => _contentTypeService.Get(id),
                PublishedItemType.Media => _mediaTypeService.Get(id),
                PublishedItemType.Member => _memberTypeService.Get(id),
                _ => throw new ArgumentOutOfRangeException(nameof(itemType)),
            };

            if (contentType == null)
            {
                throw new Exception($"ContentTypeService failed to find a {itemType.ToString().ToLower()} type with id {id}.");
            }

            return(_publishedContentTypeFactory.CreateContentType(contentType));
        }
        private static PublishedContentType GetPublishedContentType(PublishedItemType type, string alias)
        {
            var dataType = new DataType(new VoidEditor(Mock.Of <ILogger>()))
            {
                Id = 1
            };

            var dataTypeService = Mock.Of <IDataTypeService>();

            Mock.Get(dataTypeService)
            .Setup(x => x.GetDataType(It.IsAny <int>()))
            .Returns <int>(id => id == 1 ? dataType : null);
            Mock.Get(dataTypeService)
            .Setup(x => x.GetAll())
            .Returns(new[] { dataType });

            var factory = new PublishedContentTypeFactory(Mock.Of <IPublishedModelFactory>(), new PropertyValueConverterCollection(Array.Empty <IPropertyValueConverter>()), dataTypeService);

            return(factory.CreateContentType(0, alias, new string[] {},
                                             new List <PublishedPropertyType>(Enumerable.Range(0, 10).Select(x => factory.CreatePropertyType("prop" + x, 1)))));
        }
Beispiel #28
0
        /// <summary>
        /// Gets a published content type.
        /// </summary>
        /// <param name="itemType">An item type.</param>
        /// <param name="alias">An alias.</param>
        /// <returns>The published content type corresponding to the item type and alias.</returns>
        public IPublishedContentType Get(PublishedItemType itemType, string alias)
        {
            var aliasKey = GetAliasKey(itemType, alias);

            try
            {
                _lock.EnterUpgradeableReadLock();

                if (_typesByAlias.TryGetValue(aliasKey, out var type))
                {
                    return(type);
                }

                type = CreatePublishedContentType(itemType, alias);

                try
                {
                    _lock.EnterWriteLock();
                    if (type.TryGetKey(out var key))
                    {
                        _keyToIdMap[key] = type.Id;
                    }
                    return(_typesByAlias[aliasKey] = _typesById[type.Id] = type);
                }
                finally
                {
                    if (_lock.IsWriteLockHeld)
                    {
                        _lock.ExitWriteLock();
                    }
                }
            }
            finally
            {
                if (_lock.IsUpgradeableReadLockHeld)
                {
                    _lock.ExitUpgradeableReadLock();
                }
            }
        }
Beispiel #29
0
    // looks safer but probably useless... ppl should not call these methods directly
    // and if they do... they have to take care about not doing stupid things

    // public static PublishedPropertyType GetModelPropertyType2<T>(Expression<Func<T, object>> selector)
    //    where T : PublishedContentModel
    // {
    //    var type = typeof (T);
    //    var s1 = type.GetField("ModelTypeAlias", BindingFlags.Public | BindingFlags.Static);
    //    var alias = (s1.IsLiteral && s1.IsInitOnly && s1.FieldType == typeof(string)) ? (string)s1.GetValue(null) : null;
    //    var s2 = type.GetField("ModelItemType", BindingFlags.Public | BindingFlags.Static);
    //    var itemType = (s2.IsLiteral && s2.IsInitOnly && s2.FieldType == typeof(PublishedItemType)) ? (PublishedItemType)s2.GetValue(null) : 0;

    // var contentType = PublishedContentType.Get(itemType, alias);
    //    // etc...
    // }
    public static IPublishedContentType?GetModelContentType(
        IPublishedSnapshotAccessor publishedSnapshotAccessor,
        PublishedItemType itemType,
        string alias)
    {
        IPublishedSnapshot publishedSnapshot = publishedSnapshotAccessor.GetRequiredPublishedSnapshot();

        switch (itemType)
        {
        case PublishedItemType.Content:
            return(publishedSnapshot.Content?.GetContentType(alias));

        case PublishedItemType.Media:
            return(publishedSnapshot.Media?.GetContentType(alias));

        case PublishedItemType.Member:
            return(publishedSnapshot.Members?.GetContentType(alias));

        default:
            throw new ArgumentOutOfRangeException(nameof(itemType));
        }
    }
        public static string GetLinkType(PublishedItemType itemType)
        {
            switch (itemType)
            {
            case PublishedItemType.Unknown:
                return(string.Empty);

            case PublishedItemType.Element:
                return(LinkType.Element.ToString());

            case PublishedItemType.Content:
                return(LinkType.Content.ToString());

            case PublishedItemType.Media:
                return(LinkType.Media.ToString());

            case PublishedItemType.Member:
                return(LinkType.Member.ToString());

            default:
                throw new ArgumentOutOfRangeException(nameof(itemType), itemType, null);
            }
        }
        private static IList<TypeModel> GetTypes(PublishedItemType itemType, IContentTypeBase[] contentTypes)
        {
            var typeModels = new List<TypeModel>();

            // get the types and the properties
            foreach (var contentType in contentTypes)
            {
                var typeModel = new TypeModel
                {
                    Id = contentType.Id,
                    Alias = contentType.Alias,
                    ClrName = contentType.Alias.ToCleanString(CleanStringType.ConvertCase | CleanStringType.PascalCase),
                    ParentId = contentType.ParentId,

                    Name = contentType.Name,
                    Description = contentType.Description
                };

                switch (itemType)
                {
                    case PublishedItemType.Content:
                        typeModel.ItemType = TypeModel.ItemTypes.Content;
                        break;
                    case PublishedItemType.Media:
                        typeModel.ItemType = TypeModel.ItemTypes.Media;
                        break;
                    case PublishedItemType.Member:
                        typeModel.ItemType = TypeModel.ItemTypes.Member;
                        break;
                    default:
                        throw new InvalidOperationException(string.Format("Unsupported PublishedItemType \"{0}\".", itemType));
                }

                typeModels.Add(typeModel);

                var publishedContentType = PublishedContentType.Get(itemType, contentType.Alias);

                foreach (var propertyType in contentType.PropertyTypes)
                {
                    var propertyModel = new PropertyModel
                    {
                        Alias = propertyType.Alias,
                        ClrName = propertyType.Alias.ToCleanString(CleanStringType.ConvertCase | CleanStringType.PascalCase),

                        Name = propertyType.Name,
                        Description = propertyType.Description
                    };

                    var publishedPropertyType = publishedContentType.GetPropertyType(propertyType.Alias);
                    propertyModel.ClrType = publishedPropertyType.ClrType;

                    typeModel.Properties.Add(propertyModel);
                }
            }

            // wire the base types
            foreach (var typeModel in typeModels.Where(x => x.ParentId > 0))
            {
                typeModel.BaseType = typeModels.SingleOrDefault(x => x.Id == typeModel.ParentId);
                // Umbraco 7.4 introduces content types containers, so even though ParentId > 0, the parent might
                // not be a content type - here we assume that BaseType being null while ParentId > 0 means that 
                // the parent is a container (and we don't check).
                typeModel.IsParent = typeModel.BaseType != null;
            }

            // discover mixins
            foreach (var contentType in contentTypes)
            {
                var typeModel = typeModels.SingleOrDefault(x => x.Id == contentType.Id);
                if (typeModel == null) throw new Exception("Panic: no type model matching content type.");

                IEnumerable<IContentTypeComposition> compositionTypes;
                var contentTypeAsMedia = contentType as IMediaType;
                var contentTypeAsContent = contentType as IContentType;
                var contentTypeAsMember = contentType as IMemberType;
                if (contentTypeAsMedia != null) compositionTypes = contentTypeAsMedia.ContentTypeComposition;
                else if (contentTypeAsContent != null) compositionTypes = contentTypeAsContent.ContentTypeComposition;
                else if (contentTypeAsMember != null) compositionTypes = contentTypeAsMember.ContentTypeComposition;
                else throw new Exception(string.Format("Panic: unsupported type \"{0}\".", contentType.GetType().FullName));

                foreach (var compositionType in compositionTypes)
                {
                    var compositionModel = typeModels.SingleOrDefault(x => x.Id == compositionType.Id);
                    if (compositionModel == null) throw new Exception("Panic: composition type does not exist.");

                    if (compositionType.Id == contentType.ParentId) continue;

                    // add to mixins
                    typeModel.MixinTypes.Add(compositionModel);

                    // mark as mixin - as well as parents
                    compositionModel.IsMixin = true;
                    while ((compositionModel = compositionModel.BaseType) != null)
                        compositionModel.IsMixin = true;
                }
            }

            return typeModels;
        }
        public static PublishedContentType Get(PublishedItemType itemType, string alias)
        {
            var key = string.Format("PublishedContentType_{0}_{1}",
                itemType == PublishedItemType.Content ? "content" : "media", alias.ToLowerInvariant());

            var type = ApplicationContext.Current.ApplicationCache.StaticCache.GetCacheItem<PublishedContentType>(key,
                () => CreatePublishedContentType(itemType, alias));

            return type;
        }
        private static PublishedContentType CreatePublishedContentType(PublishedItemType itemType, string alias)
        {
            if (GetPublishedContentTypeCallback != null)
                return GetPublishedContentTypeCallback(alias);

            var contentType = itemType == PublishedItemType.Content
                ? (IContentTypeComposition) ApplicationContext.Current.Services.ContentTypeService.GetContentType(alias)
                : (IContentTypeComposition) ApplicationContext.Current.Services.ContentTypeService.GetMediaType(alias);

            if (contentType == null)
                throw new Exception(string.Format("ContentTypeService failed to find a {0} type with alias \"{1}\".",
                    itemType.ToString().ToLower(), alias));

            return new PublishedContentType(contentType);
        }