You are here

class EndnoteEncoder in Bibliography & Citation 8

Same name and namespace in other branches
  1. 2.0.x modules/bibcite_endnote/src/Encoder/EndnoteEncoder.php \Drupal\bibcite_endnote\Encoder\EndnoteEncoder

Endnote format encoder.

@todo Refactor this class.

Hierarchy

  • class \Drupal\bibcite_endnote\Encoder\EndnoteEncoder implements \Symfony\Component\Serializer\Encoder\DecoderInterface, \Symfony\Component\Serializer\Encoder\EncoderInterface

Expanded class hierarchy of EndnoteEncoder

6 files declare their use of EndnoteEncoder
Endnote7DecodeTest.php in modules/bibcite_endnote/tests/src/Kernel/Endnote7DecodeTest.php
Endnote7EncodeTest.php in modules/bibcite_endnote/tests/src/Kernel/Endnote7EncodeTest.php
Endnote8DecodeTest.php in modules/bibcite_endnote/tests/src/Kernel/Endnote8DecodeTest.php
Endnote8EncodeTest.php in modules/bibcite_endnote/tests/src/Kernel/Endnote8EncodeTest.php
TaggedDecodeTest.php in modules/bibcite_endnote/tests/src/Kernel/TaggedDecodeTest.php

... See full list

2 string references to 'EndnoteEncoder'
bibcite_endnote.bibcite_format.yml in modules/bibcite_endnote/bibcite_endnote.bibcite_format.yml
modules/bibcite_endnote/bibcite_endnote.bibcite_format.yml
bibcite_endnote.services.yml in modules/bibcite_endnote/bibcite_endnote.services.yml
modules/bibcite_endnote/bibcite_endnote.services.yml
3 services use EndnoteEncoder
bibcite_endnote.encoder.endnote7 in modules/bibcite_endnote/bibcite_endnote.services.yml
Drupal\bibcite_endnote\Encoder\EndnoteEncoder
bibcite_endnote.encoder.endnote8 in modules/bibcite_endnote/bibcite_endnote.services.yml
Drupal\bibcite_endnote\Encoder\EndnoteEncoder
bibcite_endnote.encoder.endnote_tagged in modules/bibcite_endnote/bibcite_endnote.services.yml
Drupal\bibcite_endnote\Encoder\EndnoteEncoder

File

modules/bibcite_endnote/src/Encoder/EndnoteEncoder.php, line 15

Namespace

Drupal\bibcite_endnote\Encoder
View source
class EndnoteEncoder implements EncoderInterface, DecoderInterface {

  /**
   * The format that this encoder supports.
   *
   * @var array
   */
  protected static $format = [
    'endnote7',
    'endnote8',
    'tagged',
  ];

  /**
   * {@inheritdoc}
   */
  public function supportsDecoding($format) {
    return in_array($format, static::$format);
  }

