<commit_before>﻿using System;
using System.Linq;
using System.Web.Mvc;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Aspects;
using Orchard.ContentManagement.Drivers;
using Orchard.Core.Common.Models;
using Orchard.Core.Containers.Models;
using Orchard.Core.Containers.ViewModels;
using Orchard.Localization;

namespace Orchard.Core.Containers.Drivers {
    public class ContainablePartDriver : ContentPartDriver<ContainablePart> {
        private readonly IContentManager _contentManager;

        public ContainablePartDriver(IContentManager contentManager) {
            _contentManager = contentManager;
            T = NullLocalizer.Instance;
        }

        public Localizer T { get; set; }

        protected override DriverResult Editor(ContainablePart part, dynamic shapeHelper) {
            return Editor(part, (IUpdateModel)null, shapeHelper);
        }

        protected override DriverResult Editor(ContainablePart part, IUpdateModel updater, dynamic shapeHelper) {
            return ContentShape(
                "Parts_Containable_Edit",
                () => {
                    var commonPart = part.As<ICommonPart>();

                    var model = new ContainableViewModel();
                    if (commonPart.Container != null) {
                        model.ContainerId = commonPart.Container.Id;
                    }

                    if (updater != null) {
                        var oldContainerId = model.ContainerId;
                        updater.TryUpdateModel(model, "Containable", null, null);
                        if (oldContainerId != model.ContainerId)
                            commonPart.Container = _contentManager.Get(model.ContainerId, VersionOptions.Latest);
                    }

                    // these containers are allowed to contain any content type
                    var freeContainers = _contentManager.Query<ContainerPart, ContainerPartRecord>(VersionOptions.Latest).Where(ctr => ctr.ItemContentType == null).List();
                    // these containers are allowed to contain any content type (workaround: string.IsNullOrEmpty not functioning)
                    var freeContainers2 = _contentManager.Query<ContainerPart, ContainerPartRecord>(VersionOptions.Latest).Where(ctr => ctr.ItemContentType == "").List();
                    // these containers are restricted to contain the content type of this content item
                    var restrictedContainers = _contentManager.Query<ContainerPart, ContainerPartRecord>(VersionOptions.Latest).Where(ctr => ctr.ItemContentType == part.ContentItem.ContentType).List();
                    var containers = restrictedContainers.Concat(freeContainers).Concat(freeContainers2).OrderByDescending(ctr => ctr.As<CommonPart>().PublishedUtc);

                    var listItems = new[] { new SelectListItem { Text = T("(None)").Text, Value = "0" } }
                        .Concat(containers.Select(x => new SelectListItem {
                            Value = Convert.ToString(x.Id),
                            Text = x.ContentItem.TypeDefinition.DisplayName + ": " + x.As<IRoutableAspect>().Title,
                            Selected = x.Id == model.ContainerId,
                        }))
                        .ToList();

                    model.AvailableContainers = new SelectList(listItems, "Value", "Text", model.ContainerId);

                    return shapeHelper.EditorTemplate(TemplateName: "Containable", Model: model, Prefix: "Containable");
                });
        }<commit_msg>Much better query to find allowable containers.<commit_after>﻿using System;
using System.Linq;
using System.Web.Mvc;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Aspects;
using Orchard.ContentManagement.Drivers;
using Orchard.Core.Common.Models;
using Orchard.Core.Containers.Models;
using Orchard.Core.Containers.ViewModels;
using Orchard.Localization;

namespace Orchard.Core.Containers.Drivers {
    public class ContainablePartDriver : ContentPartDriver<ContainablePart> {
        private readonly IContentManager _contentManager;

        public ContainablePartDriver(IContentManager contentManager) {
            _contentManager = contentManager;
            T = NullLocalizer.Instance;
        }

        public Localizer T { get; set; }

        protected override DriverResult Editor(ContainablePart part, dynamic shapeHelper) {
            return Editor(part, (IUpdateModel)null, shapeHelper);
        }

        protected override DriverResult Editor(ContainablePart part, IUpdateModel updater, dynamic shapeHelper) {
            return ContentShape(
                "Parts_Containable_Edit",
                () => {
                    var commonPart = part.As<ICommonPart>();

                    var model = new ContainableViewModel();
                    if (commonPart.Container != null) {
                        model.ContainerId = commonPart.Container.Id;
                    }

                    if (updater != null) {
                        var oldContainerId = model.ContainerId;
                        updater.TryUpdateModel(model, "Containable", null, null);
                        if (oldContainerId != model.ContainerId)
                            commonPart.Container = _contentManager.Get(model.ContainerId, VersionOptions.Latest);
                    }

                    // note: string.isnullorempty not being recognized by linq-to-nhibernate hence the inline or
                    var containers = _contentManager.Query<ContainerPart, ContainerPartRecord>(VersionOptions.Latest)
                        .Where(ctr => ctr.ItemContentType == null || ctr.ItemContentType == "" || ctr.ItemContentType == part.ContentItem.ContentType).List();

                    var listItems = new[] { new SelectListItem { Text = T("(None)").Text, Value = "0" } }
                        .Concat(containers.Select(x => new SelectListItem {
                            Value = Convert.ToString(x.Id),
                            Text = x.ContentItem.TypeDefinition.DisplayName + ": " + x.As<IRoutableAspect>().Title,
                            Selected = x.Id == model.ContainerId,
                        }))
                        .ToList();

                    model.AvailableContainers = new SelectList(listItems, "Value", "Text", model.ContainerId);

                    return shapeHelper.EditorTemplate(TemplateName: "Containable", Model: model, Prefix: "Containable");
                });
        }
{'fraction_non_alphanumeric': 0.09012611504152568, 'fraction_numerical': 0.0006151953245155337, 'mean_word_length': 2.135486981677917, 'pattern_counts': {'":': 2, '<': 14, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6271765', 'n_tokens_mistral': 1617, 'n_tokens_neox': 1536, 'n_words': 338}