Making an extension to the API

Instead of making new output formats (like I'm asking about in this post: http://omeka.org/forums/topic/complete-database-export-to-json-xml) I'm trying to make an extension to the API. I can't seem to add any data to the output. I created this very simple code:

protected $_filters = array( 'api_extend_items' );

public function filterApiExtendItems($extend, $args)
{
$extend['test'] = "testvalue1";
return $extend;
}

Shouldn't that simply add "test":testvalue1 to my results? Any ideas?

From the docs:

> Note that the API enforces a pattern when extending a
> resource:
>
> * id and url for a one-to-one relationship
> * count and url for a one-to-many relationship
> * resource is recommended but not required
>
> All other keys pass through as custom data that may be
> used for the client’s convenience.

So you must add id and url or count and url keys to the passed array, along with any custom keys you want. See the docs for examples on how to format for one or multiple resources.

I should have seen that. I now have the following code, that gives no errors, warnings or problems, it just doesn't add anything to the json export.


public function filterApiExtendItems($extend, $args)
{
$record = $args['record'];
if ($record->owner_id) {
$extend['secondowner'] = array(
'id' => $record->owner_id,
'url' => Omeka_Record_Api_AbstractRecordAdapter::getResourceUrl("/users/{$record->owner_id}"),
'resource' => 'users'
);
} else {
$extend['secondowner'] = null;
}
return $extend;
}

It also doesn't work with my extended geolocation data.
Also, I'm not sure if $extend is supposed to be empty at the start, but it is. Actually, whatever I return, the output remains the same.

Remember that you must format the return value as an array with id or count and url as keys. Also, whatever you extend must be a registered resource, so unless secondowner is registered as a resource using the api_resources filter, what you are doing will not work.

Thanks! That worked out nicely.

Now it seems like I can only add single nodes to the extended_resources node. How should a branch be formatted? The filter doesn't seem to swallow arrays but I would like to add something like this:


"extended_resources":{
"narration-location":[
{
"count":1,
"url":"url/1",
"name":"blastreet",
"resource":"location-route"
},
{
"count":2,
"url":"kaasboer",
"name":"Amsterdam",
"resource":"location-locality"
},
}

It your case, narration-location must be a registered resource. What you are trying to do will not work.

Yes I understand that. I have registered the resources I want to add. Adding single nodes to the json output works. I just have no idea on how to add multiple nodes like in my previous post.

This is what I've got so far. I see the same structure has is generated in getRepresentation() but I suppose it has to be different?


public function filterApiExtendItems($extend, $args)
{
$locations = array(
array( "id" => 67,
"url" => "a_url",
"name" => "angst",
"resource" => "location"),
array( "id" => 68,
"url" => "another_url",
"name" => "bangheid",
"resource" => "location")
);
$item = $args['record'];
$extend['Narration-location'] = $locations;
return $extend;
}

public function filterApiResources($apiResources)
{
$apiResources['Narration-location'] = array(
'module' => 'ApiExtender',
'record_type' => 'Location',
'actions' => array( 'index', 'get' ),
'index_params' => array(
'collection', 'item_type', 'featured', 'public', 'added_since',
'modified_since', 'owner',
),
);
return $apiResources;
}

You cannot have multiple nodes for the same resource. The only legal formats in the api_extend_* array are:

$extend['narration_location'] = array(
   'id' => 1,
   'url' => 'narration_location/1',
   'resource' => 'narration_location',
)

or:

$extend['narration_location'] = array(
   'count' => 100,
   'url' => 'narration_location?foo=1',
   'resource' => 'narration_location',
)

I would like to get back to this problem. At the moment we have a forked and adjusted version of GeolocationPlugin installed. (Latest version on Omeka 2.1.4). It can hold more geological information, like so: http://www.verhalenbank.nl/api/geolocations/544?pretty_print

The API is extended nicely as you can see. Only, now I would like this information added to an item in the API, but I can't get it to work: http://www.verhalenbank.nl/api/items/54491?pretty_print

This item has a bunch of geo information connected to it: http://www.verhalenbank.nl/items/show/54491

The code in our plugin does the same as in the Geolocations plugin:

public function filterApiExtendItems($extend, $args)
{
$item = $args['record'];
$location = $this->_db->getTable('Location')->findBy(array('item_id' => $item->id));
if (!$location) {
return $extend;
}
$locationId = $location[0]['id'];
$extend['geolocations'] = array(
'id' => $locationId,
'url' => Omeka_Record_Api_AbstractRecordAdapter::getResourceUrl("/geolocations/{$locationId}"),
'resource' => 'geolocations',
);
return $extend;
}

A print_r($extend['geolocations']); in filterApiExtendItems prints out:

Array
(
[id] => 19598
[url] => http://127.0.0.1/vb/api/geolocations/19598
[resource] => geolocations
)

I hope I described my problem clearly. What am I overlooking? Why is there no location information appearing with the Item through the API?

That all seems right. I vaguely recall encountering a similar issue here, and it turned out that it was a separate plugin improperly using the filter (possibly Commenting). So I'd try deactivating other plugins and checking to see if that makes the data appear. If so, there's probably something amiss in that plugin's use of the filter.

It seems to be the ExhibitBuilder. I updated that and it appears to be fixed. Thanks for pointing that out!

Is there a way to append extended data directly to the items through the API? This seems to be working similarly in case of the tags.
It's actually kind of nice to get a json dump of the whole database this way, except for the extended data parts, that I am merging to the items by means of script now.
Or do you recommend writing an alternative API of some kind if I would like this functionality?

Yep! You just need to write a plugin that follows the Extending Existing Resources guide.

Yes I did, but I just get an Id and a link to the resource in the extended_resources. Not all the data of that resource included. Like so:


"extended_resources":{
"geolocations":{
"id":45,
"url":"http:\/\/127.0.0.1\/vb\/api\/geolocations\/45",
"resource":"geolocations"
},
"exhibit_pages":{
"count":0,
"url":"http:\/\/127.0.0.1\/vb\/api\/exhibit_pages?item=8649",
"resource":"exhibit_pages"
}
}

In the api_extend_items filter, you can add any additional data you want, provided you follow the constraints in the documentation.