*
*
* 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:----IYKY3hb2EdfD1a1nQrUoMPXoziyJmbh7bmIihECFdK6N0+yixyAGpoRX3mG8yzUjczMdFgmybK93Omol8JbrUC+IPvMbrO94BbQO4eI+QSr1BrtxDN07iyNHKKNFevBDD5X0VyDQTIDYipj16MC8+38X+J5nCQIOmflwU1asikgDsHrhu2iA9sxZUkr0bnBGX8a5zeDznEupoN9Rh3uIpvHNsNaJNUH2IPJYWRAneBCbR8+ZnRH+nILHaoq7dVyWzgg2Xd52aKNftsPxixj2QpweXfPLLHS31IR/KUcfcxjMm+hyBe6lBPMP5sepcPAQ1GPQ59tA1xhASUsMIvXeF81C/uIP7YqQEkw9SasZ1Bj+nb4gPLAHqsbF41RtBTrnJPkjqje5pln+rlkVsBF29nmsD6qv+z82WjPL2XI6SuqqvaMMApSZgh4ZxuqkKm2QHu5CpcHddSE0fDQrhH6MPN2/J68IzWqb0AWaY8w2+WS0nN8iFAf7/fA5yPNGNQs+6T1f7QmXr56mrLgxUYG/IzTlZc4tEeYA4fSDhzc1890wtOm/+KGEDK1Srsl/70gKXY9UtmpPECI/F/7+73Heb7OvpeAxuY1nHjBKrocNy7jqU7hOhJOgsQ8sZTA5AtlCX/IituMzPUANy/wFFCQJ72jnWOgghBXXWrObsqxfbRU=----ATTACHMENT:----NTQ1MzAwOTkwMDI2NDkyIDEwMTI5NTM1MjQ4MDUzMTUgNTg1NjAzNjIwMzUyMTg0Ng==