In this example, we'll see what content-blocks are in the system, and where they are in use.
@inherits Custom.Hybrid.Razor14 @if (CmsContext.Platform.Name == "Oqtane") { @Html.Partial("../../tut-sys/messages/MessageOqtaneDisabled.cshtml") } else { @Html.Partial("110-content-blocks.dnn.cshtml") }
@inherits Custom.Hybrid.Razor14 @using System.Collections; @using System.Linq @using DotNetNuke.Entities.Modules; @* Tag: #DnnOnly - ATM can't work in Oqtane because it uses the Factory command and because it uses DNN objects 2sxclint:disable:no-inline-script 2sxclint:disable:no-dnn-namespaces *@ @{ // isDev should just tell us, if we're looking at the dev-portal (while creating this demo app) or if it's running on 2sxc.org // where we use other zoneId and appId; var isDev = CmsContext.Site.Id == 59; var is2sxcTutorial = CmsContext.Site.Id == 24; var portalId = isDev ? 10 : is2sxcTutorial ? 0 : CmsContext.Site.Id; // create array with all 2sxc modules in this portal var allMods = GetAllModulesOfPortal(portalId); // Get the app & views we're going to investigate the views of var app = isDev ? ToSic.Sxc.Dnn.Factory.App(11, 35) // some app on our dev environment : is2sxcTutorial ? ToSic.Sxc.Dnn.Factory.App(2, 2) // the 2sxc.org Content-App : App; // fallback, use this app, but not very exciting // all views in this specific app, sorted by name var views = AsList(app.Data["2SexyContent-Template"]).OrderBy(t => t.Name); // get all content blocks which have templates - skip the ones without, as they have not been initialized yet var contentBlocks = AsList(app.Data["2SexyContent-ContentGroup"]); // create a map of all blocks to DNN modules var block2ModuleMap = contentBlocks.GroupJoin(allMods, cb => cb.EntityGuid, m => Kit.Convert.ToGuid(m.ModuleSettings[SettingsCG]), (cb, m) => new { Block = cb, Modules = m } ); // now map all the template-IDs to the block-module map var template2BlockModuleMap = block2ModuleMap.GroupBy(b2m => { var templates = AsList(b2m.Block.Template as object); return templates.Any() ? templates.First().EntityGuid : null; }); var viewsWithBlocks = views.GroupJoin(template2BlockModuleMap, v => v.EntityGuid, bwm => bwm.Key, (v, bwm) => { var blockWithMod = bwm.SingleOrDefault(); return new { View = v, Blocks = blockWithMod, ModsCount = blockWithMod != null ? blockWithMod.SelectMany(bmlist => bmlist.Modules).Count() : 0, }; } ); } <h2>Statistics</h2> <ol> <li>We're looking at portal @portalId, Zone @app.ZoneId, App: @app.AppId </li> <li>@views.Count() Views</li> <li>@contentBlocks.Count() Content Blocks </li> <li>@allMods.Count() DNN Modules in the primary language </li> </ol> <hr> <h2>Views</h2> @foreach (var set in viewsWithBlocks) { <h3>View @set.View.Name</h3> if (set.Blocks != null) { <div> Used in @set.Blocks.Count() blocks and @set.ModsCount modules </div> <ol> @foreach (var blockSet in set.Blocks) { <li> Block: @blockSet.Block.EntityGuid (@blockSet.Block.EntityId) in @blockSet.Modules.Count() modules: @string.Join(",", blockSet.Modules.Select(m => m.ModuleID)) </li> } </ol> } else { <text>not in use</text> } } @functions { // CONSTANTS // this key is used in module settings const string SettingsCG = "ToSIC_SexyContent_ContentGroupGuid"; // create array with all 2sxc modules in this portal List<ModuleInfo> GetAllModulesOfPortal(int portalId) { var mc = ModuleController.Instance; var dnnMod2sxcContent = mc.GetModulesByDefinition(portalId, "2Sexy Content"); var dnnMod2sxcApp = mc.GetModulesByDefinition(portalId, "2Sexy Content App"); var mergedMods = new ModuleInfo[dnnMod2sxcContent.Count + dnnMod2sxcApp.Count]; dnnMod2sxcContent.CopyTo(mergedMods); dnnMod2sxcApp.CopyTo(mergedMods, dnnMod2sxcContent.Count); var allMods = mergedMods .Where(m => m.DefaultLanguageModule == null) .Where(m => !m.IsDeleted) .Where(m => m.ModuleSettings.ContainsKey(SettingsCG)); return allMods.ToList(); } }
This sample uses some internal APIs, so if you use this, it may require some adjustments in future.