Reflections on a little bit of open education (TL;DR: it works).

We are setting up a new honours degree programme which will involve use of online resources for work based blended learning. I was asked to demonstrate some the resources and approaches that might be useful. This is one of the quick examples that I was able to knock up(*) and some reflections on how Open … Continue reading Reflections on a little bit of open education (TL;DR: it works).

The post Reflections on a little bit of open education (TL;DR: it works). appeared first on Sharing and learning.

We are setting up a new honours degree programme which will involve use of online resources for work based blended learning. I was asked to demonstrate some the resources and approaches that might be useful. This is one of the quick examples that I was able to knock up(*) and some reflections on how Open Education helped me. By the way, I especially like the last bit about “open educational practice”. So if the rest bores you, just skip to the end.

(*Disclaimer: this really is a quickly-made example, it’s in no way representative of the depth of content we will aim for in the resources we use.)

Making the resource

I had decided that I wanted to show some resources that would be useful for our first year, first semester Praxis course. This course aims to introduce students to some of the skills they will need to study computer science, ranging from appreciating the range of topics they will study to being able to use our Linux systems, from applying study skills to understanding some requirements of academic writing. I was thinking that much of this would be fairly generic and must be covered by a hundred and one existing resources when  I saw this tweet:

That seemed to be in roughly the right area, so I took a look at the University of Nottingham’s HELM Open site and found an Introduction to Referencing. Bingo. The content seemed appropriate, but I wasn’t keen on a couple of things. First, breaking up the video in 20sec chunks I fear would mean the student spend more time ‘interacting’ with the Next-> button than thinking about the content. Second, it seems a little bit too delivery oriented, I would like the student to be a little more actively engaged.

I noticed there is a little download arrow on each page which let me download the video. So I downloaded them all and used OpenShot to string them together into one file. I exported this and used the h5p WordPress plugin to show how it could be combined with some interactive elements and hosted on a WordPress site with the hypothes.is annotation plugin, to get this:

The remixed resource: on the top left is the video, below that some questions to prompt the students to pay attention to the most significant points, and on the right the hypothes.is pop-out for discussion.

How openness helps

So that was easy enough, a demo of the type of resource we might produce, created in less than an afternoon. How did “openness” help make it easy.

Open licensing and the 5Rs

David Wiley’s famous 5Rs define open licences as those that let you  Reuse, Revise, Remix, Retain and Redistribute learning resources. The original resource was licensed as CC:BY-NC and so permitted all of these actions. How did they help?

Reuse: I couldn’t have produced the video from scratch without learning some new skills or having sizeable budget, and having much more time.

Revise: I wasn’t happy with the short video / many page turns approach, but was  able to revise the video to make it play all the way through in one go.

Remix: The video was then added to some formative exercises, and discussion facility added.

Retain: in order for us to rely on these resources when teaching we need to be sure that the resource remains available. That means taking responsibility keeping it available. Hence we’ll be hosting it on a site we control.

Redistribute: we will make our version available to other. This isn’t just about “paying forward”, it’s about the benefits that working in an open network being, see the discussion about nebulous open education below.

One point to make here: the licence has a Non-Commercial restriction. I understand why some people favour this, but imagine if I were an independent consultant brought in to do this work, and charged for it. Would I then be able to use the HELM material? The recent case about a commercial company charging to duplicate CC-licensed material for schools, which a US judge ruled within the terms of the licence might apply, but photocopying seems different to remixing. To my mind, the NC clause just complicates things too much.

Open standards, and open source

I hadn’t heard much about David Wiley’s ALMS framework for technical choices to facilitate openness (same page as before, just scroll a bit further) but it deals directly with issues I am very familiar with. Anyone who thinks about it will realise that a copy-protected PDF is not open no matter what the licence on it says. The ALMS framework breaks the reasoning for this down to four aspects: Access to editing tools, Level of expertise required, Meaningfully editable, Self sources. Hmmm. Maybe sometimes it’s clearer not to force category names into acronyms? Anyway, here’s how these helped.

Self-sourced, meaning the distribution format is the source code. This is especially relevant as the reason HELM sent the tweet that alerted me to their materials was that they are re-authoring material from Flash to HTML5. Aside from modern browser support, one big advantage of them doing this is that instead of having an impenetrable SWF package I had access to the assets that made the resource, notably the video clips.

