PageRenderTime 75ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/BlogEngine/DotNetSlave.BusinessLogic/Category.cs

#
C# | 388 lines | 210 code | 52 blank | 126 comment | 23 complexity | 3c7cbcb3f2b7d4d163ba76bd6a40d79d MD5 | raw file
Possible License(s): LGPL-2.1, Apache-2.0, BSD-3-Clause
  1. namespace BlogEngine.Core
  2. {
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using System.Web;
  7. using BlogEngine.Core.Providers;
  8. /// <summary>
  9. /// Categories are a way to organize posts.
  10. /// A post can be in multiple categories.
  11. /// </summary>
  12. [Serializable]
  13. public class Category : BusinessBase<Category, Guid>, IComparable<Category>
  14. {
  15. #region Constants and Fields
  16. /// <summary>
  17. /// The sync root.
  18. /// </summary>
  19. private static readonly object SyncRoot = new object();
  20. /// <summary>
  21. /// The categories.
  22. /// </summary>
  23. private static Dictionary<Guid, List<Category>> categories;
  24. /// <summary>
  25. /// The description.
  26. /// </summary>
  27. private string description;
  28. /// <summary>
  29. /// The parent.
  30. /// </summary>
  31. private Guid? parent;
  32. /// <summary>
  33. /// The title.
  34. /// </summary>
  35. private string title;
  36. #endregion
  37. #region Constructors and Destructors
  38. /// <summary>
  39. /// Initializes static members of the <see cref="Category"/> class.
  40. /// </summary>
  41. static Category()
  42. {
  43. Blog.Saved += (s, e) =>
  44. {
  45. if (e.Action == SaveAction.Delete)
  46. {
  47. Blog blog = s as Blog;
  48. if (blog != null)
  49. {
  50. // remove deleted blog from static 'categories'
  51. if (categories != null && categories.ContainsKey(blog.Id))
  52. categories.Remove(blog.Id);
  53. }
  54. }
  55. };
  56. }
  57. /// <summary>
  58. /// Initializes a new instance of the <see cref = "Category" /> class.
  59. /// </summary>
  60. public Category()
  61. {
  62. this.Id = Guid.NewGuid();
  63. }
  64. /// <summary>
  65. /// Initializes a new instance of the <see cref="Category"/> class.
  66. /// The category.
  67. /// </summary>
  68. /// <param name="title">
  69. /// The title.
  70. /// </param>
  71. /// <param name="description">
  72. /// The description.
  73. /// </param>
  74. public Category(string title, string description)
  75. {
  76. this.Id = Guid.NewGuid();
  77. this.title = title;
  78. this.description = description;
  79. this.Parent = null;
  80. }
  81. #endregion
  82. #region Properties
  83. /// <summary>
  84. /// Gets an unsorted list of all Categories.
  85. /// </summary>
  86. /// <value>The categories.</value>
  87. public static List<Category> Categories
  88. {
  89. get
  90. {
  91. Blog blog = Blog.CurrentInstance;
  92. if (categories == null || !categories.ContainsKey(blog.Id))
  93. {
  94. lock (SyncRoot)
  95. {
  96. if (categories == null || !categories.ContainsKey(blog.Id))
  97. {
  98. if (categories == null)
  99. categories = new Dictionary<Guid, List<Category>>();
  100. categories[blog.Id] = BlogService.FillCategories();
  101. categories[blog.Id].Sort();
  102. }
  103. }
  104. }
  105. return categories[blog.Id];
  106. }
  107. }
  108. /// <summary>
  109. /// Gets the absolute link to the page displaying all posts for this category.
  110. /// </summary>
  111. /// <value>The absolute link.</value>
  112. public Uri AbsoluteLink
  113. {
  114. get
  115. {
  116. return Utils.ConvertToAbsolute(this.RelativeLink);
  117. }
  118. }
  119. /// <summary>
  120. /// Gets or sets the Description of the object.
  121. /// </summary>
  122. /// <value>The description.</value>
  123. public string Description
  124. {
  125. get
  126. {
  127. return this.description;
  128. }
  129. set
  130. {
  131. base.SetValue("Description", value, ref this.description);
  132. }
  133. }
  134. /// <summary>
  135. /// Gets the absolute link to the feed for this category's posts.
  136. /// </summary>
  137. /// <value>The feed absolute link.</value>
  138. public Uri FeedAbsoluteLink
  139. {
  140. get
  141. {
  142. return Utils.ConvertToAbsolute(this.FeedRelativeLink);
  143. }
  144. }
  145. /// <summary>
  146. /// Gets the relative link to the feed for this category's posts.
  147. /// </summary>
  148. /// <value>The feed relative link.</value>
  149. public string FeedRelativeLink
  150. {
  151. get
  152. {
  153. return string.Format(
  154. "{0}category/feed/{1}{2}",
  155. Utils.RelativeWebRoot,
  156. Utils.RemoveIllegalCharacters(this.Title),
  157. BlogConfig.FileExtension);
  158. }
  159. }
  160. /// <summary>
  161. /// Gets or sets the Parent ID of the object
  162. /// </summary>
  163. /// <value>The parent.</value>
  164. public Guid? Parent
  165. {
  166. get
  167. {
  168. return this.parent;
  169. }
  170. set
  171. {
  172. base.SetValue("Parent", value, ref this.parent);
  173. }
  174. }
  175. /// <summary>
  176. /// Gets all posts in this category.
  177. /// </summary>
  178. /// <value>The posts.</value>
  179. public List<Post> Posts
  180. {
  181. get
  182. {
  183. return Post.GetPostsByCategory(this.Id);
  184. }
  185. }
  186. /// <summary>
  187. /// Gets the relative link to the page displaying all posts for this category.
  188. /// </summary>
  189. /// <value>The relative link.</value>
  190. public string RelativeLink
  191. {
  192. get
  193. {
  194. return Utils.RelativeWebRoot + "category/" + Utils.RemoveIllegalCharacters(this.Title) +
  195. BlogConfig.FileExtension;
  196. }
  197. }
  198. /// <summary>
  199. /// Gets or sets the Title or the object.
  200. /// </summary>
  201. /// <value>The title.</value>
  202. public string Title
  203. {
  204. get
  205. {
  206. return this.title;
  207. }
  208. set
  209. {
  210. base.SetValue("Title", value, ref this.title);
  211. }
  212. }
  213. #endregion
  214. #region Public Methods
  215. /// <summary>
  216. /// Returns a category based on the specified id.
  217. /// </summary>
  218. /// <param name="id">
  219. /// The category id.
  220. /// </param>
  221. /// <returns>
  222. /// The category.
  223. /// </returns>
  224. public static Category GetCategory(Guid id)
  225. {
  226. return Categories.FirstOrDefault(category => category.Id == id);
  227. }
  228. /// <summary>
  229. /// Gets the full title with Parent names included
  230. /// </summary>
  231. /// <returns>
  232. /// The complete title.
  233. /// </returns>
  234. public string CompleteTitle()
  235. {
  236. return this.parent == null
  237. ? this.title
  238. : string.Format("{0} - {1}", GetCategory((Guid)this.parent).CompleteTitle(), this.title);
  239. }
  240. /// <summary>
  241. /// Returns a <see cref="T:System.String"></see> that represents the current <see cref="T:System.Object"></see>.
  242. /// </summary>
  243. /// <returns>
  244. /// A <see cref="T:System.String"></see> that represents the current <see cref="T:System.Object"></see>.
  245. /// </returns>
  246. public override string ToString()
  247. {
  248. return this.CompleteTitle();
  249. }
  250. #endregion
  251. #region Implemented Interfaces
  252. #region IComparable<Category>
  253. /// <summary>
  254. /// Compares the current object with another object of the same type.
  255. /// </summary>
  256. /// <param name="other">
  257. /// An object to compare with this object.
  258. /// </param>
  259. /// <returns>
  260. /// A 32-bit signed integer that indicates the relative order of the objects being compared.
  261. /// The return value has the following meanings: Value Meaning Less than zero This object is
  262. /// less than the other parameter.Zero This object is equal to other. Greater than zero This object is greater than other.
  263. /// </returns>
  264. public int CompareTo(Category other)
  265. {
  266. return this.CompleteTitle().CompareTo(other.CompleteTitle());
  267. }
  268. #endregion
  269. #endregion
  270. #region Methods
  271. /// <summary>
  272. /// Deletes the object from the data store.
  273. /// </summary>
  274. protected override void DataDelete()
  275. {
  276. if (this.Deleted)
  277. {
  278. foreach (var c in
  279. Categories.ToArray().Where(
  280. c => !c.Id.Equals(this.Id) && c.Parent.HasValue && c.Parent.Value.Equals(this.Id)))
  281. {
  282. c.Parent = null;
  283. c.Save();
  284. }
  285. BlogService.DeleteCategory(this);
  286. }
  287. if (Categories.Contains(this))
  288. {
  289. Categories.Remove(this);
  290. }
  291. this.Dispose();
  292. }
  293. /// <summary>
  294. /// Inserts a new object to the data store.
  295. /// </summary>
  296. protected override void DataInsert()
  297. {
  298. if (this.New)
  299. {
  300. BlogService.InsertCategory(this);
  301. }
  302. }
  303. /// <summary>
  304. /// Retrieves the object from the data store and populates it.
  305. /// </summary>
  306. /// <param name="id">
  307. /// The unique identifier of the object.
  308. /// </param>
  309. /// <returns>
  310. /// True if the object exists and is being populated successfully
  311. /// </returns>
  312. protected override Category DataSelect(Guid id)
  313. {
  314. return BlogService.SelectCategory(id);
  315. }
  316. /// <summary>
  317. /// Updates the object in its data store.
  318. /// </summary>
  319. protected override void DataUpdate()
  320. {
  321. if (this.IsChanged)
  322. {
  323. BlogService.UpdateCategory(this);
  324. }
  325. }
  326. /// <summary>
  327. /// Reinforces the business rules by adding additional rules to the
  328. /// broken rules collection.
  329. /// </summary>
  330. protected override void ValidationRules()
  331. {
  332. this.AddRule("Title", "Title must be set", string.IsNullOrEmpty(this.Title));
  333. }
  334. #endregion
  335. }
  336. }