The view.ucw page is used for viewing the contents of a wiki page. The user specifies which page they're insterested in using the "page-name" HTTP request parameter. If no page-name is specified we default to "WelcomePage," if the specified page-name does not exist we assume the user wants to edit (in this case create) the page.
(defentry-point "view.ucw" (:application *example-application*) ((page-name "WelcomePage")) (if (find-wiki-page page-name) (call 'view-wiki-page :page-name page-name) (call 'redirect-component :target (strcat "edit.ucw?page-name=" page-name))))
DEFENTRY-POINT is UCW's way of associating a piece of code to a particular url, it's analogous to handlers or servlet definitions in other frameworks.
In this case we are creating an entry-point named "view.ucw" and tying it to the example-app application. The entry-point takes one parameter: page-name. If the page-name parameter is not passed in the request we will use "WelcomePage."
This entry-point is very simple, if the requested wiki-page exists then we should just view it using the page (aka component) view-wiki-page, if the requested page doesn't exist then we'll just pretend that the user actually wants to edit the page.
What is the "effective" url for this entry point? Since example-app application's url-prefix is "/ucw/examples/" we simply concatentate the entry-point's name and the url-prefix to get "/ucw/examples/view.ucw". The extension needn't be ".ucw" it can be anything you want or nothing at all. When using the araneida or aserve backends the entry-point's url is automatically registered with the server, with the mod_lisp backend you must manually configure apache to send requests for this entry point to ucw.
How do we tell UCW to show the user some html? While we could just litter our entry-point with (progn (write-line "<html>") ...) we're not going to, it's bad style and UCW is makes that more difficult than it could be.
What we're supposed to do is hand off our request to a component and let it deal with the nitty gritty html stuff. Here's the form which defines the view-wiki-page component:
(defcomponent view-wiki-page (window-component template-component) ((page-name :accessor page-name :initarg :page-name)) (:default-initargs :template-name "ucw/examples/view.tal"))
(defmethod template-component-environment nconc ((page view-wiki-page)) (tal-env 'contents (cl-ppcre:regex-replace-all "([A-Z][a-z]+){2,}" (contents (find-wiki-page (page-name page))) "<a href=\"view.ucw?page-name=\\&\">\\&</a>")))
Notice how much the defcomponent macro looks like defclass, that's not accidental. view-wiki-page now names a class of components. The (call 'view-wiki-page ...) form in our view.ucw entry-point is little more than a call to make-instance.
view-wiki-page, since it's a window-component, is designed to occupy the entire browser window, it has to worry about emiting <html> and <head> tags and setting up javascript includes and style sheet links. Since view-wiki-page is also a template component it depends an a TAL file ("ucw/examples/view.tal") to specify what html to output.
Editing pages is only slightly more complicated than viewing:
(defentry-point "edit.ucw" (:application *example-application*) ((page-name "WelcomePage") name summary contents) (if contents (progn (update-wiki-page page-name (make-instance 'wiki-edit :author name :summary summary :contents contents)) (call 'thankyou :page-name page-name)) (call 'edit-wiki-page :page-name page-name)))
We assume that if the request contains the contents parameter then we're submitting an edit, otherwise we're asking for the edit page form. We've already seen DEFENTRY-POINT, entry-point lambda lists and call, so we can jump directly to the edit-wiki-page component:
(defcomponent edit-wiki-page (window-component template-component) ((page-name :accessor page-name :initarg :page-name)) (:default-initargs :template-name "ucw/examples/edit.tal"))
Like view-wiki-page this is also a window component based on a TAL template.
Just for fun we're going to use YACLML as opposed to TAL for the thankyou component:
(defcomponent thankyou (window-component) ((page-name :accessor page-name :initarg :page-name)))
(defmethod render-on ((res response) (page thankyou)) (symbol-macrolet ((page-name (<:as-html (page-name page)))) (<:html (<:head (<:title "Thank you for editing " page-name)) (<:body (<:p "Thank you for editing " page-name) (<:a :href (strcat "view.ucw?page-name=" (page-name page)) "View " page-name)))))
As you can see by the strcat UCW isn't well adapted to munging strings into urls. [the situation is slightly better in tal pages with tal expression language].