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