Step 3: Create a new page for every user
Now that we have our users with user information, we want to create a page for each of them. This is fairly simple, since we can use the Atom Publishing Protocol (APP) to create and edit page content in Sitebuilder.
Unfortunately, one limitation of APP is that it doesn't specify a field where we can specify a new URL for the content, so Sitebuilder just takes the page title and turns it into something sensible. That's not exactly ideal, but we can edit all of this in the page properties afterwards. We also need to authenticate to be able to access Sitebuilder, so we need to add ?forceBasic=true to the end of the URL and pass it the username and password credentials of our created external user.
/**
* Creates a new page under the base page with the specified page name,
* title and content. The pageName is the last part of the URL, so if the
* pageName was "c" and the basePage was /a/b, the new URL would be /a/b/c.
*
* This method returns the URL for the new page.
*/
public String createPage(User user, String basePage) {
AtomClient client = new AtomClient(username, password);
client.setAtomEndpoint("https://sitebuilder.warwick.ac.uk/sitebuilder2/edit/atom/atom.htm");
/*
* In the Atom Publishing Protocol, a new page is called a new "Entry".
* Unfortunately, the APP specification doesn't provide anywhere to set
* a URL, so Sitebuilder generates a new URL from the title.
* Unfortunately, this means that to get our desired result we need to
* create the page and then edit it.
*
* Sitebuilder only listens to the "title" and "content" parts of an
* entry.
*/
AtomEntry newPage = new AtomEntry();
newPage.setTitle(user.usercode);
newPage.setContent("<p>Hi, my name is ${user.name} and I'm a ${user.year} year ${user.type} in ${user.dept}.</p>");
/*
* We need to construct the URL to the Atom API to create a page.
* Setting forcebasic=true allows us to authenticate to the service with
* HTTP Basic authentication, and then we set the base page's url.
*/
String uri = "?forcebasic=true&page=" + basePage;
Response response = client.POST(uri, newPage);
/*
* We need to get the URL for the new page - ATOM responds with the
* location of the ATOM representation of the created page, so we can
* just get the information from there.
*/
String newPageAtomUrl = response.location + "&forcebasic=true";
response = client.get(newPageAtomUrl);
AtomEntry createdPage = response.getDocument().getRoot();
return createdPage.getAlternateLink().path;
}
Now our new page is created with content under our base page, we can edit the properties to add some useful metadata about the user. This is a good example of where we are replicating form behaviour in Sitebuilder because no formal API exists at the moment, but please be aware that this might mean it is not necessarily stable.
private void applyUserMetadata(String pageUrl, User user) {
/*
* We want to apply some metadata to the page in question based on the user.
*
* The things we want to do are:
*
* - Set the page heading, title bar caption and link caption to the users name
* - Turn off Show in Local Navigation
* - Turn on Allow Page Comments
* - Set the description to something useful
* - Add some keywords
* - Set the page contact to be the student themselves
*
* Unfortunately, there isn't a formal API for editing page properties, so this
* must be achieved by simulating a POST into the Edit Properties page in Sitebuilder.
*/
properties = {
// the page to edit
page: pageUrl,
// tell Sitebuilder that we're saving the page
_submit: "submit",
// set the page heading, title bar caption and link caption to
// the users name
title: user.name,
shortTitle: user.name,
linkTitle: user.name,
// turn off show in local navigation
showInLocalNavigation: "false",
// turn on page comments
commentable: "true",
// set a description
description: "Contributed module data for module ${moduleCode} for ${user.name}",
// add keywords to the page
keywords: "user contributed content, ${user.name}, ${moduleCode}",
// set the page contact to be the student themselves
owner: user.userCode
};
String url =
"https://sitebuilder.warwick.ac.uk/sitebuilder2/edit/page/properties/submit.html?forcebasic=true";
// We're POSTing data this time
Request request = new Request(url, POST, properties);
// set the user-agent string to something identifiable so that if there
// is a problem with the way I am calling the API I can be contacted.
request.addHeader("User-Agent",
"Mat Mannion (M.Mannion@warwick.ac.uk), IT Services, x74433");
request.authenticate(username, password);
request.process(); // we should make sure this returns a 302
}
Finally, now the properties are set, we want to add the student themselves with permissions to be a Contributor to that page, so they can modify their own page and upload files there. This is a similar operation, but internally Sitebuilder uses JSON for permissions changes (since the page uses AJAX) so we can parse out useful information if required.
private void addPermission(String pageUrl, User user) {
/*
* To add permission to a page, we POST data to an API which returns JSON.
*/
String url =
"https://sitebuilder.warwick.ac.uk/sitebuilder2/edit/permissions/ajax/addPermission.html?forcebasic=true";
// We're POSTing data this time
Request request = new Request(url, POST, {
// the page to edit
page: pageUrl,
// the usercode that we're adding, and the matchmethod (exact match)
groupName: user.usercode,
matchmethod: "matches",
// only this page, no sub-pages/files
includeSection: "false",
// permission type
permissionAsString: permissionLevel
});
// set the user-agent string to something identifiable so that if there
// is a problem with the way I am calling the API I can be contacted.
request.addHeader("User-Agent",
"Mat Mannion (M.Mannion@warwick.ac.uk), IT Services, x74433");
request.authenticate(username, password);
request.process(); // we should make sure this returns a 200 and parse the JSON
}