You are here

protected function views_oai_pmh_plugin_style::append_record_metadata in Views OAI-PMH 7.3

Builds the core of a record's XML.

Builds the core of a record's XML by using the mappings configured in the view.

2 calls to views_oai_pmh_plugin_style::append_record_metadata()
views_oai_pmh_plugin_style::get_record_render in plugins/views_oai_pmh_plugin_style.inc
Renders a response to the 'GetRecord' OAI-PMH request.
views_oai_pmh_plugin_style::list_records_render in plugins/views_oai_pmh_plugin_style.inc
Renders a response to the 'ListRecords' OAI-PMH request.

File

plugins/views_oai_pmh_plugin_style.inc, line 458
Contains the base OAI-PMH style plugin.

Class

views_oai_pmh_plugin_style
Views OAI-PMH_plugin style.

Code

protected function append_record_metadata($parent, $row_index, $row) {
  $metadata_element = $this->xml
    ->createElement('metadata');
  $parent
    ->appendChild($metadata_element);
  $metadata_root = $this->xml
    ->createElement($this->request->metadata_format->root_element);
  $metadata_element
    ->appendChild($metadata_root);

  // Getting the configurable root elements.
  $configurable_root_attributes = $this
    ->get_root_attribute_elements($row_index, $this->view->field);

  // Merging all the root attributes.
  $root_attributes = array_merge($this->request->metadata_format->root_attributes, $configurable_root_attributes);

  // Setting the root attributes.
  $this
    ->xml_set_attributes($metadata_root, $root_attributes);

  // Prepare XPath object for later use.
  $xpath = new DOMXPath($this->xml);
  foreach ($this->request->metadata_format->namespaces as $namespace_prefix => $namespace_uri) {
    if (!$xpath
      ->registerNamespace($namespace_prefix, $namespace_uri)) {
      watchdog('views_oai_pmh', 'Error registering namespace @uri', array(
        '@uri' => $namespace_uri,
      ), WATCHDOG_ERROR);
    }
  }

  // Available attributes, as an array of field ids keyed by attribute name.
  $available_attributes = array();
  foreach ($this->view->field as $field_name => $field) {
    list($mapping, $is_attribute) = $this
      ->get_mapping($field_name);
    if ($is_attribute) {

      // Field is mapped to an attribute. Mark it is available for an upcoming
      // element.
      $available_attributes[$mapping] = $field_name;
    }
    else {

      // Field is mapped to an element. Build the element in the XML tree.
      $used_attributes = array();

      // $field_value is the output value from the view exactly as it should
      // be shown if the view mode was a page.
      $field_value = $this
        ->get_field($row_index, $field_name);
      if ($field->options['exclude'] || empty($mapping) || empty($field_value) && $field->options['hide_empty']) {
        if (!empty($mapping)) {

          // Eat attributes that would have been consumed by the field's
          // mapping, had the field not been empty. This prevents attributes
          // from spilling to subsequent fields they were not intended for.
          $this
            ->eat_attributes(explode('/', $mapping), $available_attributes);
        }

        // Skip this field.
        continue;
      }

      // Convert field value to an array.
      if (isset($field->multiple) && $field->multiple) {
        $field_values = explode($field->options['separator'], $field_value);
      }
      else {
        $field_values = array(
          $field_value,
        );
      }

      // Build XML elements for each value.
      // Track position of current field values.
      $delta = 0;
      foreach ($field_values as $field_value) {

        // Path of the current element in the mapping string.
        $mapping_path = array();

        // Path of the current element, free of mapping codes.
        $element_path = array();
        $nodes_in_element_path = array();
        $parent = $metadata_root;
        foreach (explode('/', $mapping) as $element) {
          $mapping_path[] = $element;
          if (implode('/', $mapping_path) != $mapping) {

            // We're not on a tree leaf. If the element has a '[]' suffix,
            // we'll try to work under an existing node whose position
            // matches $delta. If the element has a '[n]' suffix, we'll try
            // to work under an existing node at position 'n'. If neither
            // case applies, a new node will get created.
            $element_xpath_pattern = $this
              ->prepare_tag($element, $delta);

            // Check if child exists.
            $existing_nodes = $xpath
              ->query($element_xpath_pattern, $parent);
            if ($existing_nodes !== FALSE && $existing_nodes->length) {

              // Found an existing node matching the path. No need to create a
              // new one.
              $element_node = $existing_nodes
                ->item(0);
            }
            else {

              // Create a new node.
              $element_node = $this->xml
                ->createElement($element);
              $parent
                ->appendChild($element_node);
            }
          }
          else {

            // We're on a tree leaf. Create a new node no matter what, with
            // the field value.
            $this
              ->prepare_tag($element, $delta);
            $element_node = $this->xml
              ->createElement($element, check_plain($field_value));
            $parent
              ->appendChild($element_node);
          }
          $element_path[] = $element;
          $nodes_in_element_path[implode('/', $element_path)] = $element_node;

          // Prepare next iteration.
          $parent = $element_node;
        }
        $this
          ->apply_attributes($row_index, $field, $delta, $nodes_in_element_path, $available_attributes, $used_attributes);

        // Moving on to next field value.
        $delta++;
      }

      // Remove attributes that have been consumed by this field.
      $available_attributes = array_diff_key($available_attributes, $used_attributes);
    }
  }
}