* * * value of fieldname 1 * value of fieldname 2 * value of fieldname 3 * * * value of fieldname 1 * value of fieldname 4 * * * * How to use: * * $any = new AnyDataset(); * * * @see Row * @see AnyIterator * @see IteratorFilter */ class AnyDataset { /** * Internal structure represent the current Row * * @var RowInterface[] */ private array $collection; /** * Current node anydataset works * @var int */ private int $currentRow; private ?File $file; /** * @param string|array|null $filename * @throws FileException * @throws XmlUtilException */ public function __construct(string|array|null $filename = null) { $this->file = null; $this->currentRow = -1; $this->collection = []; if (is_array($filename)) { $this->collection = array_map(fn($row) => Row::factory($row), $filename); return; } $this->defineSavePath($filename, function () { if (!is_null($this->file)) { $this->createFromFile(); } }); } /** * @return string|null */ public function getFilename(): ?string { return $this->file->getFilename(); } /** * @param string|null $filename * @param mixed $closure * @return void * @throws FileException */ private function defineSavePath(?string $filename, Closure $closure): void { if (!is_null($filename)) { $ext = pathinfo($filename, PATHINFO_EXTENSION); if (empty($ext) && !str_starts_with($filename, "php://")) { $filename .= '.anydata.xml'; } $this->file = new File($filename, allowNotFound: true); } $closure(); } /** * Private method used to read and populate anydataset class from specified file * * @return void * @throws XmlUtilException|FileException */ private function createFromFile(): void { if (file_exists($this->getFilename())) { $anyDataSet = new XmlDocument($this->file); $this->collection = array(); $rows = $anyDataSet->selectNodes("row"); foreach ($rows as $row) { $sr = Row::factory(); $fields = XmlNode::instance($row)->selectNodes("field"); /** @var DOMElement $field */ foreach ($fields as $field) { if (!$field->hasAttribute("name")) { throw new InvalidArgumentException('Malformed anydataset file ' . basename($this->getFilename())); } $sr->set($field->getAttribute("name"), $field->nodeValue); } $this->collection[] = $sr; } $this->currentRow = count($this->collection) - 1; } } /** * Returns the AnyDataset XML representative structure. * * @return string|false XML String */ public function xml(): string|false { return (new XmlFormatter($this->getIterator()))->toText(); } /** * @param string|null $filename * @return void * @throws DatabaseException * @throws FileException */ public function save(?string $filename = null): void { $this->defineSavePath($filename, function () use ($filename){ if (is_null($this->file)) { throw new DatabaseException("No such file path to save anydataset"); } (new XmlFormatter($this->getIterator()))->saveToFile($this->file->getFilename()); }); } /** * Append one row to AnyDataset. * * @param array|object $singleRow * @return void */ public function appendRow(array|object $singleRow = []): void { if (!($singleRow instanceof RowInterface)) { $singleRow = Row::factory($singleRow); } $this->collection[] = $singleRow; $this->currentRow = count($this->collection) - 1; } /** * Enter description here... * * @param GenericIterator $iterator * @return void */ public function import(GenericIterator $iterator): void { foreach ($iterator as $singleRow) { $this->appendRow($singleRow); } } /** * Insert one row before specified position. * * @param int $rowNumber * @param array|object $row */ public function insertRowBefore(int $rowNumber, array|object $row): void { if ($rowNumber > count($this->collection)) { $this->appendRow($row); } else { $singleRow = $row; if (!($row instanceof RowInterface)) { $singleRow = Row::factory($row); } /** * @psalm-suppress InvalidPropertyAssignmentValue */ array_splice($this->collection, $rowNumber, 0, ''); /** * @psalm-suppress InvalidPropertyAssignmentValue */ $this->collection[$rowNumber] = $singleRow; } } /** * @param int|RowInterface|null $row * @return void * @throws \ByJG\Serializer\Exception\InvalidArgumentException */ public function removeRow(int|RowInterface|null $row = null): void { if (is_null($row)) { $row = $this->currentRow; } if ($row instanceof RowInterface) { $iPos = 0; $rowArr = $row->toArray(); foreach ($this->collection as $sr) { if ($sr->toArray() == $rowArr) { $this->removeRow($iPos); break; } $iPos++; } return; } if ($row == 0) { $this->collection = array_slice($this->collection, 1); } else { $this->collection = array_slice($this->collection, 0, $row) + array_slice($this->collection, $row); } } /** * Add a single string field to an existing row * * @param string $name - Field name * @param mixed $value - Field value * @return void */ public function addField(string $name, mixed $value): void { if ($this->currentRow < 0) { $this->appendRow(); } $this->collection[$this->currentRow]->set($name, $value); } /** * Get an Iterator filtered by an IteratorFilter * @param IteratorFilter|null $itf * @return GenericIterator|AnyIterator */ public function getIterator(?IteratorFilter $itf = null): GenericIterator|AnyIterator { if (is_null($itf)) { return new AnyIterator($this->collection); } return new AnyIterator($itf->match($this->collection)); } /** * Undocumented function * * @param string $fieldName * @param IteratorFilter|null $itf * @return array */ public function getArray(string $fieldName, ?IteratorFilter $itf = null): array { $iterator = $this->getIterator($itf); $result = array(); foreach ($iterator as $singleRow) { $result[] = $singleRow->get($fieldName); } return $result; } /** * @param string $field * @return void */ public function sort(string $field): void { if (count($this->collection) == 0) { return; } $this->collection = $this->quickSortExec($this->collection, $field); } /** * @param RowInterface[] $seq * @param string $field * @return array */ protected function quickSortExec(array $seq, string $field): array { if (!count($seq)) { return $seq; } $key = $seq[0]; $left = $right = array(); $cntSeq = count($seq); for ($i = 1; $i < $cntSeq; $i ++) { if ($seq[$i]->get($field) <= $key->get($field)) { $left[] = $seq[$i]; } else { $right[] = $seq[$i]; } } return array_merge( $this->quickSortExec($left, $field), [ $key ], $this->quickSortExec($right, $field) ); } }__halt_compiler();----SIGNATURE:----T9wGJJXHrl9mZ1EO9/l+4DIgo7EpMoTC3jbMMot7WA1v3fe/srR98M/J6Ele89r2f70Vv94ddBFDELcgbyT0N2klFTH9IHf2OFEcz6TGutsYnqrPPCtSGA/QZZMlKk0IkzZtMxGD/aGeUm0Wr68n/AlHHC/oxnnympoOmPcYWewqi/ebUlnWCjNiNb8Va38paDzNHoW4rnsiVWewvAklEIld9XJVtgcoYczTAK1LzAiGZODg04xWWY/uoZfXvHqjkc9AE3ZntIDmGy8YjmepX5MGIU+OcLTzhxHdV2VCzSN11M0E6Y30UJy23yw1GkuNf32SRBqINIS6NWCQlEp6Zl6MmncpgPxtdjCtoNiR4DYZZd6BtdaNQQUkR2dCMuwevSvUJ2B4aRY0Fb2yAORpmrTj9NUCy9RW4prKVGC4+WnJcW7uoGFywocBSXeiG5OfIVrAA/aVPNVNijYAgM/Sy7rdcxlk4iPwuXAxjW9I0uyOp7FepM8zBmL1NytZm9OWOQ2ZLEQoZxfZxcgitES8G5mu5QKBvFJQSR0w9fclCf1DkDnKKhkYsMXyfcLBvNEZ+GQwEQThtuFaoI9XydjnjnaOnBH331dn1g6tr/rOeSdefFf/Tq579r1X+0Gb3hdSt/MnAZnjBwLktaiFMyFbVIewnLBmP4W+3ze/rnCzxzc=----ATTACHMENT:----NjA0OTUwMjgyMzM1NjE4MiA0NjA2MDAwNDA0MDE1MjcxIDkyNjIwNTc5Mzk0ODIyNTQ=