using System; using System.Collections.Generic; using System.Linq; using Microsoft.SharePoint; namespace Taloyhtio.CustomNavigationCommon { // It sortes the folders based on SortOrder column added to content type. // OTB Folder content type is sealed, so in order to be able manually rearrange // folders sorting order custom content type should be created based on Folder content type. // See http://sharepoint-guru.blogspot.com/2007/06/adding-metadata-to-folder.html for details public static class FolderSorter { private const string ORDERED_FOLDER_CONTENT_TYPE_NAME = "Ordered Folder"; private const int DEFAULT_ORDER = 0; private const string SORT_ORDER_FIELD_NAME = "SortOrder"; public static List Sort(List folders) { try { if (folders.IsNullOrEmpty()) { return new List(); } // containts pairs (sortOrder, list of folders with that sortOrder) var sortDict = new Dictionary>(); int order; foreach (var folder in folders) { var isOrdered = isOrderedFolder(folder); if (isOrdered.HasValue && isOrdered.Value) { order = getOrder(folder); } else { // OTB folders are treated as having 0 order. They will be sorted after // ordered folders order = DEFAULT_ORDER; } addFolderWithOrder(sortDict, order, folder); } if (sortDict.IsNullOrEmpty()) { // it should not happen return new List(); } var result = sortFolders(sortDict); return result; } catch (Exception x) { LogUtils.LogError("Error occured during sorting folders:\n{0}\n{1}", x.Message, x.StackTrace); return folders; } } private static List sortFolders(Dictionary> sortDict) { if (sortDict.IsNullOrEmpty()) { return new List(); } var result = new List(); var orders = sortDict.Keys.ToList(); orders.Sort(); foreach (var order in orders) { if (order == DEFAULT_ORDER) { // folders with DEFAULT_ORDER are going last continue; } addFoldersRange(sortDict, order, result); } if (orders.Contains(DEFAULT_ORDER)) { addFoldersRange(sortDict, DEFAULT_ORDER, result); } return result; } private static void addFoldersRange(Dictionary> sortDict, int order, List result) { var folders = sortDict[order]; if (folders.IsNullOrEmpty()) { return; } // within the same order folders are sorted alphabetically var sortedFolders = folders.OrderBy(f => f.Name); result.AddRange(sortedFolders); } private static void addFolderWithOrder(Dictionary> sortDict, int order, SPFolder folder) { if (sortDict == null) { return; } if (!sortDict.ContainsKey(order)) { sortDict[order] = new List(); } sortDict[order].Add(folder); } private static int getOrder(SPFolder folder) { try { if (folder == null) { return DEFAULT_ORDER; } if (!folder.Item.Fields.ContainsField(SORT_ORDER_FIELD_NAME)) { return DEFAULT_ORDER; } var val = folder.Item[SORT_ORDER_FIELD_NAME] as double?; if (!val.HasValue) { return DEFAULT_ORDER; } int order = Convert.ToInt32(val.Value); if (order < 0) { order = 0; } return order; } catch (Exception x) { //LogUtils.LogError(x); return DEFAULT_ORDER; } } private static bool? isOrderedFolder(SPFolder folder) { try { if (folder == null) { return null; } string contentTypeName = (string)folder.Item[SPBuiltInFieldId.ContentType]; return (contentTypeName == ORDERED_FOLDER_CONTENT_TYPE_NAME); } catch (Exception x) { //LogUtils.LogError(x); return null; } } } }