Files
grzanieplus.pl/plugins/stTaskSchedulerImportPlugin/lib/reader/stTaskSchedulerImportXmlReader.class.php
2025-03-12 17:06:23 +01:00

264 lines
5.9 KiB
PHP

<?php
class stTaskSchedulerImportXmlReader implements stTaskSchedulerImportReaderInterface
{
const BOOL_VALUES = [
'true' => true,
'yes' => true,
'false' => false,
'no' => false,
];
/**
*
* @var XMLReader
*/
protected $xmlReader;
/**
*
* @var string
*/
protected $file;
/**
*
* @var string
*/
protected $filterNode;
/**
*
* @var null|int
*/
protected $filterNodeDepth;
/**
*
* @var null|int
*/
protected $count = null;
/**
*
* @var int
*/
protected $offset = 0;
public function __clone()
{
$this->xmlReader = new XMLReader();
$this->open($this->file);
}
/**
*
* @param string $filterNode
* @param null|int $filterNodeDepth
* @return void
*/
public function __construct(string $filterNode, ?int $filterNodeDepth = null)
{
$this->xmlReader = new \XMLReader();
$this->setNodeFilterCriteria($filterNode, $filterNodeDepth);
}
public function getFiletypeExtension(): string
{
return 'xml';
}
public function setNodeFilterCriteria(string $node, ?int $depth = null)
{
$this->filterNode = $node;
$this->filterNodeDepth = $depth;
}
public function open(string $file): bool
{
$this->file = $file;
$this->offset = 0;
return $this->xmlReader->open($file);
}
public function isValid(): bool
{
$result = $this->getNextNode();
$this->rewind();
return $result;
}
public function rewind(): void
{
if ($this->offset > 0)
{
$this->close();
$this->open($this->file);
}
}
public function count(): int
{
if (null === $this->count)
{
$this->rewind();
$this->count = 0;
while ($this->getNextNode())
{
$this->count++;
}
$this->rewind();
}
return $this->count;
}
public function setOffset(int $offset): void
{
if ($this->offset != $offset)
{
if ($offset < $this->offset)
{
$this->rewind();
}
while ($this->offset < $offset && $this->getNextNode())
{
}
}
}
public function getOffset(): int
{
return $this->offset;
}
public function read(\Closure $callback): bool
{
return $this->getNextNode($callback);
}
public function close(): void
{
if ($this->xmlReader)
{
$this->xmlReader->close();
}
}
public function getNextNode(?\Closure $callback = null): bool
{
while($this->xmlReader->read())
{
if ($this->xmlReader->nodeType == XMLReader::ELEMENT && (null === $this->filterNodeDepth || $this->xmlReader->depth == $this->filterNodeDepth) && (null === $this->filterNode || $this->xmlReader->name == $this->filterNode))
{
$this->offset++;
if (null === $this->filterNodeDepth)
{
$this->filterNodeDepth = $this->xmlReader->depth;
}
if (null !== $callback)
{
$xml = $this->xmlReader->readOuterXml();
$dom = new DOMDocument('1.0', 'UTF-8');
$dom->preserveWhiteSpace = false;
$dom->loadXml($xml);
$data = $this->parseNodeToArray($dom->documentElement);
$callback($data);
}
return true;
}
}
return false;
}
private function parseNodeToArray(\DOMNode $node, ?array &$output = null): array
{
$value = [
'@attributes' => [],
'@value' => null,
];
if (null === $output)
{
$output = array();
}
if ($node->hasAttributes())
{
$attributes = array();
/**
* @var \DOMNode $attribute
*/
foreach ($node->attributes as $attribute)
{
$attributes[$attribute->nodeName] = $this->convertValue($attribute->nodeValue);
}
$value['@attributes'] = $attributes;
}
if ($node->hasChildNodes())
{
if ($node->childNodes->length == 1 && in_array($node->childNodes->item(0)->nodeType, array(XML_CDATA_SECTION_NODE, XML_TEXT_NODE)))
{
$value['@value'] = trim($node->textContent);
}
else
{
/**
* @var \DOMNode
*/
foreach ($node->childNodes as $child)
{
$this->parseNodeToArray($child, $value);
}
}
}
if (!isset($output[$node->nodeName]))
{
$output[$node->nodeName] = $value;
}
else
{
if (is_string($output[$node->nodeName]))
{
$output[$node->nodeName] = array(0 => $output[$node->nodeName]);
}
elseif (!isset($output[$node->nodeName][0]))
{
$output[$node->nodeName] = array(0 => $output[$node->nodeName]);
}
$output[$node->nodeName][] = $value;
}
return $output;
}
/**
* Funkcja pomocnicza konwertująca wartość string na odpowiadające im wartości bool
*
* @param string $value
* @return string|bool
*/
private function convertValue(string $value)
{
$value = trim($value);
return isset(self::BOOL_VALUES[$value]) ? self::BOOL_VALUES[$value] : $value;
}
}