<?php
/**
 * -------------------------------------------------------------------------
 * The XML module to scan XML documents.
 *
 * -------------------------------------------------------------------------
 *
 * Implemented properties below are:
 *     PROTECTED  $reader
 *
 * Overridden methods below are:
 *     run
 *
 * Implemented methods below are:
 *     loadFrom
 *     step
 *     close
 *     getType
 *     getName
 *     getValue
 *     getAs
 *     getText
 *
 * -------------------------------------------------------------------------
 *
 * @package    MimimiFramework
 * @subpackage Modules
 * @copyright  2022 MiMiMi Community
 *             https://mimimi.software/
 * @license    CC BY 4
 *             https://www.creativecommons.org/licenses/by/4.0
 * -------------------------------------------------------------------------
 */

mimimiInclude('Module.php');
class MimimiXml extends MimimiModule {

    /**
     * ---------------------------------------------------------------------
     * Future instance of the XMLReader class.
     *
     * @var object
     * @access protected
     * ---------------------------------------------------------------------
     */

    protected $reader;

    /**
     * ---------------------------------------------------------------------
     * Public method to run this module.
     *
     * @public
     * @param   mixed  $params  Some parameters if you need.
     * @return  mixed           Some results if you need.
     * ---------------------------------------------------------------------
     */

    public function run ( $params = '' ) {
        if (! $this->reader) {
            $this->reader = new XMLReader();
        }
    }

    /**
     * ---------------------------------------------------------------------
     * Public method to load XML from a link.
     *
     * @public
     * @param   string  $uri      Link to a document on the web.
     * @param   string  $charset  Document character set.
     * @return  mixed             The XML content if it was successfully read,
     *                            False if an error occurred.
     * ---------------------------------------------------------------------
     */

    public function loadFrom ( $uri, $charset = 'UTF-8' ) {
        $this->run();
        try {
            $result = @ $this->reader->open($uri, $charset);
        } catch (Exception $e) {
            $result = false;
        }
        return $result;
    }

    /**
     * ---------------------------------------------------------------------
     * Public method to move scanner to the next node in the document.
     *
     * @public
     * @return  bool  True if the scanner moved successfully,
     *                False if the move failed.
     * ---------------------------------------------------------------------
     */

    public function step () {
        return $this->reader
               ? $this->reader->read()
               : false;
    }

    /**
     * ---------------------------------------------------------------------
     * Public method to abort scanning document nodes.
     *
     * @public
     * ---------------------------------------------------------------------
     */

    public function close () {
        if ($this->reader) {
            $this->reader->close();
        }
    }

    /**
     * ---------------------------------------------------------------------
     * Public method to retrieve the type of the current node.
     *
     * @public
     * @return  string  Node type.
     * ---------------------------------------------------------------------
     */

    public function getType () {
        return $this->reader
               ? $this->reader->nodeType
               : '';
    }

    /**
     * ---------------------------------------------------------------------
     * Public method to retrieve the name of the current node.
     *
     * @public
     * @return  string  Node name (in lower case).
     * ---------------------------------------------------------------------
     */

    public function getName () {
        return $this->reader
               ? mb_strtolower($this->reader->name, 'UTF-8')
               : '';
    }

    /**
     * ---------------------------------------------------------------------
     * Public method to retrieve the value of the current node.
     *
     * @public
     * @return  string  Node value.
     * ---------------------------------------------------------------------
     */

    public function getValue () {
        return $this->reader
               ? $this->reader->value
               : '';
    }

    /**
     * ---------------------------------------------------------------------
     * Public method to retrieve the node value as some typed value.
     *
     * @public
     * @param   string  $converter  Name of the module to convert the retrieved value.
     * @param   string  $method     Name of the module method to be used for the transformation.
     * @return  mixed               Node value.
     * ---------------------------------------------------------------------
     */

    public function getAs ( $converter, $method ) {
        $value = $this->getAsString();
        return $this->app->has->$converter
               ? $this->app->$converter->$method($value)
               : $value;
    }

    /**
     * ---------------------------------------------------------------------
     * Public method to retrieve the text content of the current node.
     *
     * @public
     * @param   string  $cleaner  Name of the module to clean up the retrieved text.
     * @param   string  $method   Name of the module method to be used for cleanup.
     * @return  string            Node text.
     * ---------------------------------------------------------------------
     */

    public function getText ( $cleaner, $method ) {
        $text = '';
        if ($this->step()) {
            switch ($this->getType()) {
                case XMLReader::TEXT:
                case XMLReader::CDATA:
                    $text = $this->getValue();
                    if ($this->app->has->$cleaner) {
                        $text = $this->app->$cleaner->$method($text);
                    }
                    break;
            }
        }
        return $text;
    }
};