<?php
class ItemGroup
{
private int $id;
/**
* @var stdClass[]
*/
private array $items;
public function __construct(int $id, array $items)
{
$this->id = $id;
$this->items = $items;
}
public function getId(): int
{
return $this->id;
}
public function getItems(): array
{
return $this->items;
}
}
class Entry
{
private string $content;
public function __construct(string $content)
{
$this->content = trim($content);
}
public function getGroupId(): int
{
return (int) $this->content;
}
public function isGroupId(): bool
{
return is_numeric($this->content);
}
public function getHeader(): array
{
$header = preg_split("/\s+/", $this->content);
$header[0] = substr($header[0], 2); // Remove slashes: //Type -> Type
return $header;
}
public function isHeader(): bool
{
return str_starts_with($this->content, '//Type');
}
public function getItem(): array
{
return preg_split("/\"*\s+\s{2}\"*/", $this->content);
}
public function isItem(): bool
{
return !($this->isEmpty() ||
$this->isGroupId() ||
$this->isComment() ||
$this->isHeader() ||
$this->isEndOfGroup());
}
public function isEndOfGroup(): bool
{
return $this->content === 'end';
}
private function isComment(): bool
{
return str_starts_with($this->content, '//') && !$this->isHeader();
}
private function isEmpty(): bool
{
return strlen($this->content) === 0;
}
}
class Parser implements Iterator
{
private array $lines;
private int $position;
private function __construct(array $lines)
{
$this->lines = $lines;
$this->position = 0;
}
/**
* @param array $lines
* @return ItemGroup[]
*/
public static function parse(array $lines): array
{
$parser = new Parser($lines);
$groups = [];
$groupId = -1;
$header = [];
$items = [];
foreach ($parser as $entry) {
if ($entry->isGroupId()) {
$groupId = $entry->getGroupId();
} elseif ($entry->isHeader()) {
$header = $entry->getHeader();
} elseif ($entry->isItem()) {
$item = $entry->getItem();
$obj = new stdClass();
$items[] = $obj;
for ($i = 0; $i < count($item); $i++) {
$title = $header[$i];
$propertyName = strlen($title) > 2 ? lcfirst($title) : strtolower($title);
$obj->$propertyName = $item[$i];
}
} elseif ($entry->isEndOfGroup()) {
$groups[] = new ItemGroup($groupId, $items);
$groupId = -1;
$header = [];
$items = [];
}
}
return $groups;
}
public function current(): Entry
{
return new Entry($this->lines[$this->position]);
}
public function next(): void
{
$this->position++;
}
public function key(): int
{
return $this->position;
}
public function valid(): bool
{
return $this->position > -1 && $this->position < count($this->lines);
}
public function rewind(): void
{
$this->position = 0;
}
}
// Example
$groups = Parser::parse(file('items.txt'));
foreach ($groups as $group) {
echo '<pre>';
echo 'ID: ' . $group->getId() . '; Items: ' . count($group->getItems()) . "\n";
foreach ($group->getItems() as $item) {
echo 'Name: ' . $item->name . '; Level: ' . $item->level . "\n";
}
echo '</pre>';
}