Skip to content

Commit

Permalink
Refactor remaining Importers.
Browse files Browse the repository at this point in the history
  • Loading branch information
drupol committed Mar 7, 2020
1 parent 2096a62 commit 77eb6b9
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 60 deletions.
57 changes: 31 additions & 26 deletions src/Importer/SimpleArray.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,56 +4,61 @@

namespace loophp\phptree\Importer;

use loophp\phptree\Node\AttributeNode;
use loophp\phptree\Node\AttributeNodeInterface;
use loophp\phptree\Node\NodeInterface;
use loophp\phptree\Node\ValueNode;

/**
* Class SimpleArray.
*/
class SimpleArray implements ImporterInterface
final class SimpleArray implements ImporterInterface
{
/**
* {@inheritdoc}
*/
public function import($data): NodeInterface
{
return $this->arrayToTree($data);
return $this->parseNode(new AttributeNode(['label' => 'root']), $data);
}

/**
* Convert an array into a tree.
* Create a node.
*
* @param array<string, mixed> $data
* @param mixed $data
* The arguments
*
* @return \loophp\phptree\Node\NodeInterface
* The tree
* @return \loophp\phptree\Node\AttributeNodeInterface
* The node
*/
protected function arrayToTree(array $data): NodeInterface
private function createNode($data): AttributeNodeInterface
{
$data += [
'children' => [],
];

$node = $this->createNode($data['value']);

foreach ($data['children'] as $child) {
$node->add($this->arrayToTree($child));
}

return $node;
return new AttributeNode([
'data' => $data,
]);
}

/**
* Create a node.
*
* @param mixed $data
* The arguments
* @param \loophp\phptree\Node\AttributeNodeInterface $parent
* @param array ...$nodes
*
* @return \loophp\phptree\Node\NodeInterface
* The node
*/
protected function createNode($data): NodeInterface
private function parseNode(AttributeNodeInterface $parent, array ...$nodes): NodeInterface
{
return new ValueNode($data);
return array_reduce(
$nodes,
function (AttributeNodeInterface $carry, array $node): NodeInterface {
$node += ['children' => []];

return $carry
->add(
$this->parseNode(
$this->createNode($node),
...$node['children']
)
);
},
$parent
);
}
}
85 changes: 51 additions & 34 deletions src/Importer/Text.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,41 +4,37 @@

namespace loophp\phptree\Importer;

use InvalidArgumentException;
use loophp\phptree\Node\AttributeNode;
use loophp\phptree\Node\AttributeNodeInterface;
use loophp\phptree\Node\NodeInterface;
use loophp\phptree\Node\ValueNode;

/**
* Class Text.
*/
class Text extends SimpleArray
final class Text implements ImporterInterface
{
/**
* {@inheritdoc}
*/
public function import($data): NodeInterface
{
$parsed = $this->parse($data);

if ([] === $parsed) {
throw new InvalidArgumentException('Unable to import the given data.');
}

return $this->arrayToTree($parsed[0]);
return $this->parseNode(new AttributeNode(['label' => 'root']), $data);
}

/**
* Create a node.
*
* @param mixed $arguments
* The arguments
* @param string $label
* The node label
*
* @return \loophp\phptree\Node\NodeInterface
* @return \loophp\phptree\Node\AttributeNodeInterface
* The node
*/
protected function createNode($arguments): NodeInterface
private function createNode(string $label): AttributeNodeInterface
{
return new ValueNode($arguments);
return new AttributeNode([
'label' => $label,
]);
}

/**
Expand All @@ -47,34 +43,55 @@ protected function createNode($arguments): NodeInterface
* @param string $subject
* The subject string
*
* @return array<int, mixed>
* @return array<string, mixed>
* The array
*/
private function parse(string $subject): array
{
$result = [];
$result = [
'value' => mb_substr($subject, 1, mb_strpos($subject, '[', 1) - 1),
'children' => [],
];

preg_match_all('~[^\[\]]+|\[(?<nested>(?R)*)\]~', $subject, $matches);

$matches = (array) $matches['nested'];
if (false === $nextBracket = mb_strpos($subject, '[', 1)) {
return $result;
}

foreach (array_filter($matches) as $match) {
$item = [];
$position = mb_strpos($match, '[');
// Todo: Improve the regex.
preg_match_all('~[^\[\]]+|\[(?<nested>(?R)*)]~', mb_substr($subject, $nextBracket, -1), $matches);

if (false !== $position) {
$item['value'] = mb_substr($match, 0, $position);
} else {
$item['value'] = $match;
}
$result['children'] = array_map(
static function (string $match): string {
return sprintf('[%s]', $match);
},
array_filter((array) $matches['nested'])
);

if ([] !== $children = $this->parse($match)) {
$item['children'] = $children;
}
return $result;
}

$result[] = $item;
}
/**
* @param \loophp\phptree\Node\AttributeNodeInterface $parent
* @param string ...$nodes
*
* @return \loophp\phptree\Node\NodeInterface
*/
private function parseNode(AttributeNodeInterface $parent, string ...$nodes): NodeInterface
{
return array_reduce(
$nodes,
function (AttributeNodeInterface $carry, string $node): NodeInterface {
$data = $this->parse($node);

return $result;
return $carry
->add(
$this->parseNode(
$this->createNode($data['value']),
...$data['children']
)
);
},
$parent
);
}
}

0 comments on commit 77eb6b9

Please sign in to comment.