<?php

/**
 * @file
 * Extends Drupal core RDFa markup to support RDFa 1.1.
 */

/**
 * Implements MODULE_preprocess_HOOK().
 */
function rdfa_preprocess_html(&$variables) {
  // Serialize RDF namespaces into an RDFa 1.1 prefix attribute.
  if (function_exists('rdf_get_namespaces')) {
    foreach (rdf_get_namespaces() as $prefix => $uri) {
      $prefixes[] = $prefix . ': ' . $uri;
    }
    $variables['rdf_namespaces'] = ' prefix="' . implode(' ', $prefixes) . '"';
  }
}

/**
 * Implements MODULE_preprocess_HOOK().
 */
function rdfa_preprocess_node(&$variables) {
  // The empty datatype is no longer necessary in RDFa 1.1 whose default
  // behavior is now to interpret the data inside an element as plain literal
  // unless an explicit datatype is asserted in the HTML markup.
  unset($variables['title_attributes_array']['datatype']);
}

/**
 * Implements MODULE_preprocess_HOOK().
 */
function rdfa_preprocess_comment(&$variables) {
  // The empty datatype is no longer necessary in RDFa 1.1 whose default
  // behavior is now to interpret the data inside an element as plain literal
  // unless an explicit datatype is asserted in the HTML markup.
  unset($variables['title_attributes_array']['datatype']);
}

/**
 * Implements MODULE_preprocess_HOOK().
 */
function rdfa_preprocess_field(&$variables) {
  $element = $variables['element'];
  $mapping = rdf_mapping_load($element['#entity_type'], $element['#bundle']);
  $field_name = $element['#field_name'];
  $field_type = $element['#field_type'];

  if (!empty($mapping) && !empty($mapping[$field_name])) {
    // Output RDFa for plain text taxonomy terms as plain literal by overriding
    // core default attributes.
    if ($element['#field_type'] == 'taxonomy_term_reference' && $element['#formatter'] == 'taxonomy_term_reference_plain') {
      foreach ($element['#items'] as $delta => $item) {
        $mapping[$field_name]['type'] = 'property';
        $variables['item_attributes_array'][$delta] = rdf_rdfa_attributes($mapping[$field_name], $item);
      }
    }

    // Remove wrapping property attribute for date field types.
    if (in_array($field_type, array('date', 'datetime', 'datestamp'))) {
      foreach ($element['#items'] as $delta => $item) {
        unset($variables['item_attributes_array'][$delta]['property']);
      }
    }
  }

}


/**
 * Implements MODULE_preprocess().
 *
 * Support for RDFa in Panels. Each panel layout is a theme function and to
 * avoid having to implement a MODULE_preprocess_HOOK() for each of them, we
 * keep all our code in hook_preprocess(). If the hook matches one of the known
 * Panels layout, we add attributes to the top HTML element of the layout for
 * the RDF type of the node (@typeof) and its URI (@about). We also add markup
 * for the title as metadata in one of the visible regions. This is very similar
 * to how things are done in Drupal core for nodes.
 */
function rdfa_preprocess(&$variables, $hook) {
  // List of all panels layout that are supported.
  $panels_layouts = array(
    'panels_flexible',
    'panels_onecol',
    'panels_threecol_25_50_25',
    'panels_threecol_25_50_25_stacked',
    'panels_threecol_33_34_33',
    'panels_threecol_33_34_33_stacked',
    'panels_twocol',
    'panels_twocol_bricks',
    'panels_twocol_stacked',
  );

  if (in_array($hook, $panels_layouts)) {
    // Extract ctools context.
    $context = current($variables['display']->context);
    // Make sure we're dealing with the right kind of data. Only support node
    // for now, because ctools doesn't make it obvious what entity type we are
    // dealing with.
    if (is_object($context) && get_class($context) == 'ctools_context' && $context->is_type('node')) {
      $node = $context->data;
      $uri = entity_uri('node', $node);
    }
    else {
      return;
    }

    // Load RDF mapping to get the RDF type.
    $mapping = rdf_mapping_load('node', $node->type);
    if (!empty($mapping['rdftype'])) {
      // Adds RDFa markup to the panel container like in rdf_preprocess_node().
      // The about attribute specifies the URI of the resource described within
      // the HTML element (panel), while the @typeof attribute indicates its
      // RDF type (e.g., foaf:Document, sioc:Person, and so on.)
      $variables['attributes_array']['resource'] = url($uri['path'], $uri['options']);
      $variables['attributes_array']['typeof'] = $mapping['rdftype'];
    }

    // Add RDFa markup about the title of the node to the first region that has
    // content, starting from the bottom.
    if (!empty($mapping['title']['predicates'])) {
      foreach (array('bottom', 'right', 'middle', 'center', 'left', 'top') as $region) {
        if (!empty($variables['content'][$region])) {
          $metadata[] = array(
            'property' => $mapping['title']['predicates'],
            'content' => $node->title,
          );
          $variables['content'][$region] .= theme('rdf_metadata', array('metadata' => $metadata));
          break;
        }
      }
    }
  }
}

/**
 * Implements MODULE_preprocess_HOOK().
 */
function rdfa_preprocess_panels_flexible(&$variables) {
  // panels_flexible is a theme function and therefore MODULE_preprocess() does
  // not get invoked. Force rdfa_preprocess() to be called so that
  // panels_flexible behaves like a template file.
  template_preprocess($variables, 'panels_flexible');
  rdfa_preprocess($variables, 'panels_flexible');
  template_process($variables, 'panels_flexible');
}

/**
 * Implements MODULE_preprocess_HOOK().
 */
function rdfa_preprocess_username(&$variables) {
  // xml:lang alone is invalid in HTML5. Use the lang attribute instead.
  if (empty($variables['attributes_array']['lang'])) {
    $variables['attributes_array']['lang'] = '';
  }
  unset($variables['attributes_array']['xml:lang']);
  unset($variables['attributes_array']['property']);
  unset($variables['attributes_array']['rel']);
}
