Skip to main content Skip to navigation

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
}