*
*
* 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=