  /**
   * {@inheritdoc}
   */
  public function decode($data, $format, array $context = []) {
    if ($format === 'tagged') {
      return $this
        ->decodeTagged($data);
    }
    $result = [];
    try {
      $sxml = new SimpleXMLElement($data);
    } catch (\Exception $ex) {
      $format_definition = \Drupal::service('plugin.manager.bibcite_format')
        ->getDefinition($format);
      $format_label = $format_definition['label'];
      throw new UnexpectedValueException("Incorrect '{$format_label}' format.");
    }
    $records = $sxml->records;
    $config = \Drupal::config('bibcite_entity.mapping.' . $format);
    $indexes = $config
      ->get('indexes');
    if ($records instanceof SimpleXMLElement) {
      foreach ($records
        ->children() as $record) {
        $rec = [];
        if ($record instanceof SimpleXMLElement) {
          foreach ($record
            ->children() as $child) {
            if ($child instanceof SimpleXMLElement) {
              switch ($child
                ->getName()) {
                case 'REFERENCE_TYPE':
                case 'ref-type':
                  if (strlen($child
                    ->__toString()) > 0) {
                    $type = array_search($child
                      ->__toString(), $indexes);
                    if ($type) {
                      $rec['type'] = $type;
                    }
                    else {
                      $rec['type'] = -1;
                    }
                  }
                  break;
                case 'DATES':
                case 'dates':
                  foreach ($child
                    ->children() as $dates) {
                    if ($dates instanceof SimpleXMLElement) {
                      switch ($dates
                        ->getName()) {
                        case 'YEAR':
                        case 'year':
                          $rec[$dates
                            ->getName()] = $this
                            ->getString($dates);
                          break;
                        case 'DATE':
                        case 'date':
                          $rec[$dates->{'pub-dates'}
                            ->getName()] = $this
                            ->getString($dates->{'pub-dates'});
                          break;
                      }
                    }
                  }
                  break;
                case 'CONTRIBUTORS':
                case 'contributors':
                  foreach ($child
                    ->children() as $authors) {
                    if ($authors instanceof SimpleXMLElement) {
                      foreach ($authors
                        ->children() as $author) {

                        // Hotfix: contributorKey property is hardcoded in the
                        // bibcite_endnote.services.xml. Access authors by this key
                        // explicitly for the moment, mapping is not working anyway.
                        // @todo Rework this place when mapping of authors is fixed and flexible.
                        $rec['authors'][] = $this
                          ->getString($author);
                      }
                    }
                  }
                  break;
                case 'TITLES':
                case 'titles':
                  foreach ($child
                    ->children() as $title) {
                    if ($title instanceof SimpleXMLElement) {
                      $rec[$title
                        ->getName()] = $this
                        ->getString($title);
                    }
                  }
                  break;
                case 'KEYWORDS':
                case 'keywords':
                  foreach ($child
                    ->children() as $keyword) {
                    if ($keyword instanceof SimpleXMLElement) {
                      $rec['keywords'][] = $this
                        ->getString($keyword);
                    }
                  }
                  break;
                case 'source-app':
                  break;
                default:
                  $rec[$child
                    ->getName()] = $this
                    ->getString($child);
                  break;
              }
            }
          }
        }
        $result[] = $rec;
      }
    }
    return $result;
  }

  /**
   * Get string from element.
   *
   * @param \SimpleXMLElement $element
   *   Element value.
   *
   * @return string
   *   Result string.
   */
  private function getString($element) {
    return $element->style
      ->__toString() ?: $element
      ->__toString();
  }

  /**
   * {@inheritdoc}
   */
  public function supportsEncoding($format) {
    return in_array($format, static::$format);
  }

  /**
   * {@inheritdoc}
   */
  public function encode($data, $format, array $context = []) {
    if (isset($data['type'])) {
      $data = [
        $data,
      ];
    }
    if ($format === 'tagged') {
      return $this
        ->encodeTagged($data);
    }
    $sxml = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><xml><records></records></xml>');
    $records = $sxml->records;
    foreach ($data as $id => $ref) {
      if ($records instanceof SimpleXMLElement) {
        switch ($format) {
          case 'endnote7':
            $record = $records
              ->addChild('RECORD');
            $contrib_key = 'CONTRIBUTORS';
            $author_key = 'AUTHOR';
            $titles_key = 'TITLES';
            $keywords_key = 'KEYWORDS';
            $dates_key = 'DATES';
            $web_key = 'WEB-URLS';
            $pub_key = 'PUB-DATES';
            $keyword_key = 'KEYWORD';
            $authors_key = 'AUTHORS';
            break;
          case 'endnote8':
          default:
            $record = $records
              ->addChild('record');
            $contrib_key = 'contributors';
            $author_key = 'author';
            $titles_key = 'titles';
            $keywords_key = 'keywords';
            $dates_key = 'dates';
            $web_key = 'web-urls';
            $pub_key = 'pub-dates';
            $keyword_key = 'keyword';
            $authors_key = 'authors';
            break;
        }
        $source = $record
          ->addChild('source-app', 'Drupal-Bibcite');
        $source
          ->addAttribute('name', 'Bibcite');
        $source
          ->addAttribute('version', '8.x');
        $config = \Drupal::config('bibcite_entity.mapping.' . $format);
        $indexes = $config
          ->get('fields');
        $ref['type_en8id'] = $config
          ->get('indexes')[$ref['type']];
        $type_key = array_search('type', $indexes);
        if ($type_key) {
          $record
            ->addChild($type_key, $ref['type_en8id']);
        }
        unset($ref[$type_key]);
        unset($ref['type']);
        unset($ref['type_en8id']);
        unset($ref['reference']);
        if ($authors_key) {
          $authors = $record
            ->addChild($contrib_key)
            ->addChild($authors_key);

          // Hotfix: contributorKey property is hardcoded in the
          // bibcite_endnote.services.xml. Access authors by this key
          // explicitly for the moment, mapping is not working anyway.
          // @todo Rework this place when mapping of authors is fixed and flexible.
          if (isset($ref['authors'])) {
            foreach ($ref['authors'] as $author) {
              $author_xml = $authors
                ->addChild($author_key);
              $this
                ->setStyledText($author_xml, $author);
            }
            unset($ref['authors']);
          }
        }
        $titles = $record
          ->addChild($titles_key);
        $this
          ->addTitles($titles, $ref, $indexes);
        $keywords = $record
          ->addChild($keywords_key);
        $this
          ->addKeywords($keywords, $ref, $indexes, $keyword_key);
        unset($ref[$keywords_key]);
        $dates = $record
          ->addChild($dates_key);
        $this
          ->addDates($dates, $ref, $indexes, $pub_key);
        $urls_key = array_search('urls', $indexes);
        if (isset($ref[$urls_key])) {
          $this
            ->addTag($record
            ->addChild($web_key), $urls_key, $ref[$urls_key]);
          unset($ref[$urls_key]);
        }

        // Only in endnote X3.
        if (isset($ref['full-title'])) {
          $this
            ->addTag($record
            ->addChild('periodical'), 'full-title', $ref['full-title']);
          unset($ref['full-title']);
        }
        $this
          ->addFields($record, $ref);
      }
    }
    return $sxml
      ->asXML();
  }

