<?php
namespace ModulesGarden\Servers\ZimbraEmail\App\Libs\Zimbra\Components\Api\Soap\Helpers;
/**
 *
 * Created by PhpStorm.
 * User: Tomasz Bielecki ( tomasz.bi@modulesgarden.com )
 * Date: 28.08.19
 * Time: 14:42
 * Class XmlParser
 */
class XmlParser
{
    /**
     * @var array
     */
    var $stack=array();
    /**
     * @var
     */
    var $stack_ref;
    /**
     * @var array
     */
    var $arrOutput = array();
    /**
     * @var
     */
    var $resParser;
    /**
     * @var
     */
    var $strXmlData;

    /**
     * @param $pos
     */
    public function push_pos(&$pos)
    {
        $this->stack[count($this->stack)]=&$pos;
        $this->stack_ref=&$pos;
    }

    /**
     *
     */
    public function pop_pos()
    {
        unset($this->stack[count($this->stack)-1]);
        $this->stack_ref=&$this->stack[count($this->stack)-1];
    }

    /**
     * @param $strInputXML
     * @return array
     */
    public function parse($strInputXML)
    {
        $this->resParser = xml_parser_create ();
        xml_set_object($this->resParser,$this);
        xml_set_element_handler($this->resParser, "tagOpen", "tagClosed");

        xml_set_character_data_handler($this->resParser, "tagData");

        $this->push_pos($this->arrOutput);

        $this->strXmlData = xml_parse($this->resParser,$strInputXML );
        if(!$this->strXmlData)
        {
            var_dump(sprintf("XML error: %s at line %d",
                xml_error_string(xml_get_error_code($this->resParser)),
                xml_get_current_line_number($this->resParser)));
            die();
        }

        xml_parser_free($this->resParser);

        return $this->arrOutput;
    }

    /**
     * @param $parser
     * @param $name
     * @param $attrs
     */
    public function tagOpen($parser, $name, $attrs)
    {
        if (isset($this->stack_ref[$name]))
        {
            if (!isset($this->stack_ref[$name][0]))
            {
                $tmp=$this->stack_ref[$name];
                unset($this->stack_ref[$name]);
                $this->stack_ref[$name][0]=$tmp;
            }
            $cnt=count($this->stack_ref[$name]);
            $this->stack_ref[$name][$cnt]=array();
            if (isset($attrs))
                $this->stack_ref[$name][$cnt]=$attrs;
            $this->push_pos($this->stack_ref[$name][$cnt]);
        }
        else
        {
            $this->stack_ref[$name]=array();
            if (isset($attrs))
                $this->stack_ref[$name]=$attrs;
            $this->push_pos($this->stack_ref[$name]);
        }
    }

    /**
     * @param $parser
     * @param $tagData
     */
    public function tagData($parser, $tagData)
    {
        if(trim($tagData))
        {
            if(isset($this->stack_ref['DATA']))
                $this->stack_ref['DATA'] .= $tagData;
            else
                $this->stack_ref['DATA'] = $tagData;
        }
    }

    /**
     * @param $parser
     * @param $name
     */
    public function tagClosed($parser, $name)
    {
        $this->pop_pos();
    }
}