Meaningfully editable: that access to the assets meant that I could edit the content, stringing the videos together, copying and pasting text from the transcript to use as questions.

Level of expertise required: I have found all the tools and services used (OpenShot, H5P, hypothes.is, WordPress) relatively easy to use, however some experience is required, for example to be familiar with various plugins available for WordPress and how to install them. Video editing in particular takes some expertise. It’s probably something that most people don’t do very often (I don’t).  Maybe the general level of digital literacy level we should now aim for is one where people are familiar with photo and video editing tools as well as text oriented word processing and presentation tools. However, I’m inclined to think that the details of using the H264 video codec and AAC audio codec, packaged in a MPEG-4 Part 14 container (compare and contrast with VP9 and ogg vorbis packaged in a profile of Matroska) should remain hidden from most people. Fortunately, standardisation means that the number of options is less than it would otherwise be, and it was possible to find many pages on the web with guidance on the browser compatibility of these options (MP4 and WebM respectively).

Access to editing tools, where access starts with low cost. All the tools used were free, most were open source, and all ran on Ubuntu (most can also run on other platforms).

It’s notable that all these ultimately involve open source software and open standards, and work especially well when then “open” for open standards includes free to implement. That complicated bit around MP4 & WebM video formats, that comes about because royalty requirements for those implementing MP4.

Open educational practice: nebulous but important.

Open education includes but is more than open education resources, open content, open licensing and open standards. It also means talking about what we do. It means that I found out about HELM because they were openly tweeting about their resources. I think that is how I learnt about nearly all the tools discussed here ina similar manner. Yes, “pimping your stuff” is importantly open. Open education also means asking questions and writing how-to articles that let non-experts like me deal with complexities like video encoding.

There’s a deeper open education at play here as well. See that resource from HELM that I started with? It started life in the RLO CETL, i.e. in a publicly funded initiative, now long gone. And the reason I and others in the UKHE know about Creative Commons and David Wiley’s analysis of open content, that largely comes down to #UKOER, again a publicly  funded initiative. UKOER and the stuff about open standards and open source was supported by Jisc, publicly funded. Alumni from these initiatives are to be found all over UKHE, through which these initiatives continue to be crucially important in building our capability and capacity to support learners in new and innovative settings.

 

The post Reflections on a little bit of open education (TL;DR: it works). appeared first on Sharing and learning.

Shared WordPress archive for different post types

In a WordPress plugin I have custom post types for different types of publication: books, chapters, papers, presentations, reports. I want one single archive of all of these publications. I know that the theme template hierarchy allows templates with the pattern archive-$posttype.php, so  I tried setting the slug for all the custom post types to ‘presentations’. WordPress … Continue reading Shared WordPress archive for different post types

The post Shared WordPress archive for different post types appeared first on Sharing and learning.

In a WordPress plugin I have custom post types for different types of publication: books, chapters, papers, presentations, reports. I want one single archive of all of these publications.

I know that the theme template hierarchy allows templates with the pattern archive-$posttype.php, so  I tried setting the slug for all the custom post types to ‘presentations’. WordPress doesn’t like that.  So what I did was set the slug for one of the publication custom post types to ‘presentations’, that gives me a /presentations/ archive for that custom post type(1). I then edited the archive.php file to use a different  template parts for custom post types(2):

<?php $cpargs = array('_builtin' => False,
				  'exclude_from_search' => False);
	$custom_post_types = get_post_types( $cpargs, 'names', 'and' );
	if ( is_post_type_archive( $custom_post_types ) ) {
		get_template_part( 'archive-publication' );
	} else {
		get_template_part( 'archive-default' );
	}  
?>

See anything wrong with this approach? Any comments on how better to do this would be welcome.

Notes:
  1. 1 could edit the .htaccess file to redirect the /books/, /chapters/ …etc archives to /publications/, which would be neater in some ways but would make setting up the theme a bit of a faff.
  2. Yes, the code gives all the custom post types with an archive the same archive. That’s fixable if you make the array of post types for which you want a shared archive manually.

The post Shared WordPress archive for different post types appeared first on Sharing and learning.

Shared WordPress archive for different post types

In a WordPress plugin I have custom post types for different types of publication: books, chapters, papers, presentations, reports. I want one single archive of all of these publications. I know that the theme template hierarchy allows templates with the pattern archive-$posttype.php, so  I tried setting the slug for all the custom post types to ‘presentations’. WordPress … Continue reading Shared WordPress archive for different post types

