СНИППЕТ

Файловый менеджер для wordpress

<?php
function simple_file_manager_menu() {
    add_menu_page(
        'Файловый менеджер', // Название страницы
        'Файловый менеджер', // Название меню
        'manage_options', // Уровень доступа
        'simple-file-manager', // Уникальный идентификатор
        'simple_file_manager_page' // Функция, которая выводит содержимое страницы
    );
}
add_action('admin_menu', 'simple_file_manager_menu');

// Регистрация виджета
function simple_file_manager_widget() {
    wp_add_dashboard_widget(
        'simple_file_manager_widget', // Уникальный идентификатор
        'Файловый менеджер', // Название виджета
        'simple_file_manager_widget_display' // Функция, которая выводит содержимое виджета
    );
}
add_action('wp_dashboard_setup', 'simple_file_manager_widget');

function simple_file_manager_page() {
$total_space_mb = disk_total_space("/") / 1048576; // Общее место в МБ
$used_space_mb = ($total_space_mb - (disk_free_space("/") / 1048576)); // Занятое место в МБ
$used_space_percent = ($used_space_mb / $total_space_mb) * 100; // Заполненность в %
$free_space_mb = disk_free_space("/") / 1048576; // Свободное место в МБ


    ?>
    <div class="wrap">
        <h1>Файловый менеджер</h1>
        <div style="margin-bottom: 20px;">
<div style="margin-bottom: 20px;">
    <div style="background-color: #e0e0e0; border-radius: 3px; overflow: hidden;">
        <div style="width: <?php echo $used_space_percent; ?>%; background-color: #76c7c0; height: 20px; text-align: center; color: white;">
           <?php echo round($used_space_mb, 2) . ' МБ из ' . round($total_space_mb, 2) . ' МБ (осталось: ' . round($free_space_mb, 2) . ' МБ)'; ?>
        </div>
    </div>
</div>	
		
            <button id="back-button" style="display:none;">Назад</button>
            <button id="root-button">В корень</button>
        </div>
        <table id="file-manager" style="width:100%; border-collapse: collapse;">
            <thead>
                <tr>
                    <th onclick="sortFiles('name')">Имя файла <span id="name-sort-icon"></span></th>
                    <th onclick="sortFiles('size')">Размер <span id="size-sort-icon"></span></th>
                    <th onclick="sortFiles('date')">Дата создания <span id="date-sort-icon"></span></th>
                </tr>
            </thead>
            <tbody></tbody>
        </table>
    </div>
    <script>
        let currentPath = '';
        let filesData = [];
        let currentSortKey = '';
        let currentSortOrder = 'asc'; // 'asc' или 'desc'
        
        document.getElementById('root-button').addEventListener('click', () => {
            currentPath = '';
            fetchFiles();
        });

        document.getElementById('back-button').addEventListener('click', () => {
            const pathParts = currentPath.split('/').filter(part => part);
            pathParts.pop(); // Удаляем последний элемент
            currentPath = pathParts.join('/') + '/';
            fetchFiles();
        });

        async function fetchFiles() {
            const response = await fetch(`<?php echo admin_url('admin-ajax.php'); ?>?action=get_files&path=${encodeURIComponent(currentPath)}`);
            filesData = await response.json();
            renderFiles();
        }

        function renderFiles() {
            const tbody = document.querySelector('#file-manager tbody');
            tbody.innerHTML = '';

            for (const item of filesData) {
                const tr = document.createElement('tr');
                const nameCell = document.createElement('td');
                const sizeCell = document.createElement('td');
                const dateCell = document.createElement('td');

                if (item.isDirectory) {
                    nameCell.innerHTML = `<a href="#" onclick="navigateTo('${currentPath}${item.name}/'); return false;">${item.name}/</a>`;
                } else {
                    nameCell.textContent = item.name;
                }
                sizeCell.textContent = item.size;
                dateCell.textContent = item.date;

                tr.appendChild(nameCell);
                tr.appendChild(sizeCell);
                tr.appendChild(dateCell);
                tbody.appendChild(tr);
            }

            document.getElementById('back-button').style.display = currentPath ? 'block' : 'none';
        }

        function navigateTo(path) {
            currentPath = path;
            fetchFiles();
        }

        function sortFiles(key) {
            if (currentSortKey === key) {
                currentSortOrder = currentSortOrder === 'asc' ? 'desc' : 'asc';
            } else {
                currentSortOrder = 'asc';
            }
            currentSortKey = key;
            
            filesData.sort((a, b) => {
                if (key === 'name') {
                    return currentSortOrder === 'asc' ? a.name.localeCompare(b.name) : b.name.localeCompare(a.name);
                } else if (key === 'size') {
                    return currentSortOrder === 'asc' ? a.size - b.size : b.size - a.size;
                } else if (key === 'date') {
                    return currentSortOrder === 'asc' ? new Date(a.date) - new Date(b.date) : new Date(b.date) - new Date(a.date);
                }
            });
            updateSortIcons();
            renderFiles();
        }

        function updateSortIcons() {
            document.getElementById('name-sort-icon').textContent = currentSortKey === 'name' ? (currentSortOrder === 'asc' ? '↑' : '↓') : '';
            document.getElementById('size-sort-icon').textContent = currentSortKey === 'size' ? (currentSortOrder === 'asc' ? '↑' : '↓') : '';
            document.getElementById('date-sort-icon').textContent = currentSortKey === 'date' ? (currentSortOrder === 'asc' ? '↑' : '↓') : '';
        }

        // Начинаем с корневого каталога
        fetchFiles();
    </script>
    <style>
        #file-manager th {
            cursor: pointer;
            background-color: #f1f1f1;
            border-bottom: 2px solid #ccc;
            padding: 10px;
        }
        #file-manager td {
            padding: 10px;
            border-bottom: 1px solid #eaeaea;
        }
        #file-manager tr:hover {
            background-color: #f9f9f9;
        }
        #back-button, #root-button {
            margin-right: 10px;
            padding: 5px 10px;
        }
    </style>
    <?php
}

function simple_file_manager_widget_display() {
$total_space_mb = disk_total_space("/") / 1048576; // Общее место в МБ
$used_space_mb = ($total_space_mb - (disk_free_space("/") / 1048576)); // Занятое место в МБ
$used_space_percent = ($used_space_mb / $total_space_mb) * 100; // Заполненность в %
$free_space_mb = disk_free_space("/") / 1048576; // Свободное место в МБ

    ?>
    <div id="file-manager-widget" style="overflow-y: auto; max-height: 400px;">
<div style="margin-bottom: 20px;">
    <div style="background-color: #e0e0e0; border-radius: 3px; overflow: hidden;">
        <div style="width: <?php echo $used_space_percent; ?>%; background-color: #76c7c0; height: 20px; text-align: center; color: white;">
            <?php echo round($used_space_mb, 2) . ' МБ из ' . round($total_space_mb, 2) . ' МБ (осталось: ' . round($free_space_mb, 2) . ' МБ)'; ?>
        </div>
    </div>
</div>	


        <button id="back-button" style="display:none;">Назад</button>
        <button id="root-button">В корень</button>
        <table id="file-manager" style="width:100%; border-collapse: collapse;">
            <thead>
                <tr>
                    <th onclick="sortFiles('name')">Имя файла <span id="name-sort-icon"></span></th>
                    <th onclick="sortFiles('size')">Размер <span id="size-sort-icon"></span></th>
                    <th onclick="sortFiles('date')">Дата создания <span id="date-sort-icon"></span></th>
                </tr>
            </thead>
            <tbody></tbody>
        </table>
    </div>
    <script>
        let currentPath = '';
        let filesData = [];
        let currentSortKey = '';
        let currentSortOrder = 'asc'; // 'asc' или 'desc'

        document.getElementById('root-button').addEventListener('click', () => {
            currentPath = '';
            fetchFiles();
        });

        document.getElementById('back-button').addEventListener('click', () => {
            const pathParts = currentPath.split('/').filter(part => part);
            pathParts.pop(); // Удаляем последний элемент
            currentPath = pathParts.join('/') + '/';
            fetchFiles();
        });

        async function fetchFiles() {
            const response = await fetch(`<?php echo admin_url('admin-ajax.php'); ?>?action=get_files&path=${encodeURIComponent(currentPath)}`);
            filesData = await response.json();
            renderFiles();
        }

        function renderFiles() {
            const tbody = document.querySelector('#file-manager tbody');
            tbody.innerHTML = '';

            for (const item of filesData) {
                const tr = document.createElement('tr');
                const nameCell = document.createElement('td');
                const sizeCell = document.createElement('td');
                const dateCell = document.createElement('td');

                if (item.isDirectory) {
                    nameCell.innerHTML = `<a href="#" onclick="navigateTo('${currentPath}${item.name}/'); return false;">${item.name}/</a>`;
                } else {
                    nameCell.textContent = item.name;
                }
                sizeCell.textContent = item.size;
                dateCell.textContent = item.date;

                tr.appendChild(nameCell);
                tr.appendChild(sizeCell);
                tr.appendChild(dateCell);
                tbody.appendChild(tr);
            }

            document.getElementById('back-button').style.display = currentPath ? 'block' : 'none';
        }

        function navigateTo(path) {
            currentPath = path;
            fetchFiles();
        }

        function sortFiles(key) {
            if (currentSortKey === key) {
                currentSortOrder = currentSortOrder === 'asc' ? 'desc' : 'asc';
            } else {
                currentSortOrder = 'asc';
            }
            currentSortKey = key;
            
            filesData.sort((a, b) => {
                if (key === 'name') {
                    return currentSortOrder === 'asc' ? a.name.localeCompare(b.name) : b.name.localeCompare(a.name);
                } else if (key === 'size') {
                    return currentSortOrder === 'asc' ? a.size - b.size : b.size - a.size;
                } else if (key === 'date') {
                    return currentSortOrder === 'asc' ? new Date(a.date) - new Date(b.date) : new Date(b.date) - new Date(a.date);
                }
            });
            updateSortIcons();
            renderFiles();
        }

        function updateSortIcons() {
            document.getElementById('name-sort-icon').textContent = currentSortKey === 'name' ? (currentSortOrder === 'asc' ? '↑' : '↓') : '';
            document.getElementById('size-sort-icon').textContent = currentSortKey === 'size' ? (currentSortOrder === 'asc' ? '↑' : '↓') : '';
            document.getElementById('date-sort-icon').textContent = currentSortKey === 'date' ? (currentSortOrder === 'asc' ? '↑' : '↓') : '';
        }

        // Начинаем с корневого каталога
        fetchFiles();
    </script>
    <style>
        #file-manager th {
            cursor: pointer;
            background-color: #f1f1f1;
            border-bottom: 2px solid #ccc;
            padding: 10px;
        }
        #file-manager td {
            padding: 10px;
            border-bottom: 1px solid #eaeaea;
        }
        #file-manager tr:hover {
            background-color: #f9f9f9;
        }
        #back-button, #root-button {
            margin-right: 10px;
            padding: 5px 10px;
            margin-bottom: 10px;
        }
    </style>
    <?php
}

function get_files() {
    $path = isset($_GET['path']) ? $_GET['path'] : '';
    $fullPath = ABSPATH . $path; // Путь к директории

    if (!is_dir($fullPath)) {
        wp_send_json_error('Директория не найдена');
        return;
    }

    $files = array();
    $dir = opendir($fullPath);
    
    while (($file = readdir($dir)) !== false) {
        if ($file != '.' && $file != '..') {
            $filePath = $fullPath . '/' . $file;
            $size = is_dir($filePath) ? get_directory_size($filePath) : filesize($filePath);
            $date = date("Y-m-d H:i:s", filemtime($filePath));
            $files[] = array(
                'name' => $file,
                'size' => formatSize($size),
                'date' => $date,
                'isDirectory' => is_dir($filePath)
            );
        }
    }
    closedir($dir);
    
    wp_send_json($files);
}

function get_directory_size($dir) {
    $size = 0;
    $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir));

    foreach ($files as $file) {
        if ($file->isFile()) {
            $size += $file->getSize();
        }
    }

    return $size;
}

function formatSize($size) {
    if ($size < 1024) return $size . ' Б';
    if ($size < 1048576) return round($size / 1024, 2) . ' КБ';
    if ($size < 1073741824) return round($size / 1048576, 2) . ' МБ';
    return round($size / 1073741824, 2) . ' ГБ';
}

add_action('wp_ajax_get_files', 'get_files');

?>