namespace BlogEngine.Core { using System; using System.Collections.Generic; using System.Linq; using BlogEngine.Core.Providers; /// /// A page is much like a post, but is not part of the /// blog chronology and is more static in nature. /// /// Pages can be used for "About" pages or other static /// information. /// /// public sealed class Page : BusinessBase, IPublishable { #region Constants and Fields /// /// The _ sync root. /// private static readonly object SyncRoot = new object(); /// /// The pages that not deleted. /// private static Dictionary> pages; /// /// The deleted pages. /// private static Dictionary> deletedpages; /// /// The _ content. /// private string content; /// /// The _ description. /// private string description; /// /// The _ keywords. /// private string keywords; /// /// The _ parent. /// private Guid parent; /// /// The _ show in list. /// private bool showInList; /// /// The _ slug. /// private string slug; /// /// The _ title. /// private string title; /// /// The front page. /// private bool frontPage; /// /// The published. /// private bool isPublished; /// /// The deleted. /// private bool isDeleted; /// /// The sort order /// private int sortOrder; #endregion #region Constructors and Destructors /// /// Initializes a new instance of the class. /// The contructor sets default values. /// public Page() { this.Id = Guid.NewGuid(); this.DateCreated = BlogSettings.Instance.FromUtc(); } static Page() { Blog.Saved += (s, e) => { if (e.Action == SaveAction.Delete) { Blog blog = s as Blog; if (blog != null) { // remove deleted blog from static 'pages' and 'deletedpages' if (pages != null && pages.ContainsKey(blog.Id)) pages.Remove(blog.Id); if (deletedpages != null && deletedpages.ContainsKey(blog.Id)) deletedpages.Remove(blog.Id); } } }; } #endregion #region Events /// /// Occurs when the page is being served to the output stream. /// public static event EventHandler Serving; #endregion #region Properties /// /// Gets an unsorted list of all pages excluding deleted. /// public static List Pages { get { Blog blog = Blog.CurrentInstance; if (pages == null || !pages.ContainsKey(blog.Id)) { lock (SyncRoot) { if (pages == null || !pages.ContainsKey(blog.Id)) { if (pages == null) pages = new Dictionary>(); pages[blog.Id] = BlogService.FillPages().Where(p => p.IsDeleted == false).ToList(); pages[blog.Id].Sort((p1, p2) => String.Compare(p1.Title, p2.Title)); } } } return pages[blog.Id]; } } /// /// Gets an unsorted list of deleted pages. /// public static List DeletedPages { get { Blog blog = Blog.CurrentInstance; if (deletedpages == null || !deletedpages.ContainsKey(blog.Id)) { lock (SyncRoot) { if (deletedpages == null || !deletedpages.ContainsKey(blog.Id)) { if (deletedpages == null) deletedpages = new Dictionary>(); deletedpages[blog.Id] = BlogService.FillPages().Where(p => p.IsDeleted == true).ToList(); deletedpages[blog.Id].Sort((p1, p2) => String.Compare(p1.Title, p2.Title)); } } } return deletedpages[blog.Id]; } } /// /// Gets the absolute link to the page. /// public Uri AbsoluteLink { get { return Utils.ConvertToAbsolute(this.RelativeLink); } } /// /// Gets or sets the Description or the object. /// public string Content { get { return this.content; } set { base.SetValue("Content", value, ref this.content); } } /// /// Gets or sets the Description or the object. /// public string Description { get { return this.description; } set { base.SetValue("Description", value, ref this.description); } } /// /// Gets or sets a value indicating whether or not this page should be displayed on the front page. /// public bool IsFrontPage { get { return this.frontPage; } set { base.SetValue("IsFrontPage", value, ref this.frontPage); } } /// /// Gets a value indicating whether the has child pages. /// /// Does this page have child pages public bool HasChildPages { get { return Pages.Any(p => p.Parent == this.Id); } } /// /// Gets a value indicating whether the has parent page. /// /// Does this page have a parent page? public bool HasParentPage { get { return this.Parent != Guid.Empty; } } /// /// Gets or sets the Keywords or the object. /// public string Keywords { get { return this.keywords; } set { base.SetValue("Keywords", value, ref this.keywords); } } /// /// Gets or sets the parent of the Page. It is used to construct the /// hierachy of the pages. /// public Guid Parent { get { return this.parent; } set { base.SetValue("Parent", value, ref this.parent); } } /// /// Gets or sets a value indicating whether or not this page should be published. /// public bool IsPublished { get { return this.isPublished; } set { base.SetValue("IsPublished", value, ref this.isPublished); } } /// /// Gets or sets a value indicating whether or not this page is deleted. /// public bool IsDeleted { get { return this.isDeleted; } set { base.SetValue("IsDeleted", value, ref this.isDeleted); } } /// /// Gets a relative-to-the-site-root path to the page. /// Only for in-site use. /// public string RelativeLink { get { var theslug = Utils.RemoveIllegalCharacters(this.Slug) + BlogConfig.FileExtension; return string.Format("{0}page/{1}", Utils.RelativeWebRoot, theslug); } } /// /// Returns a relative link if possible if the hostname of this blog instance matches the /// hostname of the site aggregation blog. If the hostname is different, then the /// absolute link is returned. /// public string RelativeOrAbsoluteLink { get { if (this.Blog.DoesHostnameDifferFromSiteAggregationBlog) return this.AbsoluteLink.ToString(); else return this.RelativeLink; } } /// /// Gets or sets a value indicating whether or not this page should be in the sitemap list. /// public bool ShowInList { get { return this.showInList; } set { base.SetValue("ShowInList", value, ref this.showInList); } } /// /// Gets or sets the Slug of the Page. /// A Slug is the relative URL used by the pages. /// public string Slug { get { if (string.IsNullOrEmpty(this.slug)) { return Utils.RemoveIllegalCharacters(this.Title); } return this.slug; } set { base.SetValue("Slug", value, ref this.slug); } } /// /// Gets or sets the Title or the object. /// public string Title { get { return this.title; } set { base.SetValue("Title", value, ref this.title); } } /// /// Gets a value indicating whether or not this page should be shown /// /// public bool IsVisible { get { if (this.isDeleted) return false; else if (this.IsPublished) return true; else if (Security.IsAuthorizedTo(Rights.ViewUnpublishedPages)) return true; return false; } } /// /// Gets a value indicating whether or not this page is visible to visitors not logged into the blog. /// /// public bool IsVisibleToPublic { get { return this.IsPublished && !this.IsDeleted; } } /// /// Gets Author. /// string IPublishable.Author { get { return BlogSettings.Instance.AuthorName; } } /// /// Gets whether or not the current user owns this page. /// /// public override bool CurrentUserOwns { get { // Because we are not storing an author name for each page, // any user that have edit page access is an owner return Security.IsAuthorizedTo(BlogEngine.Core.Rights.EditOwnPages); } } /// /// Gets whether the current user can delete this page. /// /// public override bool CanUserDelete { get { return Security.IsAuthorizedTo(BlogEngine.Core.Rights.EditOwnPages); } } /// /// Gets whether the current user can edit this page. /// /// public override bool CanUserEdit { get { return Security.IsAuthorizedTo(BlogEngine.Core.Rights.EditOwnPages); } } /// /// Gets Categories. /// /// /// /// 10/21/10 /// This was returning null. I'm not sure what the purpose of that is. An IEnumerable should return /// an empty collection rather than null to indicate that there's nothing there. /// /// StateList IPublishable.Categories { get { return this.categories; } } private StateList categories = new StateList(); StateList IPublishable.Tags { get { return tags; } } /// /// The sort order of the page /// public int SortOrder { get { return sortOrder; } set { SetValue("SortOrder", value, ref sortOrder); } } private StateList tags = new StateList(); #endregion #region Public Methods /// /// Gets whether the current user can publish this page. /// /// public bool CanPublish() { return Security.IsAuthorizedTo(BlogEngine.Core.Rights.EditOwnPages); } /// /// Returns the front page if any is available. /// /// The front Page. public static Page GetFrontPage() { return Pages.Find(page => page.IsFrontPage); } /// /// Returns a page based on the specified id. /// /// The page id. /// The Page requested. public static Page GetPage(Guid id) { return Pages.FirstOrDefault(page => page.Id == id); } /// /// Called when [serving]. /// /// The page being served. /// The instance containing the event data. public static void OnServing(Page page, ServingEventArgs arg) { if (Serving != null) { Serving(page, arg); } } /// /// Returns a that represents the current . /// /// /// A that represents the current . /// public override string ToString() { return this.Title; } #endregion #region Implemented Interfaces #region IPublishable /// /// Raises the Serving event /// /// /// The event Args. /// public void OnServing(ServingEventArgs eventArgs) { if (Serving != null) { Serving(this, eventArgs); } } #endregion #endregion #region Methods /// /// Deletes the page from the current BlogProvider. /// protected override void DataDelete() { this.IsDeleted = true; this.DateModified = DateTime.Now; DataUpdate(); Pages.Remove(this); if(!DeletedPages.Contains(this)) DeletedPages.Add(this); } /// /// Deletes the Page from the current BlogProvider. /// public void Purge() { BlogService.DeletePage(this); DeletedPages.Remove(this); } /// /// Restores the deleted page. /// public void Restore() { this.IsDeleted = false; this.DateModified = DateTime.Now; DataUpdate(); DeletedPages.Remove(this); Pages.Add(this); } /// /// Inserts a new page to current BlogProvider. /// protected override void DataInsert() { BlogService.InsertPage(this); if (this.New) { Pages.Add(this); } } /// /// Retrieves a page form the BlogProvider /// based on the specified id. /// /// The page id. /// The Page requested. protected override Page DataSelect(Guid id) { return BlogService.SelectPage(id); } /// /// Updates the object in its data store. /// protected override void DataUpdate() { BlogService.UpdatePage(this); } /// /// Validates the properties on the Page. /// protected override void ValidationRules() { this.AddRule("Title", "Title must be set", string.IsNullOrEmpty(this.Title)); this.AddRule("Content", "Content must be set", string.IsNullOrEmpty(this.Content)); } #endregion } }