The post Shared WordPress archive for different post types appeared first on Sharing and learning.

In a WordPress plugin I have custom post types for different types of publication: books, chapters, papers, presentations, reports. I want one single archive of all of these publications.

I know that the theme template hierarchy allows templates with the pattern archive-$posttype.php, so  I tried setting the slug for all the custom post types to ‘presentations’. WordPress doesn’t like that.  So what I did was set the slug for one of the publication custom post types to ‘presentations’, that gives me a /presentations/ archive for that custom post type(1). I then edited the archive.php file to use a different  template parts for custom post types(2):

<?php $cpargs = array('_builtin' => False,
				  'exclude_from_search' => False);
	$custom_post_types = get_post_types( $cpargs, 'names', 'and' );
	if ( is_post_type_archive( $custom_post_types ) ) {
		get_template_part( 'archive-publication' );
	} else {
		get_template_part( 'archive-default' );
	}  
?>

See anything wrong with this approach? Any comments on how better to do this would be welcome.

Notes:
  1. 1 could edit the .htaccess file to redirect the /books/, /chapters/ …etc archives to /publications/, which would be neater in some ways but would make setting up the theme a bit of a faff.
  2. Yes, the code gives all the custom post types with an archive the same archive. That’s fixable if you make the array of post types for which you want a shared archive manually.

The post Shared WordPress archive for different post types appeared first on Sharing and learning.

Three resources for custom metadata in WordPress

When developing WordPress for use as a CMS one approach I have used is to create a custom post type for each type of resource and custom metadata boxes for relevant properties of those types.  I’ve used that approach when exploring the possibility of using WordPress as a semantic web platform to edit schema.org metadata, when building course … Continue reading Three resources for custom metadata in WordPress

The post Three resources for custom metadata in WordPress appeared first on Sharing and learning.

When developing WordPress for use as a CMS one approach I have used is to create a custom post type for each type of resource and custom metadata boxes for relevant properties of those types.  I’ve used that approach when exploring the possibility of using WordPress as a semantic web platform to edit schema.org metadata, when building course information pages for students and am doing so again in updating some work I did on WordPress as a lightweight repository.  Registering a custom post type is pretty straightforward, follow the example in the codex page, I found handling custom metadata boxes a little more difficult. Here are three resources that helped.

Doing it long hand

It’s a few years old, but I found Justin Tadlock’s Smashing Magazine article How To Create Custom Post Meta Boxes In WordPress really useful as a clear and informative tutorial. It was invaluable in understanding how metaboxes work. If I had only wanted one or two simple text custom metadata fields then coding them myself would be an option, but I found a couple of problems. Firstly, I was repeating the same code too many times. Secondly when I thought about wanting to store dates or urls or links to other posts, with suitable user interface elements and data validation, I could see the amount of code needed was only going to increase. So I looked to see whether any better programmers than I had created anything I could use.

Using a helper plugin

I found two plugins that promised to provide a framework to simplify the creation of metaboxes. These are not plugins that provide anything that the end user can see directly, rather they provide functions that can be used in theme an plugin development. They both reduce the work of creating a metabox down to creating an array with the properties you want the metabox to have. They both introduce a dependency on code I cannot maintain, which is something I am always cautious about in using third-party plugins, but it’s much more viable than the alternative of creating such code from scratch and maintaining it myself.

CMB2 is “a metabox, custom fields, and forms library for WordPress that will blow your mind.” It is free and open source, with development hosted on GitHub.  It seems quite mature (version 1.0 was in Nov 2013), with a large installation base and decent amount of current activity on github.

Meta Box is “a powerful, professional developer toolkit to create custom meta boxes and custom fields for WordPress.” It too is free and released under GPL2 licence, but there are paid-for extensions (also GPL2 licensed) and I don’t see any open source development (I may not have looked in the right place).  Meta box has been around for a couple of years, is regularly updated and has a very large user base. The paid-for extensions give me some hope that the developers have a sustainable business model, but a worry that maybe ‘free’ doesn’t include the one function that at sometime I will really need. Well, developers cannot live on magic beans so I wouldn’t mind paying.

In the end both plugins worked well, but Meta Box allows the creation of custom fields for a link from one post to another, which I didn’t see in CMB2. That’s what I need for a metadata field to say that the author of the book described in one post is a person described in another.

