You are here

GenericOpmlParser.php in Feeds 8.3

File

src/Component/GenericOpmlParser.php
View source
<?php

namespace Drupal\feeds\Component;


/**
 * Parses a generic OPML string into an array.
 *
 * @todo Move this to Github.
 */
class GenericOpmlParser {
  use XmlParserTrait;

  /**
   * The XPath query object.
   *
   * @var \DOMXpath
   */
  protected $xpath;

  /**
   * Whether to normalize the case of elements and attributes.
   *
   * @var bool
   */
  protected $normalizeCase;

  /**
   * Constructs a GenericOpmlParser object.
   *
   * @param string $xml
   *   The XML string.
   */
  public function __construct($xml) {
    $this->xpath = new \DOMXPath(static::getDomDocument($xml));
  }

  /**
   * Parses the OPML file.
   *
   * @param bool $normalize_case
   *   (optional) True to convert all attributes to lowercase. False, to leave
   *   them as is. Defaults to false.
   *
   * @return array
   *   A structured array.
   *
   * @todo Document the return value.
   */
  public function parse($normalize_case = FALSE) {
    $this->normalizeCase = $normalize_case;

    // Title is a required field, let parsers assume its existence.
    $return = [
      'head' => [
        '#title' => '',
      ],
    ];
    foreach ($this->xpath
      ->query('/opml/head/*') as $element) {
      if ($this->normalizeCase) {
        $return['head']['#' . strtolower($element->nodeName)] = $element->nodeValue;
      }
      else {
        $return['head']['#' . $element->nodeName] = $element->nodeValue;
      }
    }
    if (isset($return['head']['#expansionState'])) {
      $return['head']['#expansionState'] = array_filter(explode(',', $return['head']['#expansionState']));
    }
    $return['outlines'] = [];
    if ($content = $this->xpath
      ->evaluate('/opml/body', $this->xpath->document)
      ->item(0)) {
      $return['outlines'] = $this
        ->getOutlines($content);
    }
    return $return;
  }

  /**
   * Returns the sub-outline structure.
   *
   * @param \DOMElement $context
   *   The context element to iterate on.
   *
   * @return array
   *   The nested outline array.
   */
  protected function getOutlines(\DOMElement $context) {
    $outlines = [];
    foreach ($this->xpath
      ->query('outline', $context) as $element) {
      $outline = [];
      if ($element
        ->hasAttributes()) {
        foreach ($element->attributes as $attribute) {
          if ($this->normalizeCase) {
            $outline['#' . strtolower($attribute->nodeName)] = $attribute->nodeValue;
          }
          else {
            $outline['#' . $attribute->nodeName] = $attribute->nodeValue;
          }
        }
      }

      // Recurse.
      if ($sub_outlines = $this
        ->getOutlines($element)) {
        $outline['outlines'] = $sub_outlines;
      }
      $outlines[] = $outline;
    }
    return $outlines;
  }

}

Classes

Namesort descending Description
GenericOpmlParser Parses a generic OPML string into an array.