diff --git a/app/controllers/PostsController.asp b/app/controllers/PostsController.asp
index c02aea2..2b43df4 100644
--- a/app/controllers/PostsController.asp
+++ b/app/controllers/PostsController.asp
@@ -38,66 +38,173 @@ Class PostsController_Class
' Action: Index
'---------------------------------------------------------------
Public Sub Index()
- ' TODO: Implement Index action
- Response.Write "Index action called"
+ Dim posts
+ Set posts = PostsRepository().FindAllWhere("IsPublished = 1", "PublishedDate DESC", 0, 20)
+ %>
+
+ <%
End Sub
'---------------------------------------------------------------
' Action: Show
'---------------------------------------------------------------
- Public Sub Show(slug)
- ' TODO: Implement Show action
- Response.Write "Show called "
- Response.Write "Parameters: "
- Response.Write "slug = " & Server.HTMLEncode(CStr(slug)) & " "
+ Public Sub Show(ByVal slug)
+ Dim matches
+ Set matches = PostsRepository().Find(Array("Slug", slug, "IsPublished", 1), Empty)
+
+ If matches.Count = 0 Then
+ Response.Status = "404 Not Found"
+ %>
+
+ <%
+ Exit Sub
+ End If
+
+ Dim post
+ Set post = matches.Front()
+ %>
+
+ <%
End Sub
'---------------------------------------------------------------
' Action: New
'---------------------------------------------------------------
Public Sub NewForm()
- ' TODO: Implement NewForm action
- Response.Write "NewForm action called"
+ %>
+
+ <%
End Sub
'---------------------------------------------------------------
' Action: Create
'---------------------------------------------------------------
Public Sub Create()
- ' TODO: Implement Create action
- Response.Write "Create action called"
+ Dim title : title = Trim(Request.Form("Title"))
+ If Len(title) = 0 Then
+ Flash().AddError "Title is required."
+ Response.Redirect "/posts/new"
+ Exit Sub
+ End If
+
+ Dim post
+ Set post = New POBO_Posts
+
+ post.Title = title
+ post.Summary = Request.Form("Summary")
+ post.Body = Request.Form("Body")
+ post.CategoryID = FormNumberOrZero(Request.Form("CategoryID"))
+ post.Slug = BuildSlug(title)
+ post.CreatedDate = Now()
+ post.UpdatedDate = Now()
+ post.IsPublished = 0
+
+ PostsRepository().AddNew post
+ Flash().Success = "Post created."
+ Response.Redirect "/posts"
End Sub
'---------------------------------------------------------------
' Action: Edit
'---------------------------------------------------------------
- Public Sub Edit(id)
- ' TODO: Implement Edit action
- Response.Write "Edit called "
- Response.Write "Parameters: "
- Response.Write "id = " & Server.HTMLEncode(CStr(id)) & " "
+ Public Sub Edit(ByVal id)
+ Dim post
+ On Error Resume Next
+ Set post = PostsRepository().FindByID(id)
+ If Err.Number <> 0 Then
+ Err.Clear
+ On Error GoTo 0
+ Response.Status = "404 Not Found"
+ %>
+
+ <%
+ Exit Sub
+ End If
+ On Error GoTo 0
+ %>
+
+ <%
End Sub
'---------------------------------------------------------------
' Action: Update
'---------------------------------------------------------------
- Public Sub Update(id)
- ' TODO: Implement Update action
- Response.Write "Update called "
- Response.Write "Parameters: "
- Response.Write "id = " & Server.HTMLEncode(CStr(id)) & " "
+ Public Sub Update(ByVal id)
+ Dim post
+ On Error Resume Next
+ Set post = PostsRepository().FindByID(id)
+ If Err.Number <> 0 Then
+ Err.Clear
+ On Error GoTo 0
+ Response.Status = "404 Not Found"
+ %>
+
+ <%
+ Exit Sub
+ End If
+ On Error GoTo 0
+
+ Dim title : title = Trim(Request.Form("Title"))
+ If Len(title) = 0 Then
+ Flash().AddError "Title is required."
+ Response.Redirect "/posts/" & Server.URLEncode(CStr(id)) & "/edit"
+ Exit Sub
+ End If
+
+ post.Title = title
+ post.Summary = Request.Form("Summary")
+ post.Body = Request.Form("Body")
+ post.CategoryID = FormNumberOrZero(Request.Form("CategoryID"))
+ post.Slug = BuildSlug(title)
+ post.UpdatedDate = Now()
+
+ PostsRepository().Update post
+ Flash().Success = "Post updated."
+ Response.Redirect "/posts"
End Sub
'---------------------------------------------------------------
' Action: Delete
'---------------------------------------------------------------
- Public Sub Delete(id)
- ' TODO: Implement Delete action
- Response.Write "Delete called "
- Response.Write "Parameters: "
- Response.Write "id = " & Server.HTMLEncode(CStr(id)) & " "
+ Public Sub Delete(ByVal id)
+ PostsRepository().Delete id
+ Flash().Success = "Post deleted."
+ Response.Redirect "/posts"
End Sub
+ Private Function FormNumberOrZero(ByVal value)
+ If IsNumeric(value) Then
+ FormNumberOrZero = CLng(value)
+ Else
+ FormNumberOrZero = 0
+ End If
+ End Function
+
+ Private Function BuildSlug(ByVal value)
+ Dim raw : raw = LCase(Trim(CStr(value)))
+ Dim i, ch, slug, previousDash
+ slug = ""
+ previousDash = False
+
+ For i = 1 To Len(raw)
+ ch = Mid(raw, i, 1)
+ If (ch >= "a" And ch <= "z") Or (ch >= "0" And ch <= "9") Then
+ slug = slug & ch
+ previousDash = False
+ ElseIf Not previousDash And Len(slug) > 0 Then
+ slug = slug & "-"
+ previousDash = True
+ End If
+ Next
+
+ Do While Right(slug, 1) = "-"
+ slug = Left(slug, Len(slug) - 1)
+ Loop
+
+ If Len(slug) = 0 Then slug = "post"
+ BuildSlug = slug
+ End Function
+
End Class
' Singleton instance
diff --git a/app/repositories/PostsRepository.asp b/app/repositories/PostsRepository.asp
index 3a50e60..db44fdb 100644
--- a/app/repositories/PostsRepository.asp
+++ b/app/repositories/PostsRepository.asp
@@ -27,6 +27,54 @@ Class PostsRepository_Class
Set GetAll = Find(Empty, orderBy)
End Function
+ Public Function FindAllWhere(ByVal where_clause, ByVal order_by, ByVal offset, ByVal limit)
+ Dim sql : sql = "Select [Body], [CategoryID], [CreatedDate], [IsPublished], [PostID], [PublishedDate], [Slug], [Summary], [Title], [UpdatedDate] FROM [Posts]"
+ Dim whereText : whereText = ""
+ If Not IsEmpty(where_clause) Then
+ If Not IsNull(where_clause) Then whereText = Trim(CStr(where_clause))
+ End If
+
+ If Len(whereText) > 0 Then
+ sql = sql & " WHERE " & whereText
+ End If
+ sql = sql & BuildOrderBy(order_by, "[PostID]")
+
+ Dim offsetCount, limitCount
+ If IsNumeric(offset) Then
+ offsetCount = CLng(offset)
+ Else
+ offsetCount = 0
+ End If
+ If offsetCount < 0 Then offsetCount = 0
+
+ If IsNumeric(limit) Then
+ limitCount = CLng(limit)
+ Else
+ limitCount = 0
+ End If
+
+ Dim rs : Set rs = DAL.Query(sql, Empty)
+ Dim list : Set list = new LinkedList_Class
+ Dim skipped, added
+ skipped = 0
+ added = 0
+
+ Do Until rs.EOF
+ If skipped < offsetCount Then
+ skipped = skipped + 1
+ ElseIf limitCount <= 0 Or added < limitCount Then
+ list.Push Automapper.AutoMap(rs, "POBO_Posts")
+ added = added + 1
+ End If
+
+ If limitCount > 0 And added >= limitCount Then Exit Do
+ rs.MoveNext
+ Loop
+
+ Set FindAllWhere = list
+ Destroy rs
+ End Function
+
Public Function Find(where_kvarray, order_string_or_array)
Dim sql : sql = "Select [Body], [CategoryID], [CreatedDate], [IsPublished], [PostID], [PublishedDate], [Slug], [Summary], [Title], [UpdatedDate] FROM [Posts]"
Dim where_keys, where_values, i
@@ -149,21 +197,65 @@ Class PostsRepository_Class
QI = "[" & Replace(CStr(name), "]", "]]") & "]"
End Function
- Private Function BuildOrderBy(orderArg, defaultCol)
+ Private Function BuildOrderBy(ByVal orderArg, ByVal defaultCol)
Dim s : s = ""
- If IsEmpty(orderArg) Or IsNull(orderArg) Or orderArg = "" Then
- s = " ORDER BY " & defaultCol & " ASC"
- ElseIf IsArray(orderArg) Then
+ If IsArray(orderArg) Then
Dim i : s = " ORDER BY "
For i = 0 To UBound(orderArg)
If i > 0 Then s = s & ", "
s = s & QI(orderArg(i))
Next
+ ElseIf IsEmpty(orderArg) Then
+ s = " ORDER BY " & defaultCol & " ASC"
+ ElseIf IsNull(orderArg) Then
+ s = " ORDER BY " & defaultCol & " ASC"
+ ElseIf CStr(orderArg) = "" Then
+ s = " ORDER BY " & defaultCol & " ASC"
+ ElseIf IsSafeOrderExpression(orderArg) Then
+ Dim parts : parts = Split(Trim(CStr(orderArg)), " ")
+ s = " ORDER BY " & QI(parts(0))
+ If UBound(parts) = 1 Then s = s & " " & UCase(parts(1))
Else
s = " ORDER BY " & QI(orderArg)
End If
BuildOrderBy = s
End Function
+
+ Private Function IsSafeOrderExpression(ByVal orderArg)
+ Dim raw : raw = Trim(CStr(orderArg))
+ Dim parts : parts = Split(raw, " ")
+
+ IsSafeOrderExpression = False
+ If UBound(parts) < 0 Or UBound(parts) > 1 Then Exit Function
+ If Not IsSafeIdentifier(parts(0)) Then Exit Function
+ If UBound(parts) = 1 Then
+ If UCase(parts(1)) <> "ASC" And UCase(parts(1)) <> "DESC" Then Exit Function
+ End If
+
+ IsSafeOrderExpression = True
+ End Function
+
+ Private Function IsSafeIdentifier(ByVal value)
+ Dim i, ch
+ value = CStr(value)
+ If Len(value) = 0 Then
+ IsSafeIdentifier = False
+ Exit Function
+ End If
+
+ For i = 1 To Len(value)
+ ch = Mid(value, i, 1)
+ If Not ((ch >= "a" And ch <= "z") Or _
+ (ch >= "A" And ch <= "Z") Or _
+ (ch >= "0" And ch <= "9") Or _
+ ch = "_") Then
+ IsSafeIdentifier = False
+ Exit Function
+ End If
+ Next
+
+ IsSafeIdentifier = True
+ End Function
End Class
Dim PostsRepository__Singleton
diff --git a/app/views/Posts/edit.asp b/app/views/Posts/edit.asp
new file mode 100644
index 0000000..3b0894a
--- /dev/null
+++ b/app/views/Posts/edit.asp
@@ -0,0 +1,40 @@
+
+
+
+
+
Edit Post
+
+
+
+
+
+
+
+
diff --git a/app/views/Posts/index.asp b/app/views/Posts/index.asp
new file mode 100644
index 0000000..6464283
--- /dev/null
+++ b/app/views/Posts/index.asp
@@ -0,0 +1,62 @@
+
+ <%
+ Dim publishedText
+ publishedText = ""
+ If IsDate(postItem.PublishedDate) Then
+ If CDate(postItem.PublishedDate) > #1/1/1970# Then
+ publishedText = FormatDateTime(postItem.PublishedDate, vbLongDate)
+ End If
+ End If
+
+ If Len(publishedText) > 0 Then
+ %>
+ <%= H(publishedText) %>
+ <%
+ End If
+ %>
+
+
+ <%
+ Dim publishedText
+ publishedText = ""
+ If IsDate(post.PublishedDate) Then
+ If CDate(post.PublishedDate) > #1/1/1970# Then
+ publishedText = FormatDateTime(post.PublishedDate, vbLongDate)
+ End If
+ End If
+
+ If Len(publishedText) > 0 Then
+ %>
+