The post Three resources for custom metadata in WordPress appeared first on Sharing and learning.

Cloning WordPress sites for development

I do just enough theme and plugin development on WordPress to need an alternative to using a live WordPress site for development and testing, but at the same time I want to be testing on site as similar to the live site as possible. So I set up clones of WordPress sites either on my local … Continue reading Cloning WordPress sites for development

The post Cloning WordPress sites for development appeared first on Sharing and learning.

I do just enough theme and plugin development on WordPress to need an alternative to using a live WordPress site for development and testing, but at the same time I want to be testing on site as similar to the live site as possible. So I set up clones of WordPress sites either on my local machine or a server for development and testing. (Normally I have clones on the localhost server of couple of machines I use for development and another clone on a web accessible testing or staging server for other people to look at.) I don’t do this very often, but each time I do it I spend as much time trying to remember what it is I need to do as it actually takes to do it. So here, as much as an aide-memoire for myself as anything, else I’ve gathered it all in one place. What I do is largely based on the Moving WordPress information in the codex, but there are a couple of things that doesn’t cover and a couple of things I find it easier to do differently.

Assuming that the pre-requisites for WordPress are in place (i.e. MySQL, webserver, PHP), there are three stages to creating a clone. A. copy the WordPress files to the development site; B. clone the database; C. fix the links between WordPress and the database for the new site. A and B are basically creating backup copies of your site, but you will want to make sure that whatever routine backups you use are up to date and ready to restore in case something goes wrong. Also, this assumes that you are notwant to clone just one site on a WordPress Multisite installation.

Copying the WordPress files

Simply copy all the files from the folder you have WordPress installed in, and all the sub-folders to where you want the new site to be. This will mean that all the themes, plugins and uploaded media will be the same on both sites. Depending on whether the development site is on the same server as the main site I do this either with file manager or by making a compressed archive and ftp. Make sure the web server can read the files on the dev site (and write to the relevant folders if that is how you upload media, plugins and themes).

Cloning the database

First I create a new, blank database on for the new site, either from the command line or using something like MySQL Database Wizard which my hosting provider has on CPanel. I create a new user with full access to that data base–the username and password for this user will be needed to configure WordPress with access to this database. If you have complete control of over the database name and user name then use the same name username and password as is in the wp-config.php file of the site you are cloning. Otherwise you can change these later.

Second, I use PHP MyAdmin to export the data base from the original site and import it to the one on which you are making a clone.

phpMyAdmin Export screen

Fix all the bits that break

All that remains is to reconnect the PHP files to the database and fix a few other things that break. This is where it get fiddly. Also, from now on be really careful about which site you are working on: they look the same and you really don’t want to set up your public site as a development server. Make all these changes on the new development site.

In wp-config.html (it’s in the top of the WordPress folder hierarchy) find the following lines and change the values to be those for your new development server and database.

define( 'WP_CONTENT_URL', 'http://example.org/blog' );
define( 'WP_CONTENT_DIR', 'path/to/wp-content' );

define('DB_NAME', 'databaseName');

/** MySQL database username */
define('DB_USER', 'databaseUserName');

/** MySQL database password */
define('DB_PASSWORD', 'password');

You might also need to change the value for DB_HOST

Then you need to change the options that WordPress stores in the database. Normally you do this through the WordPress admin interface, but this is not yet available on your new site. There are various ways you can do this, I change the url directly in the data base with PHPMyAdmin, either by direct editing as described in the codex page or from the command line as described here.

mysql -u root -p

USE databaseName
SELECT * FROM wp_options WHERE option_name = 'home';
UPDATE wp_options SET option_value="http://example.org/blog" WHERE option_name = "home";
SELECT * FROM wp_options WHERE option_name = 'siteurl';
UPDATE wp_options SET option_value="http://example.org/blog" WHERE option_name = "siteurl";

You should now have access to the new cloned site, though some things will still be misbehaving.

You will probably have the old site’s URL in various posts and GUIDs. I use the better search replace plugin to fix these.

iesiesIf you do any fancy redirects with .htaccess, make sure that these are written in such a way that works for the new URL.

If you are using Jetpack you will need to use it in safe mode if the development server is connected to the web or development mode if running on localhost. (This is a bit of a pain if you want to test Jetpack settings.)

On a development site you’ll probably want to add this to wp-config.php:

define('WP_DEBUG', true);

