I’ve been working on a WordPress plugin to retrieve a directory structure from my server and display it in a webpage. I have a working demo, but there is an issue that I don’t understand.
I construct the data structure in the backend as an array, each item containing its name, relative path, type (file or folder) and children if it is a folder. The items in the base folder appear with incorrect paths when I print them in the console, but their children items are correct.
The project is much larger, but I tried to simplify and show the relevant code. This is the backend function that retreives the data structure:
function list_items($base, $current_path = '') {
$base_path = PWR_FILE_REPOSITORY_PATH . $base; /** Absolute path to base folder */
$full_path = $base_path . $current_path; /** Absolute path to current folder */
$items = [];
if (is_dir($full_path)) {
$files = scandir($full_path);
foreach ($files as $file) {
if ($file === '.' || $file === '..') continue;
$full_item_path = trailingslashit($full_path) . $file; /** Absolute path to file*/
$item_path = ltrim(str_replace($base_path, '', $full_item_path), '/\');/** Relative path to file from the base path */
$item = [
'name' => $file,
'path' => $item_path,
'type' => is_dir($full_item_path) ? 'folder' : 'file',
];
if ($item['type'] === 'folder') {
$item['children'] = self::list_items($base, $item_path . '/');
}
$items[] = $item;
}
}
return $items;
}
$base
is the base folder for each user and should not appear in the item’s path. $current_path
is initially empty because I’m retreiving the base folder. There is an intermediate function that acts as request handler, and I made sure that all paths are correct:
$directories = self::list_items($base_path, $path);
foreach ($directories as $item) {
error_log(print_r($item, true));
}
wp_send_json_success(['directories' => $directories]);
Example log (this is correct):
Array
(
[name] => folder1
[path] => folder1
[type] => folder
[children] => Array
(
[0] => Array
(
[name] => subfolder1_1
[path] => folder1/subfolder1_1
[type] => folder
[children] => Array
(
[0] => Array
(
[name] => file.txt
[path] => folder1/subfolder1_1/file.txt
[type] => file
)
)
)
)
)
Console (this is not correct):
```
fetchDirectoryStructure().then(data => {
console.log(data);
/** More code here */
});
Array(n) [ {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, … ]
0: Object { name: "folder1", path: "base_folder1/folder1", type: "folder", … }
children: Array(m) [ {…}, {…}, {…}, … ]
0: Object { name: "subfolder1_1", path: "folder1/subfolder1_1", type: "folder", … }
children: Array [ {…} ]
0: Object { name: "file.txt", path: "folder1/subfolder1_1/file.txt", type: "file" }
...
As you can see, there’s a discrepancy between the path sent (‘folder1’) and the path received (‘base_folder1/folder1’) and I don’t understand why does it happen, because I don’t modify the structure at any point. I’ll write down the fetch too if its helpful.
async function fetchDirectoryStructure(path = '') {
const response = await fetch(pwrFileRepoAjax.ajaxurl, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: `action=get_directory_structure&base_path=${pathManager.getBasePath()}&path=${path}&nonce=${encodeURIComponent(pwrFileRepoAjax.nonce)}`,
});
if (!response.ok) {
console.error('AJAX request failed:', response.status, response.statusText);
throw new Error('AJAX request failed');
}
const data = await response.json();
if (!data.success) {
console.error('Error in AJAX response:', data);
throw new Error('Error in AJAX response');
}
return data.data.directories;
}