  /**
   * Add titles to xml.
   *
   * @param \SimpleXMLElement $xml
   *   Parent XmlElement.
   * @param mixed $ref
   *   Our reference.
   * @param array $indexes
   *   Mapping indexes.
   */
  private function addTitles(&$xml, &$ref, $indexes) {
    foreach ($ref as $key => $value) {
      if (array_key_exists($key, $indexes)) {
        $title_key = $indexes[$key];
        switch ($title_key) {
          case 'title':
          case 'secondary-title':
          case 'tertiary-title':
          case 'alt-title':
          case 'short-title':
          case 'translated-title':
            $this
              ->addTag($xml, $key, $value);
            unset($ref[$key]);
            break;
        }
      }
    }
  }

  /**
   * Add keywords to xml.
   *
   * @param \SimpleXMLElement $xml
   *   Parent XmlElement.
   * @param mixed $ref
   *   Our reference.
   * @param array $indexes
   *   Mapping indexes.
   */
  private function addKeywords(&$xml, &$ref, $indexes, $keyword_key) {
    foreach ($ref as $key => $value) {
      switch ($key) {
        case 'keywords':
          foreach ($ref[$key] as $keyword) {
            $this
              ->addTag($xml, $keyword_key, $keyword);
          }
          unset($ref[$key]);
          break;
      }
    }
  }

  /**
   * Add dates to xml.
   *
   * @param \SimpleXMLElement $xml
   *   Parent XmlElement.
   * @param mixed $ref
   *   Our reference.
   * @param array $indexes
   *   Mapping indexes.
   * @param string $pub_key
   *   Key for pub-date.
   */
  private function addDates(&$xml, &$ref, $indexes, $pub_key) {
    foreach ($ref as $key => $value) {
      switch ($key) {
        case 'date':
          $date = $xml
            ->addChild($pub_key);
          $this
            ->addTag($date, $key, $value);
          unset($ref[$key]);
          break;
        case 'year':
          $this
            ->addTag($xml, $key, $value);
          unset($ref[$key]);
          break;
      }
    }
  }

  /**
   * Add fields to xml.
   *
   * @param \SimpleXMLElement $xml
   *   Parent XmlElement.
   * @param mixed $ref
   *   Our reference.
   */
  private function addFields(&$xml, &$ref) {
    foreach ($ref as $key => $value) {
      $this
        ->addTag($xml, $key, $value);
      unset($ref[$key]);
    }
  }

  /**
   * Add value to xml tag.
   *
   * @param \SimpleXMLElement $xml
   *   Parent XmlElement.
   * @param string $tag
   *   Xml tag to add.
   * @param string $value
   *   Text to set.
   */
  private function addTag(&$xml, $tag, $value) {
    $xc = $xml
      ->addChild($tag);
    $this
      ->setStyledText($xc, $value);
  }