If you are running a development or testing server on a web accessible site you probably want to restrict who has access to it. I use the My private site plugin so that only site admins have access.

Keeping in sync

While it’s not entirely necessary that a development or testing site be kept completely in sync with the main one, it is worth keeping them close so that you don’t get unexpected issues on the main site. You can manually update the plugins and themes, and use the wordpress export / import plugins to transfer new content from the live site to the clone. Every now and again you might want to re-clone the site afresh. Something I find useful for development and testing of new plugins and themes is to have the plugin or theme directory that I am developing in set up as a git repository linked to github and keep files in sync with git push and git pull.

Anything else?

I think that is it. If I have forgotten anything or if you have tips on making any of this easier please leave a comment.

The post Cloning WordPress sites for development appeared first on Sharing and learning.

WordPress as a semantic web platform?

For the work we’ve been doing on semantic description of courses we needed a platform for creating and editing instance data flexibly and easily. We looked at callimachus and Semantic MediaWiki; in the end we went with the latter because of JAVA version incompatibility problems with the other, but it has been a bit of a struggle. I’ve … Continue reading WordPress as a semantic web platform?

For the work we’ve been doing on semantic description of courses we needed a platform for creating and editing instance data flexibly and easily. We looked at callimachus and Semantic MediaWiki; in the end we went with the latter because of JAVA version incompatibility problems with the other, but it has been a bit of a struggle. I’ve used WordPress for publishing information about resources on a couple of projects, for Cetis publications and for learning resources, and have been very happy with it. WordPress handles the general task of publishing stuff on the web really well, it is easily extensible through plugins and themes, I have nearly always found plugins that allow me to do what I want and themes that with a little customization allow me to present the information how I want. As a piece of open source software it is used on a massive scale (about a quarter of all web domains use it) and has the development effort and user support to match. For the previous projects my approach was to have a post for each resource I wanted to describe and to set the title, publication date and author to be those for the resource, I used the main body of the post for a description and used tags and categories for classification, e.g. by topic or resource type; other metadata could be added using WordPress’s Custom Fields, more or less as free text name-value pairs. While I had modified themes so that  the semantics of some of this information was marked up with microdata or RDFa embedded in the HTML, I was aware that WordPress allowed for more than I was doing.

The possibility of using WordPress for creating and publishing semantic data hinges on two capabilities that I hadn’t used before: firstly the ability to create custom post types so that for each resource type there can be a corresponding post type; secondly the ability to create custom metadata fields that go beyond free text. I used these in conjunction with a theme which is a child theme of the current default, TwentyFifteen, which sets up the required custom types and displays them. Because I am familiar with it and it is quite general purpose, I chose the schema.org ontology to implement, but I think the ideas in this post would be applicable to any RDF vocabulary. When creating examples I had in mind a dataset describing the books that I own and the authors I am interested in.

I started by using a plugin, Custom Post Type UI, to create the post types I wanted but eventually was doing enough in php as a theme extensions (see below) that it made sense just to add a function to create the the post types. This drops the dependency on the plugin (though it’s a good one) and means the theme works from the outset without requiring custom types to be set up manually.

add_action( 'init', 'create_creativework_type' );
function create_creativework_type() {
  register_post_type( 'creativework',
    array(
      'labels' => array(
        'name' => __( 'Creative Works' ),
        'singular_name' => __( 'Creative Work' )
      ),
      'public' => true,
      'has_archive' => true,
      'rewrite' => array('slug' => 'creativework'),
      'supports' => array('title', 'thumbnail', 'revisions' )
    )
  );
}

The key call here is to the WP function register_post_type() which is used to create a post type with the same name as the schema.org resource type / class; so I have one of these for each of the schema.org types I use (so far Thing, CreativeWork, Book and Person). This is hooked into the WordPress init process so it is done by the time you need those post types.

I do use a plugin to help create the custom metadata fields for every property except the name property (for which I use the title of the post). Meta Box extends the WordPress API with some functions that make creating metadata fields in php much easier. These metadata fields can be tailored for particular data types, e.g. text, dates, numbers, urls and, crucially, links to other posts. That last one gives you what you need for to create relationships between the resources you describe in WordPress, which can expressed as triples. Several of these custom fields can be grouped together into a “meta box” and attached as a group to specific post types so that they are displayed when editing posts of those types. Here’s what declaring a custom metadata field for the author relationship between a CreativeWork and a Person looks like with MetaBox (for simplicity I’ve omitted the code I have for declaring the other properties of a Creative Work and some of the optional parameters). I’m using the author property as an example because a repeatable link to another resource is about as complicated a property as you get.

