Web applications of all sizes rarely come without the need for editable text content. Implementing a complete content editing solution might yet be still oversized. So why not make use of one of the better known content management solutions available to the open source community – eZ Publish?
As a full blown content management system, eZ Publish does not only supply a quite powerful content repository, but also an ideally tailored content editor that supports all relevant features such as content versioning, publishing workflow or roles and permissions management.
After its step into Symfony2-based adulthood, eZ Publish has been outfitted with a completely refurbished RESTful programming interface, that enables developers on the one hand to remote control an eZ Publish based web site, on the other hand to tap the content management backend as a repository for their own applications.
The eZ Publish REST-API can be obviously called with any HTTP client such as a Webbrowser, REST-Client or programmatically any libcurl binding. Developers might be tempted to use a high level REST implementation like Guzzle, which simplifies the most common implementation chores.
Using Guzzle all eZ Publish REST Resources can be simply called for example like this:
$client = new \Guzzle\Http\Client(); $request = $client->createRequest( ‘GET’, ‘http://my.ezinstall.net/api/ezp/v2/content/objects/12345’, [‘Accept’ => ‘application/vnd.ez.api.Content+xml’], null, $parameters ); $result = $request->send();
$result then provides a compact and convenient Guzzle Response instance for further processing.
Let’s have a look at three common use case to exemplify:
Reading content from eZ Publish
Let’s start out getting a single content object from our eZ Publish content repository. This is easily accomplished with a GET request on the /content/objects/<id> resource using the code from Snippet 1.
Authentification can be achieved by using the credentials of any editor in basic auth.
It should be noted that the “Accept” header in our request is of significance. On the one hand this header is used throughout the entire API to set the desired output format – json and xml are supported – through the +xml (+json respectively) suffix. (As a rule of thumb is it not advisable to mix different formats for input and output, as this sometimes causes problems in the inner workings of eZ Publish.)
On the other hand, in some cases, several levels of output complexity can be retrieved from the API. In our example, the application/vnd.ez.api.Content mime type defines the result to contain a ‘full service’ package of all content object versions including the full content of the current, which is the currently published version of the requested object. Requesting a mime type of application/vnd.ez.api.ContentInfo would leave out the full current version data and only supply a reference to the respective /content/objects/<id>/currentversion resource. HATEOAS is generally very well implemented in the eZ Publish REST-API so that in cases where full data is not included in a result, it is only one hypermedia HTTP-call away.
The result of our request is usually a longish document in the required output format, that contains at least references to all the relevant aspects of the content object such as its content type, versions, sections and its locations in the content tree.
Writing content to eZ Publish
In cases where user feedback is collected over our web application, it might be helpful to store it in our content repository and make it available to the editorial staff.
Despite the generally rather complex repository structure of eZ Publish, creating content objects is actually one simple POST call to the /content/objects resource. Content data is included either in JSON or XML format in the request body.
The new object’s location, which is necessary to link it in its place in the eZ Publish content tree is created on the fly through the LocationCreate element. Be aware, that the included remoteID must be unique throughout the document structure.
<?xml version="1.0" encoding="utf-8" ?> <ContentCreate> <ContentType href="/api/ezp/v2/content/types/187"/> <mainLanguageCode>ger-DE</mainLanguageCode> <LocationCreate> <ParentLocation href="/api/ezp/v2/content/locations/2/9654" /> <priority>0</priority> <hidden>false</hidden> <sortField>PATH</sortField> <sortOrder>ASC</sortOrder> </LocationCreate> <Section href="/api/ezp/v2/content/sections/7"/> <alwaysAvailable>true</alwaysAvailable> <remoteId>remoteId12345678</remoteId> <fields> <field> <fieldDefinitionIdentifier>text</fieldDefinitionIdentifier> <languageCode>ger-DE</languageCode> <fieldValue>This is another title</fieldValue> </field> ... </fields> </ContentCreate>
Please note that this POST call only creates a draft version of our new content object that as such is not yet visible in the content structure tree. To change this, just issue a call to /content/objects/<coid>/versions/<versionNo> endpoint using the somewhat uncommon PUBLISH HTTP method. If your REST client doesn’t support this method, an X-HTTP-Method-Override header containing PUBLISH can be used as a surrogate.
Querying eZ Publish
Querying content objects from eZ Publish means creating a “view” on the content repository. Using a view basically consists of issuing a POST call on the /content/views resource, containing the view definition in the request body. Introducing offset and limit elements in the view definition, simple pagination is achieved.
<?xml version="1.0" encoding="UTF-8"?> <ViewInput> <identifier>COView</identifier> <Query> <Criteria> <ContentTypeIdentifierCriterion>image</ContentTypeIdentifierCriterion> <SectionIdentifierCriterion>holiday</SectionIdentifierCriterion> </Criteria> <limit>10</limit> <offset>0</offset> </Query> </ViewInput>
Content Sections, that can be defined by an adminstrator in the by eZ Publish setup, come in handy creating a view. A SectionIdentifierCriterion element is added to the view definition to limit the scope of our view to a desired subtree, which optimises the speed of the query and helps organising our content. More criteria according to here can be added to our query.
The documentation for the API suggests, that by POSTing to the /content/views resource, we actually create a persistent view whose results can simply be retrieved over and over again. This promising concept is – at the time of this writing – not yet implemented, so that we have to re-create the view whenever we need its results.
As can be seen from the documentation, the eZ Publish REST-API v2 holds a lot more in store for a developer than shown in our three examples. Several aspects of the API – as large parts of the eZ Publish CMS in general – are still waiting to be finalised, but it already provides a nice working base for development.