| 1 |
<?php
|
| 2 |
// $Id: rdf.feedapi.inc,v 1.3 2009/02/22 20:44:14 arto Exp $
|
| 3 |
|
| 4 |
//////////////////////////////////////////////////////////////////////////////
|
| 5 |
// Feed Element Mapper API hooks
|
| 6 |
|
| 7 |
/**
|
| 8 |
* Implementation of hook_feedapi_mapper().
|
| 9 |
*
|
| 10 |
* @requires feedapi_mapper >= 6.x-1.0-beta9
|
| 11 |
*/
|
| 12 |
function rdf_feedapi_mapper($op, $node, $feed_element = array(), $field_name = '', $sub_field = '') {
|
| 13 |
switch ($op) {
|
| 14 |
case 'describe':
|
| 15 |
return t('Maps feed item properties into RDF repositories and into CCK fields as defined by RDF schema settings');
|
| 16 |
|
| 17 |
case 'list':
|
| 18 |
// The sub-fields define the actual mapping targets available in the
|
| 19 |
// Feed Element Mapper drop-down boxes for each feed item property.
|
| 20 |
// In our case, we expose all mutable RDF repositories as targets, and
|
| 21 |
// additionally include a 'System' target that will perform a reverse
|
| 22 |
// mapping through the RDF Schema API:
|
| 23 |
$sub_fields = array('system' => t('System'));
|
| 24 |
foreach (rdf_get_repositories() as $repo_name => $repo_info) {
|
| 25 |
if (!empty($repo_info['enabled']) && !empty($repo_info['mutable'])) {
|
| 26 |
$sub_fields[$repo_name] = $repo_info['title'];
|
| 27 |
}
|
| 28 |
}
|
| 29 |
return array('rdf' => $sub_fields); // $node->rdf is defined in rdf_nodeapi('prepare')
|
| 30 |
|
| 31 |
case 'map':
|
| 32 |
// NOTE: $node->nid is unset at this point if the feed item node is being created.
|
| 33 |
|
| 34 |
// We're unable to map individual feed item properties, as the
|
| 35 |
// hook_feedapi_mapper() API misplaces the information on what the
|
| 36 |
// feed item property's name is (i.e. it only passes in the value, in
|
| 37 |
// $feed_element, not the name), without which we are powerless to do
|
| 38 |
// any RDF-related mapping. However, we do support collections of feed
|
| 39 |
// item properties, such as the 'rdf' collection exported by the
|
| 40 |
// patched version (see drupal.org issue #XXXXXX) of the Common
|
| 41 |
// Syndication Parser for RSS 1.0, as collections of properties are
|
| 42 |
// indexed by the property name and hence allow us to obtain the
|
| 43 |
// predicate in question. This is still a bit iffy, however, in the
|
| 44 |
// sense that the property collections are actually indexed by
|
| 45 |
// namespaced QNames/CURIEs, so namespace prefixes become quite (and
|
| 46 |
// unduly) significant as we don't have any other means of determining
|
| 47 |
// the full predicate URI. Provided that well-known "standard"
|
| 48 |
// prefixes are used in the feed and on the site running this code,
|
| 49 |
// all will be well.
|
| 50 |
if (is_array($feed_element)) { // is a collection of properties
|
| 51 |
$namespaces = rdf_get_namespaces();
|
| 52 |
$data = array();
|
| 53 |
|
| 54 |
// Add a statement indicating where the feed item node originates from:
|
| 55 |
if (isset($feed_element['rdf_about'][0])) {
|
| 56 |
$data['dc:origin'][] = rdf_uri($feed_element['rdf_about'][0]);
|
| 57 |
unset($feed_element['rdf_about']);
|
| 58 |
}
|
| 59 |
|
| 60 |
// Process all RDF statements extracted from the feed item:
|
| 61 |
foreach ($feed_element as $predicate => $values) {
|
| 62 |
$predicate = implode(':', explode('_', $predicate, 2)); // first '_' => ':'
|
| 63 |
$namespace = substr($predicate, 0, strpos($predicate, ':'));
|
| 64 |
|
| 65 |
if (isset($namespaces[$namespace])) { // skip any unknown namespaces
|
| 66 |
foreach (is_array($values) ? $values : array($values) as $value) {
|
| 67 |
$data[$predicate][] = rdf_str_to_val($value); // attempt to cast untyped values
|
| 68 |
}
|
| 69 |
}
|
| 70 |
}
|
| 71 |
|
| 72 |
if ($sub_field == 'system') {
|
| 73 |
// Attempt reverse CCK field mappings using the RDF Schema module:
|
| 74 |
_rdf_feedapi_mapper_cck($node, $data);
|
| 75 |
}
|
| 76 |
else {
|
| 77 |
// Store the extracted RDF statements in the RDF repository
|
| 78 |
// selected as the target for the mapping (the repository name is
|
| 79 |
// passed in $sub_field). We have to do this in an indirect manner
|
| 80 |
// as (for new feed item nodes) the $node object is still being
|
| 81 |
// constructed and therefore doesn't have a $node->nid, and hence
|
| 82 |
// of course doesn't have a URI either. See rdf_nodeapi('prepare')
|
| 83 |
// and rdf_nodeapi('insert') for details on how the $node->rdf and
|
| 84 |
// $node->rdf_options mechanisms work.
|
| 85 |
$node->rdf_options = array('repository' => $sub_field);
|
| 86 |
$node->rdf = $data;
|
| 87 |
}
|
| 88 |
}
|
| 89 |
return $node;
|
| 90 |
}
|
| 91 |
return FALSE;
|
| 92 |
}
|
| 93 |
|
| 94 |
/**
|
| 95 |
* @see rdf_feedapi_mapper()
|
| 96 |
* @private
|
| 97 |
*/
|
| 98 |
function _rdf_feedapi_mapper_cck(&$node, $data) {
|
| 99 |
// TODO: all this probably should go into the RDF Schema module proper.
|
| 100 |
static $var_prefix = 'rdf_schema_property_content_';
|
| 101 |
|
| 102 |
foreach ($data as $predicate => $values) {
|
| 103 |
// Ensure the QName/CURIE property names can be mapped into valid
|
| 104 |
// predicate URIs, and ruthlessly skip any that can't. See the note in
|
| 105 |
// rdf_feedapi_mapper() regarding the undue importance we must place on
|
| 106 |
// namespace prefixes for all this to work.
|
| 107 |
if (($predicate = rdf_qname_to_uri($predicate)) && rdf_is_valid_uri($predicate)) {
|
| 108 |
|
| 109 |
// Check if any RDF Schema-based CCK field mappings have been defined
|
| 110 |
// for this particular predicate URI:
|
| 111 |
$result = db_query('SELECT * FROM {variable} WHERE name LIKE "%s%%" AND value = "%s"', $var_prefix, serialize($predicate));
|
| 112 |
while ($row = db_fetch_object($result)) {
|
| 113 |
|
| 114 |
// For each defined CCK field mapping, graft the property values
|
| 115 |
// onto the $node object in a CCK-compatible manner. The idea is
|
| 116 |
// that CCK will take care of actually storing these values once
|
| 117 |
// hook_nodeapi('insert') or hook_nodeapi('update') gets called.
|
| 118 |
$field_name = substr($row->name, strlen($var_prefix));
|
| 119 |
foreach ($values as $value) {
|
| 120 |
$field = isset($node->$field_name) ? $node->$field_name : array();
|
| 121 |
$field[] = array('value' => rdf_val_to_str($value));
|
| 122 |
$node->$field_name = $field;
|
| 123 |
}
|
| 124 |
}
|
| 125 |
}
|
| 126 |
}
|
| 127 |
|
| 128 |
return $node;
|
| 129 |
}
|