function semwp_register_creativework_meta_boxes( $meta_boxes )
{
    $prefix = 'semwp_creativework_';

    // 1st meta box
    $meta_boxes[] = array(
        'id'         => 'main_creativework_info',
        'title'      => __( 'Main properties of a schema.org Creative Work', 'semwp_creativework_' ),
        // attach this box to the following post types
        'post_types' => array('creativework', 'book' ),

	// List of meta fields
	'fields'     => array(
            // Author
            // Link to posts of type Person.
            array(
                'name'        => __( 'Author (person)', 'semwp_creativework_' ),
                'id'          => "{$prefix}authors",
                'type'        => 'post',
                'post_type'   => 'person',
                'placeholder' => __( 'Select an Item', 'semwp_creativework_' ),
            // set clone to true for repeatable fields
            'clone' => true
            ),
        ),
    );
    return $meta_boxes;
}

What this gives when editing a post of type book is this:

semwpeditshot

WordPress uses a series of nested templates to display content, which are defined in the theme and can either be specific to a post type or generic, the generic ones being used as a fall back if a more specific one does not exist. As I mentioned I use a child theme of TwentyFifteen which means that I only have to include those files that I change from the parent. To display the main content of posts of type book I need a file called content-book.php (the rest of the page is common to all types of post), which looks like this


<article resource="?<?php the_ID() ; ?>#id" id="?<?php the_ID(); ?>" <?php post_class(); ?> vocab="http://schema.org/" typeof="Book">

<header class="entry-header">
    <?php
        if ( is_single() ) :
            the_title( '<h1 class="entry-title" property="name">', '</h1>' );
        else :
            the_title( sprintf( '<h2 class="entry-title"><;a href="%s" rel="bookmark">', esc_url( get_permalink() ) ), '</a></h2>;' );
        endif;
    ?>
</header>
<div class="entry-content">
    <?php semwp_print_creativework_author(); ?>
    <?php semwp_print_book_bookEdition(); ?>
    <?php semwp_print_book_numberOfPages(); ?>
    <?php semwp_print_book_isbn(); ?>
    <?php semwp_print_book_illustrator(); ?>
    <?php semwp_print_creativework_datePublished(); ?>
    <?php semwp_print_book_bookFormat(); ?>
    <?php semwp_print_creativework_sameAs(); ?></div>
<footer class="entry-footer">
    <?php twentyfifteen_entry_meta(); ?>
    <?php edit_post_link( __( 'Edit', 'twentyfifteen' ), '<span class="edit-link">', '</span>' ); ?>
    <?php semwp_print_extract_rdf_links(); ?>
</footer>

</article>

Note the RDFa in some of the html tags, for example the <article> tag includes

resource= [url]#id vocab="http://schema.org/" typeof="Book"

and the title is output in an <h1> tag with the

property="name"

attribute. Exposing semantic data as RDFa is one (good) thing, but what about other formats? A useful web service called RDF Translator helps here. It has an API which allowed me to put a link at the foot of each resource page to the semantic data from that page in formats such as RDF/XML, N3 and JSON-LD; it’s quite not what you would want for fully fledged semantic data publishing but it does show the different views of the data that can be extracted from what is published.

Also note that most of the content is printed through calls to php functions that I defined for each property, semwp_print_creativework_author() looks like this (again a repeatable link to another resource is about as complex as it gets:

function semwp_print_alink($id) {
     if (get_the_title($id))       //it's a object with a title
     {
         echo sprintf('<a property="url" href="%s"><span property="name">%s</span></a>', esc_url(get_permalink($id)), get_the_title($id) );
     }
     else                          //treat it as a url
     {
         echo sprintf('<a href="%s">%s</a>', esc_url($id), $id );
     }
}
function semwp_print_creativework_author()
{
    if ( rwmb_meta( 'semwp_creativework_authors' ) )
    {
	echo '

By: ';
	$authors = rwmb_meta( 'semwp_creativework_authors' );
        foreach ( $authors as $author )
        {
               echo '<span property="author" typeof="Person">';
               semwp_print_alink($author);
               echo '</span>';
        }
        echo '

';
    }
}

So in summary, for each resource type I have two files of php/html code: one which sets up a custom post type, custom metadata fields for the properties of that type (and any other types which inherit them) and includes some functions that facilitate the output of instance data as HTML with RDFa; and another file which is the WordPress template for presenting that data. Apart from a few generally useful functions related to output as HTML and modifications to other theme files (mostly to remove embedded data which I found distracting) that’s all that is required.

The result looks like this:

Note, this image is linked to the page on wordpress that is shows, click on it if you want to explore the little data that there is there, but please do be aware that it is a development site which won't always be working properly.
Note, this image is linked to the page on my WordPress install that it shows, click on it if you want to explore the little data that there is there, but please do be aware that it is a development site which won’t always be working properly.

And here’s the N3 rendering of the data in that page as converted by RDF Translator:

@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfa: <http://www.w3.org/ns/rdfa#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix schema: <http://schema.org/> .
@prefix xml: <http://www.w3.org/XML/1998/namespace> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

<http://www.pjjk.net/semanticwp/book/the-day-of-the-triffids> rdfa:usesVocabulary schema: .

<http://www.pjjk.net/semanticwp/book/the-day-of-the-triffids?36#id> a schema:Book ;
    schema:author [ a schema:Person ;
            schema:name "John Wyndham"@en-gb ;
            schema:url <http://www.pjjk.net/semanticwp/person/john-wyndham> ] ;
    schema:bookEdition "Popular penguins (2011)"@en-gb ;
    schema:bookFormat ""@en-gb ;
    schema:datePublished "2011-09-01"^^xsd:date ;
    schema:illustrator [ a schema:Person ;
            schema:name "John Griffiths"@en-gb ;
            schema:url <http://www.pjjk.net/semanticwp/person/john-griffiths> ] ;
    schema:isbn "0143566539"@en-gb ;
    schema:name "The day of the triffids"@en-gb ;
    schema:numberOfPages 256 ;
    schema:sameAs "http://www.amazon.co.uk/Day-Triffids-Popular-Penguins/dp/0143566539/"@en-gb,
        "https://books.google.co.uk/books?id=zlqAZwEACAAJ"@en-gb .

Further work: Ideas and a Problem

There’s a ton of other stuff that I can think of that could be done with this, from the simple, e.g. extend the range of types supported, to the challenging, e.g. exploring ways of importing data or facilitating / automating the creation of new post types from known ontologies, output in other formats, providing a SPARQL end point &c &c… Also, I suspect that much of what I have implemented in a theme would be better done as a plugin.

There is one big problem that I only vaguely see a way around, and that is illustrated above in the screenshot of the editing interface for the ‘about’ property. The schema.org/about property has an expected type of schema.org/Thing; schema.org types are hierarchical, which means the value for about can be a Thing or any subtype of Thing (which is to say of any type). This sort of thing isn’t unique to schema.org. However, the MetaBox plugin I use will only allow links to be made to posts of one specific type, and I suspect that reflects something about how WordPress organises posts of different custom types. I don’t think there is any way of asking it to show posts from a range of different types and I don’t think there is any way of saying that posts of type person are also of type thing and so on.  In practice this means that at the moment I can only enter data that shows books as being about unspecific Things; I cannot, for example, say that a biography is a book about a Person. I can only see clunky ways around this.
Update: I noticed that you can pass an array of post types so that selection can be made from any one of them.

[Aside: the big consumers of schema data (Google, Bing, Yahoo, Yandex) will also permit text values for most properties and try to make what sense of it they can, so you could say that for any property either a string literal or a link to another resource should be permitted. This, I think, is a peculiarity of schema.org. The screenshot above of the data input form shows that the about field is repeated to provide the option of a text-only value, an approach hinting at one of the clunky unscalable solutions to the general problem described above.]

What next? I might set a student project around addressing some of these extensions. If you know a way around the selecting different type problem please do drop me a line. Other than that I can see myself extending this work slowly if it proves useful for other stuff, like creating examples of pages with schema.org or LRMI data in them. If anyone is really interested in the source code I could put it on github.

Update 02 Sep 2015:

I refactored the code so that most of the new php for creating new custom post types and setting up the forms to edit their properties is in plugin, and all the theme does is display the data entered with embedded RDFa.

The code is now on GitHub.

I did set a student project around extending it, waiting to see if any student opts for it.