PageRenderTime 36ms CodeModel.GetById 20ms app.highlight 11ms RepoModel.GetById 1ms app.codeStats 0ms

/BlogEngine/BlogEngine.NET/App_Code/Controls/CategoryList.cs

#
C# | 269 lines | 165 code | 49 blank | 55 comment | 14 complexity | 755b5bcc06fb84dcdca5c3c2b91f3442 MD5 | raw file
  1// --------------------------------------------------------------------------------------------------------------------
  2// <summary>
  3//   Builds a category list.
  4// </summary>
  5// --------------------------------------------------------------------------------------------------------------------
  6
  7namespace App_Code.Controls
  8{
  9    using System;
 10    using System.Collections.Generic;
 11    using System.IO;
 12    using System.Linq;
 13    using System.Web;
 14    using System.Web.UI;
 15    using System.Web.UI.HtmlControls;
 16
 17    using BlogEngine.Core;
 18
 19    /// <summary>
 20    /// Builds a category list.
 21    /// </summary>
 22    public class CategoryList : Control
 23    {
 24        #region Constants and Fields
 25
 26        /// <summary>
 27        /// The html string.
 28        /// </summary>
 29        private static Dictionary<Guid, string> blogsHtml = new Dictionary<Guid, string>();
 30
 31        /// <summary>
 32        /// The show rss icon.
 33        /// </summary>
 34        private static Dictionary<Guid, bool> blogsShowRssIcon = new Dictionary<Guid, bool>();
 35
 36        /// <summary>
 37        ///     The show post count.
 38        /// </summary>
 39        private bool showPostCount;
 40
 41        #endregion
 42
 43        #region Constructors and Destructors
 44
 45        /// <summary>
 46        ///     Initializes static members of the <see cref = "CategoryList" /> class.
 47        /// </summary>
 48        static CategoryList()
 49        {
 50            Post.Saved += (sender, args) => blogsHtml.Remove(Blog.CurrentInstance.Id);
 51            Category.Saved += (sender, args) => blogsHtml.Remove(Blog.CurrentInstance.Id);
 52        }
 53
 54        #endregion
 55
 56        #region Properties
 57
 58        /// <summary>
 59        ///     Gets or sets a value indicating whether ShowPostCount.
 60        /// </summary>
 61        public bool ShowPostCount
 62        {
 63            get
 64            {
 65                return this.showPostCount;
 66            }
 67
 68            set
 69            {
 70                if (this.showPostCount == value)
 71                {
 72                    return;
 73                }
 74
 75                this.showPostCount = value;
 76                blogsHtml.Remove(Blog.CurrentInstance.Id);
 77            }
 78        }
 79
 80        /// <summary>
 81        ///     Gets or sets a value indicating whether or not to show feed icons next to the category links.
 82        /// </summary>
 83        public bool ShowRssIcon
 84        {
 85            get
 86            {
 87                Guid blogId = Blog.CurrentInstance.Id;
 88
 89                if (!blogsShowRssIcon.ContainsKey(blogId))
 90                    blogsShowRssIcon[blogId] = true;
 91
 92                return blogsShowRssIcon[blogId];
 93            }
 94
 95            set
 96            {
 97                if (ShowRssIcon == value)
 98                {
 99                    return;
100                }
101
102                blogsShowRssIcon[Blog.CurrentInstance.Id] = value;
103                blogsHtml.Remove(Blog.CurrentInstance.Id);
104            }
105        }
106
107        /// <summary>
108        ///     Gets Html.
109        /// </summary>
110        private string Html
111        {
112            get
113            {
114                Guid blogId = Blog.CurrentInstance.Id;
115
116                if (!blogsHtml.ContainsKey(blogId))
117                {
118                    var ul = this.BindCategories();
119                    using (var sw = new StringWriter())
120                    {
121                        using (var hw = new HtmlTextWriter(sw))
122                        {
123                            ul.RenderControl(hw);
124                            blogsHtml[blogId] = sw.ToString();
125                        }
126                    }
127                }
128
129                return blogsHtml[blogId];
130            }
131        }
132
133        #endregion
134
135        #region Public Methods
136
137        /// <summary>
138        /// Outputs server control content to a provided <see cref="T:System.Web.UI.HtmlTextWriter"/> object and stores tracing information about the control if tracing is enabled.
139        /// </summary>
140        /// <param name="writer">
141        /// The <see cref="T:System.Web.UI.HtmlTextWriter"/> object that receives the control content.
142        /// </param>
143        public override void RenderControl(HtmlTextWriter writer)
144        {
145            writer.Write(this.Html);
146            writer.Write(Environment.NewLine);
147        }
148
149        #endregion
150
151        #region Methods
152
153        /// <summary>
154        /// Determines whether the specified category has posts.
155        /// </summary>
156        /// <param name="cat">
157        /// The category.
158        /// </param>
159        /// <returns>
160        /// <c>true</c> if the specified category has posts; otherwise, <c>false</c>.
161        /// </returns>
162        private static bool HasPosts(Category cat)
163        {
164            return
165                Post.Posts.Where(post => post.IsVisible).SelectMany(post => post.Categories).Any(
166                    category => category == cat);
167        }
168
169        /// <summary>
170        /// Sorts the categories.
171        /// </summary>
172        /// <returns>
173        /// The sorted categories.
174        /// </returns>
175        private static SortedDictionary<string, Guid> SortCategories()
176        {
177            var dic = new SortedDictionary<string, Guid>();
178            foreach (var cat in Category.Categories.Where(HasPosts))
179            {
180                dic.Add(cat.CompleteTitle(), cat.Id);
181            }
182
183            return dic;
184        }
185
186        /// <summary>
187        /// Binds the categories.
188        /// </summary>
189        /// <returns>A category control.</returns>
190        private HtmlGenericControl BindCategories()
191        {
192            var dic = SortCategories();
193
194            if (dic.Keys.Count == 0)
195            {
196                var none = new HtmlGenericControl("p") { InnerText = "None" };
197                return none;
198            }
199
200            var ul = new HtmlGenericControl("ul") { ID = "categorylist" };
201
202            foreach (var id in dic.Values)
203            {
204                // Find full category
205                var cat = Category.GetCategory(id);
206                var key = cat.CompleteTitle();
207
208                var li = new HtmlGenericControl("li");
209
210                int i = cat.CompleteTitle().Count(c => c == '-');
211
212                string spaces = string.Empty;
213
214                for (int j = 0; j < i; j++)
215                {
216                    spaces += "&#160;&#160;&#160";
217                }
218
219                if (i > 0)
220                {
221                    var textArea = new HtmlAnchor();
222                    textArea.InnerHtml = spaces;
223                    li.Controls.Add(textArea);
224                }
225
226                if (this.ShowRssIcon)
227                {
228                    var img = new HtmlImage
229                        {
230                            Src = string.Format("{0}pics/rssButton.png", Utils.RelativeWebRoot),
231                            Alt =
232                                string.Format(
233                                    "{0} feed for {1}", BlogSettings.Instance.SyndicationFormat.ToUpperInvariant(), key)
234                        };
235                    img.Attributes["class"] = "rssButton";
236
237                    var feedAnchor = new HtmlAnchor { HRef = cat.FeedRelativeLink };
238                    feedAnchor.Attributes["rel"] = "nofollow";
239                    feedAnchor.Controls.Add(img);
240
241                    li.Controls.Add(feedAnchor);
242                }
243
244                var posts = Post.GetPostsByCategory(dic[key]).FindAll(p => p.IsVisible).Count;
245
246                var postCount = string.Format(" ({0})", posts);
247                if (!this.ShowPostCount)
248                {
249                    postCount = null;
250                }
251
252                var anc = new HtmlAnchor
253                    {
254                        HRef = cat.RelativeLink,
255                        InnerHtml = HttpUtility.HtmlEncode(cat.Title) + postCount,
256                        Title = string.Format("Categorie: {0}", key)
257                    };
258                
259
260                li.Controls.Add(anc);
261                ul.Controls.Add(li);
262            }
263
264            return ul;
265        }
266
267        #endregion
268    }
269}