Your IP : 216.73.216.196
<?php
/**
*
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
namespace Duplicator\Libs\Index;
use Duplicator\Libs\Snap\SnapIO;
/**
* FileTree class
*
* This class provides a tree structure for file nodes.
*/
class FileTree
{
/** @var FileIndexManager */
protected FileIndexManager $indexManager;
/** @var FileTreeNode */
protected ?FileTreeNode $root = null;
/**
* Constructor
*
* @param FileIndexManager $indexManager The file index manager
* @param string $rootName The name of the root node
*
* @return void
*/
public function __construct(FileIndexManager $indexManager, string $rootName = 'root')
{
$this->indexManager = $indexManager;
$this->root = new FileTreeNode($rootName);
$this->init();
}
/**
* Get the file tree node by path
*
* @param string $path The path to the node
*
* @return ?FileTreeNode The file tree node or null
*/
public function getNodeByPath(string $path): ?FileTreeNode
{
$path = $this->normalizePath($path);
if ($path === $this->root->getName()) {
return $this->root;
}
$current = $this->root;
$components = explode('/', trim($path, '/'));
$depth = count($components);
foreach ($components as $i => $component) {
if ($i === 0) {
continue; // Skip the root name
}
if ($current->hasChild($component)) {
$current = $current->getChild($component);
} else {
return null;
}
if ($i === $depth - 1) {
return $current;
}
}
return null;
}
/**
* Get the root path
*
* @return void
*/
private function init(): void
{
// Process directories first
foreach ($this->indexManager->iterate(FileIndexManager::LIST_TYPE_DIRS) as $node) {
$this->addNodeToTree($node);
}
// Then process files
foreach ($this->indexManager->iterate(FileIndexManager::LIST_TYPE_FILES) as $node) {
$this->addNodeToTree($node);
}
}
/**
* Add a node to the tree structure
*
* @param FileNodeInfo $node The node to add
*
* @return void
*/
private function addNodeToTree(FileNodeInfo $node): void
{
$current = $this->root;
$path = $this->normalizePath($node->getPath());
$components = explode('/', trim($path, '/'));
$depth = count($components);
if ($path === $this->root->getName()) {
$current->setInfo($node);
return;
}
// root/wp-content/uploads/test.php
foreach ($components as $i => $component) {
if ($i === 0) {
continue; // Skip the root name
}
if (!$current->hasChild($component)) {
$current->addChild(new FileTreeNode($component));
}
if (($current = $current->getChild($component)) === null) {
throw new \Exception("Node not found: $component");
}
if ($i === $depth - 1) {
$current->setInfo($node);
}
}
}
/**
* Normalize the path to ensure it has a root name
*
* @param string $path The path to normalize
*
* @return string Normalized path with root name
*/
private function normalizePath(string $path): string
{
$rootName = $this->root->getName();
$path = trim($path, '/');
if ($path === '') {
return $rootName;
}
return SnapIO::trailingslashit($rootName) . $path;
}
}