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
}
}