  /**
   * Add xml child style.
   *
   * @param \SimpleXMLElement $xml
   *   Parent XmlElement.
   * @param string $text
   *   Text to set.
   */
  private function setStyledText(&$xml, $text) {
    $styled = $xml
      ->addChild('style', $text);
    $styled
      ->addAttribute('face', 'normal');
    $styled
      ->addAttribute('font', 'default');
    $styled
      ->addAttribute('size', '100%');
  }

  /**
   * Decode tagged format function.
   */
  private function decodeTagged($data) {
    $result = [];
    $config = \Drupal::config('bibcite_entity.mapping.tagged');
    $indexes = $config
      ->get('indexes');
    $data = explode("\n\n", $data);
    foreach ($data as $i => &$record) {
      $fields = explode("\n", $record);
      foreach ($fields as $field) {
        $key = array_search(substr($field, 0, 2), $indexes);
        $value = substr($field, 3);
        if ($key) {
          if (isset($result[$i][$key])) {
            if (is_array($result[$i][$key])) {
              $result[$i][$key][] = $value;
            }
            else {
              $val = $result[$i][$key];
              unset($result[$i][$key]);
              $result[$i][$key][] = $val;
              $result[$i][$key][] = $value;
            }
          }
          else {
            $result[$i][$key] = $value;
          }
        }
      }
    }
    return $result;
  }

  /**
   * Encode tagged format function.
   */
  private function encodeTagged($data) {
    $data = array_map(function ($raw) {
      return $this
        ->buildEntry($raw);
    }, $data);
    return implode("\n", $data);
  }

  /**
   * Build tagged entry string.
   *
   * @param array $data
   *   Array of tagged values.
   *
   * @return string
   *   Formatted tagged string.
   */
  protected function buildEntry(array $data) {
    $config = \Drupal::config('bibcite_entity.mapping.tagged');
    $indexes = $config
      ->get('indexes');
    $entry = NULL;

    // For not duplicating pages parse.
    $pages_parsed = FALSE;
    foreach ($data as $key => $value) {
      if (is_array($value)) {
        if (isset($indexes[$key])) {
          $entry .= $this
            ->buildMultiLine($indexes[$key], $value);
        }
      }
      else {
        if (isset($indexes[$key])) {
          $entry .= $this
            ->buildLine($indexes[$key], $value);
        }
      }
    }
    return $entry;
  }

  /**
   * Build multi line entry.
   *
   * @param string $key
   *   Line key.
   * @param array $value
   *   Array of multi line values.
   *
   * @return string
   *   Multi line entry.
   */
  protected function buildMultiLine($key, array $value) {
    $lines = '';
    foreach ($value as $item) {
      $lines .= $this
        ->buildLine($key, $item);
    }
    return $lines;
  }

  /**
   * Build entry line.
   *
   * @param string $key
   *   Line key.
   * @param string $value
   *   Line value.
   *
   * @return string
   *   Entry line.
   */
  protected function buildLine($key, $value) {
    return $key . ' ' . $value . "\n";
  }

}

Members

Namesort descending Modifiers Type Description Overrides
EndnoteEncoder::$format protected static property The format that this encoder supports.
EndnoteEncoder::addDates private function Add dates to xml.
EndnoteEncoder::addFields private function Add fields to xml.
EndnoteEncoder::addKeywords private function Add keywords to xml.
EndnoteEncoder::addTag private function Add value to xml tag.
EndnoteEncoder::addTitles private function Add titles to xml.
EndnoteEncoder::buildEntry protected function Build tagged entry string.
EndnoteEncoder::buildLine protected function Build entry line.
EndnoteEncoder::buildMultiLine protected function Build multi line entry.
EndnoteEncoder::decode public function
EndnoteEncoder::decodeTagged private function Decode tagged format function.
EndnoteEncoder::encode public function
EndnoteEncoder::encodeTagged private function Encode tagged format function.
EndnoteEncoder::getString private function Get string from element.
EndnoteEncoder::setStyledText private function Add xml child style.
EndnoteEncoder::supportsDecoding public function
EndnoteEncoder::supportsEncoding public function