PageRenderTime 95ms CodeModel.GetById 30ms RepoModel.GetById 1ms app.codeStats 0ms

/SadPanda.ProgrammingBlog.UI/widgets/Most comments/widget.ascx.cs

https://github.com/digitalpacman/SadPanda
C# | 345 lines | 199 code | 55 blank | 91 comment | 19 complexity | 12d060271f1f97a8ddc7a37f19b6a782 MD5 | raw file
  1. // --------------------------------------------------------------------------------------------------------------------
  2. // <summary>
  3. // The most comments widget.
  4. // </summary>
  5. // --------------------------------------------------------------------------------------------------------------------
  6. namespace Widgets.MostComments
  7. {
  8. using System;
  9. using System.Collections.Generic;
  10. using System.Globalization;
  11. using System.Linq;
  12. using System.Web;
  13. using System.Web.UI.WebControls;
  14. using App_Code.Controls;
  15. using BlogEngine.Core;
  16. using Resources;
  17. /// <summary>
  18. /// The visitor.
  19. /// </summary>
  20. public struct Visitor
  21. {
  22. #region Constants and Fields
  23. /// <summary>
  24. /// The comments.
  25. /// </summary>
  26. public int Comments;
  27. /// <summary>
  28. /// The country.
  29. /// </summary>
  30. public string Country;
  31. /// <summary>
  32. /// The email.
  33. /// </summary>
  34. public string Email;
  35. /// <summary>
  36. /// The visitor name.
  37. /// </summary>
  38. public string Name;
  39. /// <summary>
  40. /// The website.
  41. /// </summary>
  42. public Uri Website;
  43. #endregion
  44. }
  45. /// <summary>
  46. /// The most comments widget.
  47. /// </summary>
  48. public partial class Widget : WidgetBase
  49. {
  50. #region Constants and Fields
  51. /// <summary>
  52. /// The avatar size.
  53. /// </summary>
  54. private int avatarSize = 50;
  55. /// <summary>
  56. /// The 60 days.
  57. /// </summary>
  58. private int days = 60;
  59. /// <summary>
  60. /// The number of visitors.
  61. /// </summary>
  62. private int numberOfVisitors = 3;
  63. /// <summary>
  64. /// The show comments.
  65. /// </summary>
  66. private bool showComments = true;
  67. #endregion
  68. #region Constructors and Destructors
  69. /// <summary>
  70. /// Initializes static members of the <see cref = "Widget" /> class.
  71. /// </summary>
  72. static Widget()
  73. {
  74. Post.CommentAdded += (sender, args) => Blog.CurrentInstance.Cache.Remove("most_comments");
  75. }
  76. #endregion
  77. #region Properties
  78. /// <summary>
  79. /// Gets whether the widget can be edited.
  80. /// <remarks>
  81. /// The only way a widget can be editable is by adding a edit.ascx file to the widget folder.
  82. /// </remarks>
  83. /// </summary>
  84. public override bool IsEditable
  85. {
  86. get
  87. {
  88. return true;
  89. }
  90. }
  91. /// <summary>
  92. /// Gets the name. It must be exactly the same as the folder that contains the widget.
  93. /// </summary>
  94. public override string Name
  95. {
  96. get
  97. {
  98. return "Most comments";
  99. }
  100. }
  101. #endregion
  102. #region Public Methods
  103. /// <summary>
  104. /// This method works as a substitute for Page_Load. You should use this method for
  105. /// data binding etc. instead of Page_Load.
  106. /// </summary>
  107. public override void LoadWidget()
  108. {
  109. this.LoadSettings();
  110. if (Blog.CurrentInstance.Cache["most_comments"] == null)
  111. {
  112. this.BuildList();
  113. }
  114. var visitors = (List<Visitor>)Blog.CurrentInstance.Cache["most_comments"];
  115. this.rep.ItemDataBound += this.RepItemDataBound;
  116. this.rep.DataSource = visitors;
  117. this.rep.DataBind();
  118. }
  119. #endregion
  120. #region Methods
  121. /// <summary>
  122. /// Finds the visitor.
  123. /// </summary>
  124. /// <param name="email">
  125. /// The email.
  126. /// </param>
  127. /// <param name="comments">
  128. /// The comments.
  129. /// </param>
  130. /// <returns>
  131. /// The Visitor.
  132. /// </returns>
  133. private static Visitor FindVisitor(string email, int comments)
  134. {
  135. foreach (var visitor in from post in Post.Posts
  136. from comment in post.ApprovedComments
  137. where comment.Email == email
  138. select
  139. new Visitor
  140. {
  141. Name = comment.Author,
  142. Country = comment.Country,
  143. Website = comment.Website,
  144. Comments = comments,
  145. Email = email
  146. })
  147. {
  148. return visitor;
  149. }
  150. return new Visitor();
  151. }
  152. /// <summary>
  153. /// Sorts the dictionary.
  154. /// </summary>
  155. /// <param name="dic">
  156. /// The dictionary.
  157. /// </param>
  158. /// <returns>
  159. /// The sorted dictionary.
  160. /// </returns>
  161. private static Dictionary<string, int> SortDictionary(Dictionary<string, int> dic)
  162. {
  163. var list = dic.Keys.Select(key => new KeyValuePair<string, int>(key, dic[key])).ToList();
  164. list.Sort((obj1, obj2) => obj2.Value.CompareTo(obj1.Value));
  165. return list.ToDictionary(pair => pair.Key, pair => pair.Value);
  166. }
  167. /// <summary>
  168. /// Builds the list.
  169. /// </summary>
  170. private void BuildList()
  171. {
  172. var visitors = new Dictionary<string, int>();
  173. foreach (var comment in from post in Post.Posts
  174. from comment in post.ApprovedComments
  175. where
  176. (comment.DateCreated.AddDays(this.days) >= DateTime.Now &&
  177. !string.IsNullOrEmpty(comment.Email)) && comment.Email.Contains("@")
  178. where !post.Author.Equals(comment.Author, StringComparison.OrdinalIgnoreCase)
  179. select comment)
  180. {
  181. if (visitors.ContainsKey(comment.Email))
  182. {
  183. visitors[comment.Email] += 1;
  184. }
  185. else
  186. {
  187. visitors.Add(comment.Email, 1);
  188. }
  189. }
  190. visitors = SortDictionary(visitors);
  191. // var max = Math.Min(visitors.Count, this.numberOfVisitors);
  192. var count = 0;
  193. var list = new List<Visitor>();
  194. foreach (var v in visitors.Keys.Select(key => FindVisitor(key, visitors[key])))
  195. {
  196. list.Add(v);
  197. count++;
  198. if (count == this.numberOfVisitors)
  199. {
  200. break;
  201. }
  202. }
  203. Blog.CurrentInstance.Cache.Insert("most_comments", list);
  204. }
  205. /// <summary>
  206. /// The load settings.
  207. /// </summary>
  208. private void LoadSettings()
  209. {
  210. var settings = this.GetSettings();
  211. try
  212. {
  213. if (settings.ContainsKey("avatarsize"))
  214. {
  215. this.avatarSize = int.Parse(settings["avatarsize"]);
  216. }
  217. if (settings.ContainsKey("numberofvisitors"))
  218. {
  219. this.numberOfVisitors = int.Parse(settings["numberofvisitors"]);
  220. }
  221. if (settings.ContainsKey("days"))
  222. {
  223. this.days = int.Parse(settings["days"]);
  224. }
  225. if (settings.ContainsKey("showcomments"))
  226. {
  227. this.showComments = settings["showcomments"].Equals("true", StringComparison.OrdinalIgnoreCase);
  228. }
  229. }
  230. catch
  231. {
  232. }
  233. }
  234. /// <summary>
  235. /// Handles the ItemDataBound event of the rep control.
  236. /// </summary>
  237. /// <param name="sender">
  238. /// The source of the event.
  239. /// </param>
  240. /// <param name="e">
  241. /// The <see cref="System.Web.UI.WebControls.RepeaterItemEventArgs"/> instance containing the event data.
  242. /// </param>
  243. private void RepItemDataBound(object sender, RepeaterItemEventArgs e)
  244. {
  245. if (e.Item.ItemType != ListItemType.Item && e.Item.ItemType != ListItemType.AlternatingItem)
  246. {
  247. return;
  248. }
  249. var visitor = (Visitor)e.Item.DataItem;
  250. var imgAvatar = (Image)e.Item.FindControl("imgAvatar");
  251. var imgCountry = (Image)e.Item.FindControl("imgCountry");
  252. var name = (Literal)e.Item.FindControl("litName");
  253. var number = (Literal)e.Item.FindControl("litNumber");
  254. var litCountry = (Literal)e.Item.FindControl("litCountry");
  255. imgAvatar.ImageUrl = Avatar.GetAvatar(this.avatarSize, visitor.Email, null, null, null).Url.ToString();
  256. imgAvatar.AlternateText = visitor.Name;
  257. imgAvatar.Width = Unit.Pixel(this.avatarSize);
  258. if (this.showComments)
  259. {
  260. number.Text = string.Format("{0} {1}<br />", visitor.Comments, labels.comments.ToLowerInvariant());
  261. }
  262. if (visitor.Website != null)
  263. {
  264. const string LinkFormat = "<a rel=\"nofollow contact\" class=\"url fn\" href=\"{0}\">{1}</a>";
  265. name.Text = string.Format(LinkFormat, visitor.Website, visitor.Name);
  266. }
  267. else
  268. {
  269. name.Text = string.Format("<span class=\"fn\">{0}</span>", visitor.Name);
  270. }
  271. if (!string.IsNullOrEmpty(visitor.Country))
  272. {
  273. imgCountry.ImageUrl = string.Format("{0}pics/flags/{1}.png", Utils.RelativeWebRoot, visitor.Country);
  274. imgCountry.AlternateText = visitor.Country;
  275. foreach (var ri in
  276. CultureInfo.GetCultures(CultureTypes.SpecificCultures).Select(ci => new RegionInfo(ci.Name)).Where(
  277. ri => ri.TwoLetterISORegionName.Equals(visitor.Country, StringComparison.OrdinalIgnoreCase)))
  278. {
  279. litCountry.Text = ri.DisplayName;
  280. break;
  281. }
  282. }
  283. else
  284. {
  285. imgCountry.Visible = false;
  286. }
  287. }
  288. #endregion
  289. }
  290. }