Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- DateFolders v1.5 for umbraco 4.5+
- Created by Stefan Kip (kipusoep), InfoCaster
- Modified by Niek Bosch, De Media Fabriek
- MIT license
- Copyright (c) 2011 InfoCaster
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
- */
- using System;
- using System.Collections.Generic;
- using System.Configuration;
- using System.Linq;
- using System.Web;
- using umbraco.BasePages;
- using umbraco.BusinessLogic;
- using umbraco.cms.businesslogic;
- using umbraco.cms.businesslogic.web;
- using umbraco.presentation.nodeFactory;
- namespace InfoCaster.Umbraco.Common
- {
- /// <summary>
- /// This package creates Datefolders (year/month(/day)) for the specified doctype for Umbraco 4.5+
- ///
- /// Behavior
- ///
- /// - When you create a document with doctype "itemDocType", this package will automatically create year/month/day folders for it
- /// - When you edit the "itemDateProperty", the document is automatically moved to the correct year/month/day folder
- /// - Automatically cleans up empty year, month and day folders
- /// - Orders the items in the year, month and dayfolders by "itemDateProperty" with every action
- ///
- /// Configuration
- ///
- /// Add these keys/values to your appSettings section in the web.config:
- /// - Key: "datefolders:ItemDocType" - the doctype alias to create datefolders for (e.g. "newsItem") - comma separated values are allowed for multiple doctype aliases
- /// - Key: "datefolders:ItemDateProperty" - the property of the itemDocType to read the date from (e.g. "startDate") (don't add this key if you just want to use the document's create date)
- /// - Key: "datefolders:DateFolderDocType" - the doctype to use for creating the year/month/day folders (e.g "DateFolder")
- /// - Key: "datefolders:CreateDayFolders" - boolean indicating whether or not day folders should be created
- /// - Key: "datefolders:ForceDateFolderStructure" - boolean indicating whether or not the year/month/day folder structure should be enforced
- ///
- /// Changelog
- ///
- /// Version 1.5
- /// - Added support for enforcing the year/month/day folder structure.
- ///
- /// Version 1.4
- /// - Removed Threading (Threading can cause the back-end to be out-of-sync, therefore removed)
- /// - Changed configuration keys, added prefix (legacy still works)
- /// - Added day folders feature (configurable, off by default)
- /// - Fixed silly order by hard-coded propertyAlias bug
- ///
- /// Version 1.3
- /// - Better exception handling (speechbubble)
- /// - Exception get's handled when the datefoler document type doesn't exist
- /// - Month folders are now named with a leading zero if the month number is a single number (01, 02 etc.)
- /// - Exception get's handled when a date item is created under the 'Content' root node
- ///
- /// Version 1.2
- /// - Support for multiple itemDocTypes (comma separated)
- ///
- /// Version 1.1
- /// - Tree get's synced automatically
- /// </summary>
- public class DateFolders : ApplicationBase
- {
- readonly string[] _itemDocType;
- readonly string _itemDateProperty;
- readonly string _dateFolderDocType;
- readonly bool _createDayFolders;
- readonly bool _forceDateFolderStructure;
- static readonly object _syncer = new object();
- /* Configuration properties:
- *
- * datefolders:ItemDocType (string)
- * datefolders:ItemDateProperty (string, optional, default create date)
- * datefolders:DateFolderDocType (string)
- * datefolders:CreateDayFolders (bool, optional, default false)
- * datefolders:ForceDateFolderStructure (bool, optional, default false)
- */
- /// <summary>
- /// Constructor
- /// </summary>
- public DateFolders()
- {
- if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["datefolders:ItemDocType"]) && !string.IsNullOrEmpty(ConfigurationManager.AppSettings["datefolders:DateFolderDocType"]))
- {
- _itemDocType = ConfigurationManager.AppSettings["datefolders:ItemDocType"].Split(',');
- _itemDateProperty = ConfigurationManager.AppSettings["datefolders:ItemDateProperty"];
- _dateFolderDocType = ConfigurationManager.AppSettings["datefolders:DateFolderDocType"];
- string createDayFoldersString = ConfigurationManager.AppSettings["datefolders:CreateDayFolders"];
- if (!string.IsNullOrEmpty(createDayFoldersString))
- bool.TryParse(createDayFoldersString, out _createDayFolders);
- string forceDateFolderStructureString = ConfigurationManager.AppSettings["datefolders:ForceDateFolderStructure"];
- if (!string.IsNullOrEmpty(forceDateFolderStructureString))
- bool.TryParse(forceDateFolderStructureString, out _forceDateFolderStructure);
- }
- else if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["itemDocType"]) && !string.IsNullOrEmpty(ConfigurationManager.AppSettings["dateFolderDocType"]))
- {
- // Legacy
- _itemDocType = ConfigurationManager.AppSettings["itemDocType"].Split(',');
- _itemDateProperty = ConfigurationManager.AppSettings["itemDateProperty"];
- _dateFolderDocType = ConfigurationManager.AppSettings["dateFolderDocType"];
- string createDayFoldersString = ConfigurationManager.AppSettings["createDayFolders"];
- if (!string.IsNullOrEmpty(createDayFoldersString))
- bool.TryParse(createDayFoldersString, out _createDayFolders);
- string forceDateFolderStructureString = ConfigurationManager.AppSettings["forceDateFolderStructure"];
- if (!string.IsNullOrEmpty(forceDateFolderStructureString))
- bool.TryParse(forceDateFolderStructureString, out _forceDateFolderStructure);
- }
- if (_itemDocType.Length > 0 && !string.IsNullOrEmpty(_dateFolderDocType))
- {
- Document.New += new Document.NewEventHandler(Document_New);
- Document.AfterSave += new Document.SaveEventHandler(Document_AfterSave);
- Document.BeforeMoveToTrash += new Document.MoveToTrashEventHandler(Document_BeforeMoveToTrash);
- Document.AfterMoveToTrash += new Document.MoveToTrashEventHandler(Document_AfterMoveToTrash);
- }
- }
- /// <summary>
- /// Before move to trash event
- /// </summary>
- /// <param name="doc">The document</param>
- /// <param name="e">The event args</param>
- void Document_BeforeMoveToTrash(Document doc, MoveToTrashEventArgs e)
- {
- if (_itemDocType.Contains(doc.ContentType.Alias))
- {
- try
- {
- if (_createDayFolders)
- {
- HttpContext.Current.Items.Add("dayId", doc.ParentId);
- HttpContext.Current.Items.Add("monthId", doc.Parent.ParentId);
- HttpContext.Current.Items.Add("yearId", doc.Parent.Parent.ParentId);
- }
- else
- {
- HttpContext.Current.Items.Add("monthId", doc.ParentId);
- HttpContext.Current.Items.Add("yearId", doc.Parent.ParentId);
- }
- }
- catch (Exception ex)
- {
- if (BasePage.Current != null)
- BasePage.Current.ClientTools.ShowSpeechBubble(BasePage.speechBubbleIcon.error, "DateFolders Document_BeforeMoveToTrash exception", ex.Message);
- umbraco.BusinessLogic.Log.Add(LogTypes.Error, -1, string.Format("DateFolders Document_BeforeMoveToTrash exception: {0}", ex.Message));
- #if DEBUG
- System.Diagnostics.Trace.TraceInformation(string.Format("DateFolders Document_BeforeMoveToTrash exception: {0}", ex.Message));
- #endif
- }
- }
- }
- /// <summary>
- /// After move to trash event
- /// </summary>
- /// <param name="doc">The document</param>
- /// <param name="e">The event args</param>
- void Document_AfterMoveToTrash(Document doc, MoveToTrashEventArgs e)
- {
- if (_itemDocType.Contains(doc.ContentType.Alias))
- {
- // Date item deleted
- try
- {
- int dayId = -100, monthId, yearId;
- if (_createDayFolders)
- {
- dayId = int.Parse(HttpContext.Current.Items["dayId"].ToString());
- HttpContext.Current.Items.Remove("dayId");
- monthId = int.Parse(HttpContext.Current.Items["monthId"].ToString());
- yearId = int.Parse(HttpContext.Current.Items["yearId"].ToString());
- }
- else
- {
- monthId = int.Parse(HttpContext.Current.Items["monthId"].ToString());
- yearId = int.Parse(HttpContext.Current.Items["yearId"].ToString());
- }
- HttpContext.Current.Items.Remove("monthId");
- HttpContext.Current.Items.Remove("yearId");
- if (_createDayFolders)
- {
- Node day = new Node(dayId);
- if (day.Children.Count < 1)
- new Document(dayId).DeleteCompletely();
- }
- Node month = new Node(monthId);
- if (month.Children.Count < 1)
- {
- new Document(monthId).DeleteCompletely();
- Node year = new Node(yearId);
- if (year.Children.Count < 1)
- new Document(yearId).DeleteCompletely();
- }
- }
- catch (Exception ex)
- {
- if (BasePage.Current != null)
- BasePage.Current.ClientTools.ShowSpeechBubble(BasePage.speechBubbleIcon.error, "DateFolders Document_AfterMoveToTrash exception", ex.Message);
- umbraco.BusinessLogic.Log.Add(LogTypes.Error, -1, string.Format("DateFolders Document_AfterMoveToTrash exception: {0}", ex.Message));
- #if DEBUG
- System.Diagnostics.Trace.TraceInformation(string.Format("DateFolders Document_AfterMoveToTrash exception: {0}", ex.Message));
- #endif
- }
- }
- }
- /// <summary>
- /// After save event
- /// </summary>
- /// <param name="doc">The document</param>
- /// <param name="e">The event args</param>
- void Document_AfterSave(Document doc, SaveEventArgs e)
- {
- if (_itemDocType.Contains(doc.ContentType.Alias))
- {
- DocumentType folderDocType = DocumentType.GetByAlias(_dateFolderDocType);
- if (folderDocType != null)
- {
- if (doc.ParentId > 0)
- {
- // Date item saved
- DateTime date = default(DateTime);
- if (!string.IsNullOrEmpty(_itemDateProperty))
- {
- string dateValue = doc.GetDatePropertyValue(_itemDateProperty);
- if (!string.IsNullOrEmpty(dateValue))
- DateTime.TryParse(dateValue, out date);
- }
- if (date == default(DateTime))
- date = doc.CreateDateTime;
- Document parent, monthFolder, yearFolder, dayFolder = null, dayDoc = null, monthDoc = null, yearDoc = null;
- if (_createDayFolders)
- {
- dayFolder = new Document(doc.ParentId);
- monthFolder = new Document(dayFolder.ParentId);
- yearFolder = new Document(monthFolder.ParentId);
- }
- else
- {
- monthFolder = new Document(doc.ParentId);
- yearFolder = new Document(monthFolder.ParentId);
- }
- parent = new Document(yearFolder.ParentId);
- bool yearChanged, monthChanged, dayChanged = false;
- yearChanged = date.Year.ToString() != yearFolder.Text;
- monthChanged = date.Month.ToString("00") != monthFolder.Text;
- if (_createDayFolders)
- dayChanged = date.Day.ToString("00") != dayFolder.Text;
- if (yearChanged || monthChanged || dayChanged)
- {
- // Date changed
- Document newYearFolder = null, newMonthFolder = null, newDayFolder = null;
- if (yearChanged)
- {
- // Year changed
- newYearFolder = parent.Children.FirstOrDefault(x => x.ContentType.Alias == _dateFolderDocType && x.Text == date.Year.ToString());
- if (newYearFolder == null)
- {
- // Create year folder
- newYearFolder = Document.MakeNew(date.Year.ToString(), DocumentType.GetByAlias(_dateFolderDocType), doc.User, parent.Id);
- }
- }
- else
- newYearFolder = yearFolder;
- // Month
- newMonthFolder = newYearFolder.Children.FirstOrDefault(x => x.ContentType.Alias == _dateFolderDocType && x.Text == date.Month.ToString("00"));
- if (newMonthFolder == null)
- {
- // Create month folder
- newMonthFolder = Document.MakeNew(date.Month.ToString("00"), DocumentType.GetByAlias(_dateFolderDocType), doc.User, newYearFolder.Id);
- }
- if (_createDayFolders)
- {
- // Day
- newDayFolder = newMonthFolder.Children.FirstOrDefault(x => x.ContentType.Alias == _dateFolderDocType && x.Text == date.Day.ToString("00"));
- if (newDayFolder == null)
- {
- // Create day folder
- newDayFolder = Document.MakeNew(date.Day.ToString("00"), DocumentType.GetByAlias(_dateFolderDocType), doc.User, newMonthFolder.Id);
- }
- }
- // Move
- if (_createDayFolders)
- doc.Move(newDayFolder.Id);
- else
- doc.Move(newMonthFolder.Id);
- if (doc.Published)
- doc.SaveAndPublish();
- int orderParentId = newMonthFolder.Id;
- if (_createDayFolders)
- orderParentId = newDayFolder.Id;
- if (!string.IsNullOrEmpty(_itemDateProperty))
- OrderChildrenByDateProperty(new Document(orderParentId), _itemDateProperty);
- else
- OrderChildrenByCreateDate(new Document(orderParentId));
- if (newYearFolder != null)
- newYearFolder.SaveAndPublish();
- if (newMonthFolder != null)
- newMonthFolder.SaveAndPublish();
- if (newDayFolder != null)
- newDayFolder.SaveAndPublish();
- // Delete if empty
- if (_createDayFolders)
- {
- dayDoc = new Document(dayFolder.Id);
- if (dayDoc.ChildCount < 1)
- {
- dayDoc.DeleteCompletely();
- }
- }
- monthDoc = new Document(monthFolder.Id);
- if (monthDoc.ChildCount < 1)
- {
- monthDoc.DeleteCompletely();
- yearDoc = new Document(yearFolder.Id);
- if (yearDoc.ChildCount < 1)
- yearDoc.DeleteCompletely();
- }
- // Order
- OrderChildrenByName(new Document(parent.Id));
- OrderChildrenByName(new Document(newYearFolder.Id));
- if (_createDayFolders)
- OrderChildrenByName(new Document(newMonthFolder.Id));
- doc = new Document(doc.Id);
- BasePage.Current.ClientTools
- .ChangeContentFrameUrl(string.Concat("editContent.aspx?id=", doc.Id));
- }
- }
- else
- {
- // Item is created under 'Content' root, which is unsupported
- if (BasePage.Current != null)
- BasePage.Current.ClientTools.ShowSpeechBubble(BasePage.speechBubbleIcon.error, "Unsupported", "Creating a datefolders item under 'Content' root is unsupported");
- }
- }
- else
- {
- // Date folder doctype is null
- if (BasePage.Current != null)
- BasePage.Current.ClientTools.ShowSpeechBubble(BasePage.speechBubbleIcon.error, "Configuration error", string.Format("The date folder doctype ('{0}') does not exist", _dateFolderDocType));
- }
- }
- }
- /// <summary>
- /// New document event
- /// </summary>
- /// <param name="doc">The document</param>
- /// <param name="e">The event args</param>
- void Document_New(Document doc, NewEventArgs e)
- {
- try
- {
- DocumentType folderDocType = DocumentType.GetByAlias(_dateFolderDocType);
- if (folderDocType != null)
- {
- Document parent = new Document(doc.ParentId);
- if (_forceDateFolderStructure)
- {
- // Find first ancestor that is not a date folder
- while (parent.ContentType.Alias == _dateFolderDocType)
- {
- parent = new Document(parent.ParentId);
- }
- }
- if (_itemDocType.Contains(doc.ContentType.Alias))
- {
- // Date item created
- DateTime now = DateTime.Now;
- Document yearFolder = parent.Children.FirstOrDefault(x => x.ContentType.Alias == _dateFolderDocType && x.Text == now.Year.ToString());
- if (yearFolder == null)
- {
- // Create year folder
- yearFolder = Document.MakeNew(now.Year.ToString(), DocumentType.GetByAlias(_dateFolderDocType), doc.User, parent.Id);
- }
- Document monthFolder = yearFolder.Children.FirstOrDefault(x => x.ContentType.Alias == _dateFolderDocType && x.Text == now.Month.ToString("00"));
- if (monthFolder == null)
- {
- // Create month folder
- monthFolder = Document.MakeNew(now.Month.ToString("00"), DocumentType.GetByAlias(_dateFolderDocType), doc.User, yearFolder.Id);
- }
- Document dayFolder = null;
- if (_createDayFolders)
- {
- dayFolder = monthFolder.Children.FirstOrDefault(x => x.ContentType.Alias == _dateFolderDocType && x.Text == now.Day.ToString("00"));
- if (dayFolder == null)
- {
- // Create day folder
- dayFolder = Document.MakeNew(now.Day.ToString("00"), DocumentType.GetByAlias(_dateFolderDocType), doc.User, monthFolder.Id);
- }
- }
- if (_createDayFolders)
- doc.Move(dayFolder.Id);
- else
- doc.Move(monthFolder.Id);
- doc.Save();
- if (yearFolder != null)
- yearFolder.SaveAndPublish();
- if (monthFolder != null)
- monthFolder.SaveAndPublish();
- if (dayFolder != null)
- dayFolder.SaveAndPublish();
- // Order
- OrderChildrenByName(new Document(parent.Id));
- OrderChildrenByName(new Document(yearFolder.Id));
- if (_createDayFolders)
- OrderChildrenByName(new Document(monthFolder.Id));
- }
- }
- else
- {
- // Date folder doctype is null
- if (BasePage.Current != null)
- BasePage.Current.ClientTools.ShowSpeechBubble(BasePage.speechBubbleIcon.error, "Date folder property", string.Format("The date folder doctype does not exist ({0})", _dateFolderDocType));
- }
- }
- catch { }
- }
- /// <summary>
- /// Order the children by propertyAlias
- /// </summary>
- /// <param name="parent">The parent document</param>
- /// <param name="propertyAlias">The property alias</param>
- static void OrderChildrenByDateProperty(Document parent, string propertyAlias)
- {
- lock (_syncer)
- {
- try
- {
- DoOrder(parent.Children.OrderBy(x => DateTime.Parse(x.GetPropertyValueAsString(propertyAlias))));
- }
- catch (Exception ex)
- {
- if (BasePage.Current != null)
- BasePage.Current.ClientTools.ShowSpeechBubble(BasePage.speechBubbleIcon.error, "DateFolders OrderChildrenByDateProperty exception", ex.Message);
- umbraco.BusinessLogic.Log.Add(LogTypes.Error, -1, string.Format("DateFolders OrderChildrenByDateProperty exception: {0}", ex.Message));
- #if DEBUG
- System.Diagnostics.Trace.TraceInformation(string.Format("DateFolders OrderChildrenByDateProperty exception: {0}", ex.Message));
- #endif
- }
- }
- }
- /// <summary>
- /// Order the children by createDate
- /// </summary>
- /// <param name="parent">The parent document</param>
- static void OrderChildrenByCreateDate(Document parent)
- {
- lock (_syncer)
- {
- try
- {
- DoOrder(parent.Children.OrderBy(x => x.CreateDateTime));
- }
- catch (Exception ex)
- {
- if (BasePage.Current != null)
- BasePage.Current.ClientTools.ShowSpeechBubble(BasePage.speechBubbleIcon.error, "DateFolders OrderChildrenByCreateDate exception", ex.Message);
- umbraco.BusinessLogic.Log.Add(LogTypes.Error, -1, string.Format("DateFolders OrderChildrenByCreateDate exception: {0}", ex.Message));
- #if DEBUG
- System.Diagnostics.Trace.TraceInformation(string.Format("DateFolders OrderChildrenByCreateDate exception: {0}", ex.Message));
- #endif
- }
- }
- }
- /// <summary>
- /// Order the children by name
- /// </summary>
- /// <param name="parent">The parent document</param>
- static void OrderChildrenByName(Document parent)
- {
- lock (_syncer)
- {
- try
- {
- DoOrder(parent.Children.OrderBy(x => int.Parse(x.Text)));
- }
- catch (Exception ex)
- {
- if (BasePage.Current != null)
- BasePage.Current.ClientTools.ShowSpeechBubble(BasePage.speechBubbleIcon.error, "DateFolders OrderChildrenByName exception", ex.Message);
- umbraco.BusinessLogic.Log.Add(LogTypes.Error, -1, string.Format("DateFolders OrderChildrenByName exception: {0}", ex.Message));
- #if DEBUG
- System.Diagnostics.Trace.TraceInformation(string.Format("DateFolders OrderChildrenByName exception: {0}", ex.Message));
- #endif
- }
- }
- }
- /// <summary>
- /// Order documents
- /// </summary>
- /// <param name="documents">The documents</param>
- static void DoOrder(IEnumerable<Document> documents)
- {
- int sortOrder = 0;
- foreach (Document objChild in documents)
- {
- objChild.sortOrder = sortOrder;
- sortOrder++;
- }
- }
- }
- static class UmbracoExtensions
- {
- /// <summary>
- /// Deletes a document completely
- /// </summary>
- /// <param name="document">The document to delete completely</param>
- public static void DeleteCompletely(this Document document)
- {
- if (document != null)
- {
- if (document.Published)
- {
- document.UnPublish();
- umbraco.library.UnPublishSingleNode(document.Id);
- }
- document.delete(true);
- }
- }
- /// <summary>
- /// Returns the value as string of the property with the given alias
- /// </summary>
- /// <param name="node">The document</param>
- /// <param name="propertyAlias">The alias of the property</param>
- /// <returns>The property's value</returns>
- public static string GetPropertyValueAsString(this Document document, string propertyAlias)
- {
- if (document.getProperty(propertyAlias) != null && document.getProperty(propertyAlias).Value != null)
- return document.getProperty(propertyAlias).Value.ToString();
- return string.Empty;
- }
- /// <summary>
- /// Saves and publishes a document
- /// </summary>
- /// <param name="document">The document to save and publish</param>
- public static void SaveAndPublish(this Document document)
- {
- if (document != null)
- {
- document.Save();
- document.Publish(document.User);
- umbraco.library.UpdateDocumentCache(document.Id);
- }
- }
- /// <summary>
- /// Gets the date property
- /// </summary>
- /// <param name="doc"></param>
- /// <returns></returns>
- public static string GetDatePropertyValue(this Document doc, string itemDateProperty)
- {
- if (string.IsNullOrEmpty(itemDateProperty))
- return doc.CreateDateTime.ToString();
- return doc.GetPropertyValueAsString(itemDateProperty);
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement