Можливість запису в локальні файли сайту на WordPress є однією з функцій, яка потрібна багатьом плагінам та темам для різних цілей. Безпека – це найбільш важливе питання для плагінів, а теми повинні піклуватися про це під час запису в локальні файлові системи.
WordPress працює на різних хостингах, тому для розробників стає важко створювати плагіни та теми, які б мали доступ до локальних файлових систем для роботи в різних умовах без шкоди для безпеки.
Дивіться також:
- WordPress File Monitor — дізнайтеся, чи файли змінювалися на вашому сайті
- Порядок завантаження файлів WordPress теми
- Куди вставляти цей код у WordPress? Загальна структура файлів теми
- Додаємо файловий менеджер із підтримкою FTP на ваш WordPress-сайт
- Як у WordPress-записі вивести список усіх доданих файлів
У цьому уроці ми дізнаємось, як використовувати WordPress Filesystem API для доступу до локальної файлової системи, яка дбає про правильне право доступу до файлів. У процесі ми створимо плагін, який виводить форму з текстом на сторінці адміністратора, яка зберігатиме цей текст у текстовий файл.
Навіщо використовувати WordPress Filesystem API?
Ви можете поцікавитися, чому нам просто не використовувати функції PHP файлової системи для читання і запису локальних файлів, а не починати вивчати і використовувати абсолютно новий набір API?
Проблема використання API файлової системи PHP полягає в тому, що вона не дбає про права доступу до файлів автоматично. Припустимо, ви використовуєте shared хостинг для розміщення вашого WordPress сайту, і ваш веб-сервер працює як "адмін" операційної системи. Тому щоразу, коли ви створюєте файли, використовуючи PHP, вони належать "адміністраторам".
Таким чином, будь-який інший веб-сайт, який розміщений у тому ж хостингу, може також отримати доступ до файлів сайту, оскільки він також працює як "адміністратор", що створить проблеми безпеки на вашому сайті. Щоб захистити нас від цієї проблеми, необхідно змінити власників файлу та права доступу вручну за допомогою PHP.
Але коли ви входите, використовуючи SSH або FTP/SFTP для створення файлів, то вони прикріплюються до облікового запису користувача операційної системи, під якою він увійшов до системи. Якщо FTP-сервер працює як користувач Admin , а ви увійшли в систему як користувач User, то нові файли будуть мати власника User, а не Admin.
WordPress представив Filesystem API, яка може автоматично дбати про права доступу до файлів. Filesystem API була випущена ще у версії WordPress 2.6. WordPress насправді випустили її для підтримки своїх плагінів, тем і основних оновлень системи, але наступні плагіни та теми почали використовувати її вже для своїх власних цілей.
Як працює файлова система API?
API файлової системи може робити записи у файлах, використовуючи системні дзвінки (тобто direct, ftp, ftp socket, ssh2). Файлова система вибирає один із методів, ґрунтуючись на тому, який з представлених методів має відповідний допуск, і яке PHP розширення доступне. API файлової системи спочатку перевіряє метод direct, потім ftp та, нарешті, ssh2.
При використанні FTP або SSH ви повинні отримати облікові дані вашого користувача. API файлова система надає спеціальні функції, які полегшать цей процес виведення на екран спеціальної форми для отримання та зберігання даних.
Створення плагіна для роботи з файлами
Тепер давайте створимо наш плагін, який відображатиме текст на сторінці, і при заповненні форми зберігатиме її вміст у локальний файл.
Ось структура директорії нашого плагіна:
--filesystem --filesystem.php --filesystem-demo --demo.txt
Створіть ці файли в директорії wp-content/plugins вашого сайту WordPress.
Для того, щоб зробити плагін встановлюваним, вставте цей код у файл файлова система.php:
<?php /* Plugin Name: Filesystem API Plugin URI: http://www.sitepoint.com Description: A sample plugin to demonstrate Filesystem API Version: 1.0 Author: Narayan Prusty */
Тепер перейдіть в панель адміністратора та активуйте плагін.
Створення сторінки керування плагіном
Далі нам знадобиться сторінка на панелі адміністратора, де наш приклад буде розміщений. Нижче наведено код для створення цієї сторінки та відображення тексту. Просто скопіюйте цей код у файл файлова система.php:
function menu_item() { add_submenu_page("options-general.php", "Demo", "Demo", "manage_options", "demo", "demo_page"); } add_action("admin_menu", "menu_item"); function demo_page() { ?> <div class="wrap"> <h1>Demo</h1> <form method="post"> <?php $output = ""; if(isset($_POST["file-data"])) { $output = write_file_demo($_POST["file-data"]); } else { $output = read_file_demo(); } if(!is_wp_error($output)) { ?> <textarea name="file-data"><?php echo $output; ?></textarea> <?php wp_nonce_field("filesystem-nonce"); ?> <br> <input type="submit"> <?php } else { echo $output->get_error_message(); } ?> </form> </div> <?php }
Пояснимо, як цей код працює:
- Спершу ми додали сторінку в меню "Налаштування". demo_page є колббеком для відображення вмісту сторінки.
- Усередині сторінки ми розмістимо HTML-форму з областю тексту. Там також є кнопка представляти для надсилання форми. Текстове поле називається file-data. Поле нунцій було додано для запобігання атаки CSRF.
- Коли сторінку відкрито, ми повертаємо збережену інформацію з файлів за допомогою функції read_file_demo. При надсиланні форми ми зберігаємо вміст текстового поля у файл за допомогою функції write_file_demo.
- Якщо read_file_demo або write_file_demo повертає екземпляр об'єкту WP_Error, на екрані з'явиться повідомлення про помилку.
Зверніть увагу, що цей код "поламає" ваш WordPress сайт, оскільки ми ще не створили функції read_file_demo и write_file_demo. Тому давайте створимо їх прямо зараз!
Запис у файл
Нижче представлено реалізацію нашої функції write_file_demo:
function connect_fs($url, $method, $context, $fields = null) { global $wp_filesystem; if(false === ($credentials = request_filesystem_credentials($url, $method, false, $context, $fields))) { return false; } //check if credentials are correct or not. if(!WP_Filesystem($credentials)) { request_filesystem_credentials($url, $method, true, $context); return false; } return true; } function write_file_demo($text) { global $wp_filesystem; $url = wp_nonce_url("options-general.php?page=demo", "filesystem-nonce"); $form_fields = array("file-data"); if(connect_fs($url, "", WP_PLUGIN_DIR . "/filesystem/filesystem-demo", $form_fields)) { $dir = $wp_filesystem->find_folder(WP_PLUGIN_DIR . "/filesystem/filesystem-demo"); $file = trailingslashit($dir) . "demo.txt"; $wp_filesystem->put_contents($file, $text, FS_CHMOD_FILE); return $text; } else { return new WP_Error("filesystem_error", "Cannot initialize filesystem"); } }
Ось як цей код працює:
- Спочатку ми посилаємося на глобальний об'єкт $wp_filesystem усередині функції. Цей об'єкт є екземпляром класу WP_Filesystem. Він відповідає за вилучення різних методів для читання, створення, написання та видалення файлів.
- Далі, ми створюємо URL nonce для сторінки нашої форми і масив з полем імен з нашої форми.
- Нарешті ми приєднуємося до файлової системи, використовуючи функцію connect_fs.
- connect_fs використовує функцію request_filesystem_credentials, надану WordPress, щоб знайти відповідний спосіб підключення до файлової системи (direct, FTP або SSH). У разі FTP або SSH буде виконано звернення до форми, щоб задати облікові дані користувача. У разі прямого (direct) методу він просто повертає значення правда.
- Коли форма TextArea представлена та request_filesystem_credentials вибирає метод FTP або SSH, ми виводимо форму з обліковими даними та приховуємо інформацію з поля файлу даних.
- Перший параметр функції request_filesystem_credentials приймає URL-адресу, куди слід перенаправити користувача, як тільки він отримав правильні облікові дані. Редирект є типом запиту POST. Request_filesystem_credentials — останній параметр, який є масивом поля імен до запису, який надсилають по URL.
- Як тільки форма з обліковими даними заповнена, вона перенаправляється назад до початкової форми, надаючи URL-адресу з належними полями імен та значеннями, які були введені користувачем.
- Весь процес знову починається і ми запускаємо write_file_demo. Цього разу request_filesystem_credentials має необхідні повноваження, отже, він просто поверне значення правда.
- Потім ми використовуємо $wp_filesystem->find_folderде ми посилаємося на необхідну папку. Після цього ми будуємо повний шлях до файлу demo.txt.
- Ми використали $wp_filesystem-> put_contents для запису даних у файл.
Примітка: Якщо ви спробуєте використовувати методи об'єкта $wp_filesystem без запиту та підтвердження облікових даних, то вони не працюватимуть.
Читання файлу
Нижче розміщена реалізація функції read_file_demo:
function read_file_demo() { global $wp_filesystem; $url = wp_nonce_url("options-general.php?page=demo", "filesystem-nonce"); if(connect_fs($url, "", WP_PLUGIN_DIR . "/filesystem/filesystem-demo")) { $dir = $wp_filesystem->find_folder(WP_PLUGIN_DIR . "/filesystem/filesystem-demo"); $file = trailingslashit($dir) . "demo.txt"; if($wp_filesystem->exists($file)) { $text = $wp_filesystem->get_contents($file); if(!$text) { return ""; } else { return $text; } } else { return new WP_Error("filesystem_error", "File doesn't exist"); } } else { return new WP_Error("filesystem_error", "Cannot initialize filesystem"); } }
Опис того, як цей код каботає:
- У той час як відбуватиметься читання файлу demo.txt, ми підключаємося до файлової системи, використовуючи функцію request_filesystem_credentials.
- На цей раз ми не будемо проходити жодну форму поля в останньому параметрі, тому що форма не представлена. Ми просто пропустимо переадресацію URL, так що вона відбулася, як тільки облікові дані будуть вилучені.
- Після цього ми перевіримо, чи існує файл, використовуючи функцію $wp_filesystem->exists. Якщо файл не існує, на екрані з'явиться повідомлення про помилку. Інакше ми вважаємо файл за допомогою функції $wp_filesystem->get_contents і повернемо вміст.
Припускаючи, що WordPress вибрав FTP як підходящий спосіб створення файлів, ми прикріплюємо скріншоти всього процесу.
Спочатку, коли ми відкриваємо демо-сторінку, ми маємо побачити цю форму:
Тут ми повинні запровадити повноваження FTP або FTPS і підтвердити. Після того, як ми підтверджуємо дію, побачимо цю форму:
На екрані було виведено порожнє поле для тексту. Введіть тудиHello World!" і надішліть форму. Ви знову побачите форму для облікових даних.
Ви повинні ще раз заповнити її, тому що WordPress не зберігає пароль FTP за промовчанням (ви можете зробити це в WP-config.php, Але про це пізніше). Таким чином, щоразу, коли ваш плагін повинен працювати з файловою системою, вона має запитувати дані. Тепер підтвердження цього перенаправить назад на URL із полями імен та значень, представлених раніше. Ось як виглядатиме текстове поле:
Тут ми зчитуємо вміст із файлу та виводимо його.
Інші методи об'єкту $wp_filesystem
Об'єкт $wp_filesystem надає безліч інших методів для виконання різних операцій з файлами і директоріями. Ми тільки-но бачили операції запису та читання файлу. Ви можете знайти повний Список функцій WP_Filesystem_Base () на сторінці документації.
Давайте розглянемо кілька важливих із них:
- $wp_filesystem->delete: використовується для видалення файлу або директорії. Вам необхідно вибрати рядок, позначивши шлях до нього.
- $wp_filesystem->mkdir: використовується для створення директорії Береться рядок, який представлятиме батьківську директорію.
- $wp_filesystem->move: використовується для переміщення файлу. Береться два параметри: перший шлях до файлу і другий директорія, в яку його необхідно перемістити.
- $wp_filesystem->size: повертає розмір файлу в байтах Вам необхідно пройти шлях до файлу.
- $wp_filesystem->chmod: використовується для зміни прав доступу до файлу. Використовується три аргументи: шлях до файлу, дозвіл (вісімкове число) та булеві змінні для рекурсії.
Ви можете з'ясувати, який метод зв'язку використовує WordPress для доступу до файлової системи, використовуючи публічний метод $wp_filesystem->method.
Постійне зберігання облікових даних
Ви вже встигли помітити, що WordPress не зберігає повноважень доступу FTP або SSH на постійній основі. Це не дуже зручно, звертатися до користувача знову та знову за необхідною інформацією. Тому існує спосіб зберігання даних на постійній основі, використовуючи файл WP-config.php.
Використовуйте ці параметри для зберігання повноважень FTP та SSH:
- FTP_HOST: ім'я хостингу сервера
- FTP_USER: ім'я користувача для використання під час підключення
- FTP_PASS: пароль для використання при підключенні
- FTP_PUBKEY: шлях до публічного ключа, який використовуватиметься при з'єднанні SSH2
- FTP_PRIKEY: шлях до приватного ключа, який використовуватиметься при з'єднанні SSH2
Висновок
У цій статті ми побачили процес створення плагіна, який має доступ до нашої файлової системи, використовуючи WordPress Filesystem API. У випадку, якщо ви спробуєте отримати доступ до файлової системи у фоновому режимі (наприклад, за допомогою cron job), неможливо буде відобразити облікові дані, тому не забудьте повідомити користувача, щоб він зробив облікові дані константними у файлі WP-config.php. Рухайтеся далі, розвивайтеся, експериментуйте з цим API та обов'язково ділитесь своїм досвідом з нами нижче.
Коментарі до запису: 1
Не виходить запустити API з functions.php моєї теми.
якщо писати
if ( ! WP_Filesystem($creds) ) {
request_filesystem_credentials($url, '', true, false, null);
return;
}
то просто отримую помилку
[22-Apr-2016 07:34:48 UTC] PHP Fatal error: Call для undefined функцію WP_Filesystem() in …